зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1912131 - Update minidump-writer to 0.10.1 r=gsvelto,glandium,supply-chain-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D221977
This commit is contained in:
Родитель
873bc3fb65
Коммит
6a6dafeb0e
|
@ -594,7 +594,7 @@ dependencies = [
|
|||
name = "buildid_reader"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"goblin 0.8.1",
|
||||
"goblin 0.8.2",
|
||||
"libc",
|
||||
"log",
|
||||
"nserror",
|
||||
|
@ -743,8 +743,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"cfg_aliases 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "chardetng"
|
||||
|
@ -2502,14 +2509,14 @@ dependencies = [
|
|||
name = "goblin"
|
||||
version = "0.7.999"
|
||||
dependencies = [
|
||||
"goblin 0.8.1",
|
||||
"goblin 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "goblin"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce2dfb858618fd40cafc83efadd02705adf6ffba765098736bd950c3c945fe0"
|
||||
checksum = "1b363a30c165f666402fe6a3024d3bec7ebc898f96a4a23bd1c99f8dbf3f4f47"
|
||||
dependencies = [
|
||||
"log",
|
||||
"plain",
|
||||
|
@ -3376,9 +3383,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.153"
|
||||
version = "0.2.158"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
||||
|
||||
[[package]]
|
||||
name = "libdbus-sys"
|
||||
|
@ -3737,9 +3744,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "minidump-common"
|
||||
version = "0.21.1"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bb6eaf88cc770fa58e6ae721cf2e40c2ca6a4c942ae8c7aa324d680bd3c6717"
|
||||
checksum = "0cd8a9fb054833d2f402e82e256aeef544e595e45fe8fca2de6d03ed605f6647"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"debugid",
|
||||
|
@ -3752,22 +3759,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "minidump-writer"
|
||||
version = "0.8.9"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abcd9c8a1e6e1e9d56ce3627851f39a17ea83e17c96bc510f29d7e43d78a7d"
|
||||
checksum = "1c75ff36a030d76801ed7ec3ea4ae45f12c0f1297f3447790288194274e9aa98"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"byteorder",
|
||||
"cfg-if",
|
||||
"crash-context",
|
||||
"goblin 0.8.1",
|
||||
"goblin 0.8.2",
|
||||
"libc",
|
||||
"log",
|
||||
"mach2",
|
||||
"memmap2",
|
||||
"memoffset 0.9.0",
|
||||
"minidump-common",
|
||||
"nix 0.28.0",
|
||||
"nix 0.29.0",
|
||||
"procfs-core",
|
||||
"scroll",
|
||||
"tempfile",
|
||||
|
@ -4056,7 +4063,7 @@ dependencies = [
|
|||
"arrayvec",
|
||||
"bit-set",
|
||||
"bitflags 2.6.0",
|
||||
"cfg_aliases",
|
||||
"cfg_aliases 0.1.1",
|
||||
"codespan-reporting",
|
||||
"hexf-parse",
|
||||
"indexmap 2.2.6",
|
||||
|
@ -4213,18 +4220,18 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
|||
name = "nix"
|
||||
version = "0.26.99"
|
||||
dependencies = [
|
||||
"nix 0.28.0",
|
||||
"nix 0.29.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"cfg_aliases 0.2.1",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
@ -6345,7 +6352,7 @@ dependencies = [
|
|||
"cargo_metadata",
|
||||
"fs-err",
|
||||
"glob",
|
||||
"goblin 0.8.1",
|
||||
"goblin 0.8.2",
|
||||
"heck",
|
||||
"once_cell",
|
||||
"paste",
|
||||
|
@ -6826,7 +6833,7 @@ dependencies = [
|
|||
"arrayvec",
|
||||
"bit-vec",
|
||||
"bitflags 2.6.0",
|
||||
"cfg_aliases",
|
||||
"cfg_aliases 0.1.1",
|
||||
"document-features",
|
||||
"indexmap 2.2.6",
|
||||
"log",
|
||||
|
@ -6854,7 +6861,7 @@ dependencies = [
|
|||
"bit-set",
|
||||
"bitflags 2.6.0",
|
||||
"block",
|
||||
"cfg_aliases",
|
||||
"cfg_aliases 0.1.1",
|
||||
"core-graphics-types",
|
||||
"gpu-alloc",
|
||||
"gpu-allocator",
|
||||
|
|
|
@ -148,9 +148,12 @@ bindgen_0_63 = { package = "bindgen", path = "build/rust/bindgen-0.63" }
|
|||
# Locally patch bindgen for https://github.com/rust-lang/rust-bindgen/pull/2824
|
||||
bindgen = { path = "third_party/rust/bindgen" }
|
||||
|
||||
# Patch nix 0.26 to 0.28
|
||||
# Patch nix 0.26 to 0.29
|
||||
nix = { path = "build/rust/nix" }
|
||||
|
||||
# Patch cfg_aliases 0.1 to 0.2
|
||||
cfg_aliases = { path = "build/rust/cfg_aliases" }
|
||||
|
||||
# Patch indexmap 2.0 to 1.0
|
||||
indexmap = { path = "build/rust/indexmap" }
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "cfg_aliases"
|
||||
version = "0.1.1"
|
||||
edition = "2018"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies.cfg_aliases]
|
||||
version = "0.2"
|
|
@ -0,0 +1,5 @@
|
|||
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
pub use cfg_aliases::*;
|
|
@ -8,7 +8,7 @@ license = "MPL-2.0"
|
|||
path = "lib.rs"
|
||||
|
||||
[dependencies.nix]
|
||||
version = "0.28"
|
||||
version = "0.29"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
|
|
|
@ -994,6 +994,12 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
|
|||
criteria = "safe-to-deploy"
|
||||
delta = "1.0.73 -> 1.0.78"
|
||||
|
||||
[[audits.cfg_aliases]]
|
||||
who = "Alex Franchuk <afranchuk@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.1.1 -> 0.2.1"
|
||||
notes = "Very minor changes."
|
||||
|
||||
[[audits.chardetng]]
|
||||
who = "Henri Sivonen <hsivonen@hsivonen.fi>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
@ -2278,6 +2284,12 @@ criteria = "safe-to-deploy"
|
|||
delta = "0.8.0 -> 0.8.1"
|
||||
notes = "Updating goblin to 0.8.1 that includes my fix for Elf SectionHeader parsing"
|
||||
|
||||
[[audits.goblin]]
|
||||
who = "Alex Franchuk <afranchuk@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.8.1 -> 0.8.2"
|
||||
notes = "Removes the TE feature/functionality, otherwise no meaningful changes."
|
||||
|
||||
[[audits.gpu-alloc]]
|
||||
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
@ -2758,6 +2770,11 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
|
|||
criteria = "safe-to-deploy"
|
||||
delta = "0.2.147 -> 0.2.148"
|
||||
|
||||
[[audits.libc]]
|
||||
who = "Alex Franchuk <afranchuk@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.2.154 -> 0.2.158"
|
||||
|
||||
[[audits.libloading]]
|
||||
who = "Mike Hommey <mh+mozilla@glandium.org>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
@ -3042,6 +3059,12 @@ criteria = "safe-to-deploy"
|
|||
delta = "0.8.3 -> 0.8.9"
|
||||
notes = "Mainly dependency updates and a few small features (in support of mozilla bugs)."
|
||||
|
||||
[[audits.minidump-writer]]
|
||||
who = "Alex Franchuk <afranchuk@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.8.9 -> 0.10.1"
|
||||
notes = "Crate written and reviewed by mozilla employees."
|
||||
|
||||
[[audits.miniz_oxide]]
|
||||
who = "Mike Hommey <mh+mozilla@glandium.org>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
@ -3181,6 +3204,11 @@ Many new features and bugfixes. Obviously there's a lot of unsafe code calling
|
|||
libc, but the usage looks correct.
|
||||
"""
|
||||
|
||||
[[audits.nix]]
|
||||
who = "Alex Franchuk <afranchuk@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.28.0 -> 0.29.0"
|
||||
|
||||
[[audits.nom]]
|
||||
who = "Mike Hommey <mh+mozilla@glandium.org>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
|
|
@ -366,6 +366,13 @@ user-id = 51017
|
|||
user-login = "JohnTitor"
|
||||
user-name = "Yuki Okushi"
|
||||
|
||||
[[publisher.libc]]
|
||||
version = "0.2.154"
|
||||
when = "2024-04-29"
|
||||
user-id = 51017
|
||||
user-login = "JohnTitor"
|
||||
user-name = "Yuki Okushi"
|
||||
|
||||
[[publisher.libz-rs-sys]]
|
||||
version = "0.2.1"
|
||||
when = "2024-07-08"
|
||||
|
@ -408,6 +415,13 @@ user-id = 72814
|
|||
user-login = "gabrielesvelto"
|
||||
user-name = "Gabriele Svelto"
|
||||
|
||||
[[publisher.minidump-common]]
|
||||
version = "0.22.1"
|
||||
when = "2024-09-05"
|
||||
user-id = 72814
|
||||
user-login = "gabrielesvelto"
|
||||
user-name = "Gabriele Svelto"
|
||||
|
||||
[[publisher.nss-gk-api]]
|
||||
version = "0.3.0"
|
||||
when = "2023-06-14"
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"984209d6fcb6276b505fe703019ed83d57b33accbd6416c2f86826baadb2dc1a","LICENSE":"31b94860253d8ec7b4529f51901044d3b459d6292d996504a36b1bae3a36a812","NOTICES.md":"1e2b7ade3fb228130408b9990cae6a7618eb314c75aa0b164bfe485d9d9756ee","README.md":"2065bc96d88b482eafba1865b059524a25c1acb32e604421d2afb97ffb58826a","src/lib.rs":"83d97f5e7643893132c290cfa7754579535f6a1576ec0b4ecfea6e8759cfede9"},"package":"fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"}
|
||||
{"files":{"Cargo.toml":"120227a96e9faeebfd1323d7faa3a0ec51e6d873cded83e3a5dc7e31e183b254","LICENSE":"31b94860253d8ec7b4529f51901044d3b459d6292d996504a36b1bae3a36a812","NOTICES.md":"1e2b7ade3fb228130408b9990cae6a7618eb314c75aa0b164bfe485d9d9756ee","README.md":"2065bc96d88b482eafba1865b059524a25c1acb32e604421d2afb97ffb58826a","src/lib.rs":"72c2ad6ce653a04c11be00a3e70b66642e73c9813c618fb23deb7533011592ac","tests/test.rs":"94837f32b02d03f761377e44af858676cd2838b9d43ec2b05807e90fbf95bbb1"},"package":"613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"}
|
|
@ -3,26 +3,41 @@
|
|||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "cfg_aliases"
|
||||
version = "0.1.1"
|
||||
version = "0.2.1"
|
||||
authors = ["Zicklag <zicklag@katharostech.com>"]
|
||||
exclude = ["modoc.config", "release.toml"]
|
||||
exclude = [
|
||||
"modoc.config",
|
||||
"release.toml",
|
||||
]
|
||||
description = "A tiny utility to help save you a lot of effort with long winded `#[cfg()]` checks."
|
||||
homepage = "https://github.com/katharostech/cfg_aliases"
|
||||
documentation = "https://docs.rs/cfg_aliases"
|
||||
readme = "README.md"
|
||||
keywords = ["cfg", "alias", "conditional", "compilation", "build"]
|
||||
categories = ["development-tools", "development-tools::build-utils"]
|
||||
keywords = [
|
||||
"cfg",
|
||||
"alias",
|
||||
"conditional",
|
||||
"compilation",
|
||||
"build",
|
||||
]
|
||||
categories = [
|
||||
"development-tools",
|
||||
"development-tools::build-utils",
|
||||
]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/katharostech/cfg_aliases"
|
||||
|
||||
[badges.maintenance]
|
||||
status = "passively-maintained"
|
||||
|
||||
[lints.clippy]
|
||||
str_to_string = "deny"
|
||||
|
|
|
@ -175,12 +175,18 @@
|
|||
macro_rules! cfg_aliases {
|
||||
// Helper that just checks whether the CFG environment variable is set
|
||||
(@cfg_is_set $cfgname:ident) => {
|
||||
std::env::var(
|
||||
format!(
|
||||
"CARGO_CFG_{}",
|
||||
&stringify!($cfgname).to_uppercase().replace("-", "_")
|
||||
)
|
||||
).is_ok()
|
||||
{
|
||||
let cfg_var = stringify!($cfgname).to_uppercase().replace("-", "_");
|
||||
let result = std::env::var(format!("CARGO_CFG_{}", &cfg_var)).is_ok();
|
||||
|
||||
// CARGO_CFG_DEBUG_ASSERTIONS _should_ be set for when debug assertions are enabled,
|
||||
// but as of writing is not: see https://github.com/rust-lang/cargo/issues/5777
|
||||
if !result && cfg_var == "DEBUG_ASSERTIONS" {
|
||||
std::env::var("PROFILE") == Ok("debug".to_owned())
|
||||
} else {
|
||||
result
|
||||
}
|
||||
}
|
||||
};
|
||||
// Helper to check for the presense of a feature
|
||||
(@cfg_has_feature $feature:expr) => {
|
||||
|
@ -201,7 +207,7 @@ macro_rules! cfg_aliases {
|
|||
"CARGO_CFG_{}",
|
||||
&stringify!($cfgname).to_uppercase().replace("-", "_")
|
||||
)
|
||||
).unwrap_or("".to_string()).split(",").find(|x| x == &$cfgvalue).is_some()
|
||||
).unwrap_or("".to_owned()).split(",").find(|x| x == &$cfgvalue).is_some()
|
||||
};
|
||||
|
||||
// Emitting `any(clause1,clause2,...)`: convert to `$crate::cfg_aliases!(clause1) && $crate::cfg_aliases!(clause2) && ...`
|
||||
|
@ -359,6 +365,7 @@ macro_rules! cfg_aliases {
|
|||
}
|
||||
|
||||
$(
|
||||
println!("cargo:rustc-check-cfg=cfg({})", stringify!($alias));
|
||||
if $crate::cfg_aliases!(@parser $($config)*) {
|
||||
println!("cargo:rustc-cfg={}", stringify!($alias));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
use cfg_aliases::cfg_aliases;
|
||||
|
||||
#[test]
|
||||
fn basic_setup() {
|
||||
// Same as in the docs.
|
||||
// Note that tests build this already, but unfortunately this doesn't catch clippy lints!
|
||||
// See https://github.com/rust-lang/rust/issues/56232
|
||||
cfg_aliases! {
|
||||
// Platforms
|
||||
wasm: { target_arch = "wasm32" },
|
||||
android: { target_os = "android" },
|
||||
macos: { target_os = "macos" },
|
||||
linux: { target_os = "linux" },
|
||||
// Backends
|
||||
surfman: { all(unix, feature = "surfman", not(wasm)) },
|
||||
glutin: { all(feature = "glutin", not(wasm)) },
|
||||
wgl: { all(windows, feature = "wgl", not(wasm)) },
|
||||
dummy: { not(any(wasm, glutin, wgl, surfman)) },
|
||||
};
|
||||
}
|
|
@ -1 +1 @@
|
|||
{"files":{"CHANGELOG.md":"50453c2109df5663c2e96b8f1f23525249c5fc2f59c8f74ec5c2b3646ac21144","Cargo.toml":"5a5859d8a4040b75bbceda8bca57dae75a4b61d28dce36aede2808e6b086c6f8","LICENSE":"655e3ee7a4c27430774962e62a6d37d7348e5f2f292010ad674ce1bebefd24bc","README.md":"5791f3dd86bcb4de9b580abf27ca6a9f59e03e87f35262c9fab2baf4b07bf930","src/archive/mod.rs":"ae739638d7267011bedf51712516d3485171d8f2df2ab6746a0d942d86efd6a6","src/elf/compression_header.rs":"2eb5fdda9177c1c897310d86714967de019b39c6e23b1f3a890dd3a659be0acc","src/elf/constants_header.rs":"f2ede290ecacf60b1719e9994aa45612bf0f7baf63806a293d4530a674e5861a","src/elf/constants_relocation.rs":"2837231dd3e2341008842e031b81cbb9999214a2f9e6738c6374a5464d62555d","src/elf/dynamic.rs":"907146d1968f656fc9cc3621037c193877e30675ccd8ec6eb2e3adbc1e2afd27","src/elf/gnu_hash.rs":"4592b5516d807a61a9dccc3f97266587c032eea621708bd78e23c70be6128228","src/elf/header.rs":"3391a1fa9b8e3923f7ce74caff0668d8ddb5b34767bf3da309ff497fd81c34c7","src/elf/mod.rs":"2ee0faa0917deb5e90ca60e9c852434745a4c7f553e609e9603a57b7d55b739f","src/elf/note.rs":"bf5e45e2697f7700d5adbb52f890ea4c63b70b7077ca0e7c751420bb92923529","src/elf/program_header.rs":"4c322eb124c4e2bdeec4915067d2bb11fe9e7fba1811dc351a3f7581df121da0","src/elf/reloc.rs":"e952fc4f79ac6a08f218a4758321ab94f172c376dc5235a82f70732682cca82f","src/elf/section_header.rs":"72eb788e8807f16a97683d20add21d5c3feaae06813509e2a87b76a7cd0c376f","src/elf/sym.rs":"267996f926f337b88058908af260be30473afbe1fe6d72cdeb8dd0ed474671d8","src/elf/symver.rs":"3f899201f64a702653d44288f860003e7acd75e38111d36479af823ed92b1341","src/error.rs":"a1bb56d82db52ac627e55b163f489f06a78c939a8ccfdec210b4f726d6ed6e9d","src/lib.rs":"06771b56b262fa30396e4bacbf0a4996b6088d1cfa5defa20dedf69a2c58d3b3","src/mach/bind_opcodes.rs":"1dcacfb853d05c2c7e6dbb4509ee705a8ea645db0d334991a2293fef92eee851","src/mach/constants.rs":"c2a2381a0b9c3047d37582465e8965d995dca414d0da21fb7bcc6b8334e49eb6","src/mach/exports.rs":"d22122744673a3ce5f54b2b4b20bfa47d17378e64d3dda2858dd13add74ed3dc","src/mach/fat.rs":"45a3228aaa1ab8b77f322dd4924b7383f1357e226ffc079846d67c0268389ea7","src/mach/header.rs":"006619188f51fa43051dc04aa4b2ecd5f89136cf05cb6a7b23a228228008e6ae","src/mach/imports.rs":"2153269dfff32e23d72f76a82d658be06bd79b7e35d79b7e17115e4eb24b13d5","src/mach/load_command.rs":"42e6f0973092185db233230e71e9312bbac7c2e1090bb6d713804020319dfa33","src/mach/mod.rs":"f1e120b7aabe370fa2af43e359f97ffa3e187fdb5743ef19c37402264e92b326","src/mach/relocation.rs":"11b0b76ed7d997c87e396100515f931fe84473c228bed0e980fbab311530070a","src/mach/segment.rs":"947acd8a724b41d0afbbd9e2727f41be51f1be439f47417258e829db1a4765e6","src/mach/symbols.rs":"d2505fa8d65ea267abfcb6a9fc4d1acd47d5605aa6775935757e2fa8e92af507","src/pe/authenticode.rs":"36b5b3ddc9806f679cf21418bc13af4b277eba87096304dfb50946bc0f941206","src/pe/certificate_table.rs":"f6c31ba518d9fc4b6e12d2f24d6c9d58b21b341a1f189cbcf2aae0ae51304ad3","src/pe/characteristic.rs":"2ffa012ec225f3c8570689713969a7dc34a92eaf4f944a27881fd0c248cc8b20","src/pe/data_directories.rs":"d0352ccc03e0ab2935235e91b391cc55828406087f026f90ec11ca5906fd8c8c","src/pe/debug.rs":"4b570730d674239ba6f9f7b6bb889206c463bce91a1a0cf84d4f519e0735ee8c","src/pe/dll_characteristic.rs":"d63e86ecb38ccdd81493268be34535391b794651d619e8d4ccc1a56aa10e1679","src/pe/exception.rs":"3935900334692a6f54f7176eca044688289834bcde1b579b88d6ed1af3c3c005","src/pe/export.rs":"c98f5ce0b1b18bb87f06d1d41dbf70f443d65ecb1624cb23a1ef6c5f93a892e1","src/pe/header.rs":"5bf09980c4113c7572010e6c5a356ace1a65a11203c0aa69a6d1f38be9c9d471","src/pe/import.rs":"855276e46c01ccd7631104e4d1265592e36c9468aadcacc937a40c29d94aabe3","src/pe/mod.rs":"6d2dc2c555e5802687dfe46b70c8200a1e83dd67eaed4c4cc7979cb5f6890755","src/pe/optional_header.rs":"f2411a0f272e22c280a1fe3c15919b07d1f152448b47db31acaacad8a0a9a153","src/pe/options.rs":"457877197f768c331437297d787dc718b1053b813e3a1dd9b968133fb1540d44","src/pe/relocation.rs":"c479b80bb1d6910f2168505dda4f2d8925b7edc34bed4e25d069546f88f52bb3","src/pe/section_table.rs":"e4b1a2f78c2336aaa0355b5ef102dbe29138c4fa1ba29ed3f379aad1fc64bdff","src/pe/subsystem.rs":"162a851e217b617aa8afa1b83e37ea9c5a793f76a17be57b56b550d7cabb7b8a","src/pe/symbol.rs":"1a5fb5bec5727752a6506682ed2ab57829ea810f21f951932a0107861ec0e092","src/pe/utils.rs":"e6da9979ba5f2ae7d1274eef8230cdc4dd90c90a79c7bb9438f8b8ff0aef74be","src/strtab.rs":"110c774b2998514b4d0be1d575b3e2a8eb85f801b6f782e4ed3a8f7521920689","tests/bins/elf/gnu_hash/README.md":"52581e2ea7067a55bd8aedf4079200fb76448573ae9ffef7d886b9556e980db9","tests/bins/te/README.md":"a0daf347449bcf82c38d981b2a700d9fd4657c3a7e7dbfa22f90e74750c6bc0d"},"package":"8ce2dfb858618fd40cafc83efadd02705adf6ffba765098736bd950c3c945fe0"}
|
||||
{"files":{"CHANGELOG.md":"50453c2109df5663c2e96b8f1f23525249c5fc2f59c8f74ec5c2b3646ac21144","Cargo.toml":"f57048482755f5bddc3ed3a06b469ebec4923b647df060ae53f3a349932ddf76","LICENSE":"655e3ee7a4c27430774962e62a6d37d7348e5f2f292010ad674ce1bebefd24bc","README.md":"d108b8d55ecd89934af0d94c6c86d4e39ed2daefa8d2ad5a229cae61dfe6f531","src/archive/mod.rs":"ae739638d7267011bedf51712516d3485171d8f2df2ab6746a0d942d86efd6a6","src/elf/compression_header.rs":"2eb5fdda9177c1c897310d86714967de019b39c6e23b1f3a890dd3a659be0acc","src/elf/constants_header.rs":"f2ede290ecacf60b1719e9994aa45612bf0f7baf63806a293d4530a674e5861a","src/elf/constants_relocation.rs":"2837231dd3e2341008842e031b81cbb9999214a2f9e6738c6374a5464d62555d","src/elf/dynamic.rs":"907146d1968f656fc9cc3621037c193877e30675ccd8ec6eb2e3adbc1e2afd27","src/elf/gnu_hash.rs":"4592b5516d807a61a9dccc3f97266587c032eea621708bd78e23c70be6128228","src/elf/header.rs":"3391a1fa9b8e3923f7ce74caff0668d8ddb5b34767bf3da309ff497fd81c34c7","src/elf/mod.rs":"2ee0faa0917deb5e90ca60e9c852434745a4c7f553e609e9603a57b7d55b739f","src/elf/note.rs":"bf5e45e2697f7700d5adbb52f890ea4c63b70b7077ca0e7c751420bb92923529","src/elf/program_header.rs":"4c322eb124c4e2bdeec4915067d2bb11fe9e7fba1811dc351a3f7581df121da0","src/elf/reloc.rs":"e952fc4f79ac6a08f218a4758321ab94f172c376dc5235a82f70732682cca82f","src/elf/section_header.rs":"72eb788e8807f16a97683d20add21d5c3feaae06813509e2a87b76a7cd0c376f","src/elf/sym.rs":"267996f926f337b88058908af260be30473afbe1fe6d72cdeb8dd0ed474671d8","src/elf/symver.rs":"3f899201f64a702653d44288f860003e7acd75e38111d36479af823ed92b1341","src/error.rs":"a1bb56d82db52ac627e55b163f489f06a78c939a8ccfdec210b4f726d6ed6e9d","src/lib.rs":"f29832bdf7d7f7d9e34f65704afea2710d578df60cc171dd179b5ce889faaf12","src/mach/bind_opcodes.rs":"1dcacfb853d05c2c7e6dbb4509ee705a8ea645db0d334991a2293fef92eee851","src/mach/constants.rs":"c2a2381a0b9c3047d37582465e8965d995dca414d0da21fb7bcc6b8334e49eb6","src/mach/exports.rs":"d22122744673a3ce5f54b2b4b20bfa47d17378e64d3dda2858dd13add74ed3dc","src/mach/fat.rs":"45a3228aaa1ab8b77f322dd4924b7383f1357e226ffc079846d67c0268389ea7","src/mach/header.rs":"006619188f51fa43051dc04aa4b2ecd5f89136cf05cb6a7b23a228228008e6ae","src/mach/imports.rs":"2153269dfff32e23d72f76a82d658be06bd79b7e35d79b7e17115e4eb24b13d5","src/mach/load_command.rs":"42e6f0973092185db233230e71e9312bbac7c2e1090bb6d713804020319dfa33","src/mach/mod.rs":"f1e120b7aabe370fa2af43e359f97ffa3e187fdb5743ef19c37402264e92b326","src/mach/relocation.rs":"11b0b76ed7d997c87e396100515f931fe84473c228bed0e980fbab311530070a","src/mach/segment.rs":"947acd8a724b41d0afbbd9e2727f41be51f1be439f47417258e829db1a4765e6","src/mach/symbols.rs":"d2505fa8d65ea267abfcb6a9fc4d1acd47d5605aa6775935757e2fa8e92af507","src/pe/authenticode.rs":"36b5b3ddc9806f679cf21418bc13af4b277eba87096304dfb50946bc0f941206","src/pe/certificate_table.rs":"f6c31ba518d9fc4b6e12d2f24d6c9d58b21b341a1f189cbcf2aae0ae51304ad3","src/pe/characteristic.rs":"2ffa012ec225f3c8570689713969a7dc34a92eaf4f944a27881fd0c248cc8b20","src/pe/data_directories.rs":"d0352ccc03e0ab2935235e91b391cc55828406087f026f90ec11ca5906fd8c8c","src/pe/debug.rs":"3811c616a9b6d6b54e15348bb369b794bb89532e04fe19eca91b745d7c51a553","src/pe/dll_characteristic.rs":"d63e86ecb38ccdd81493268be34535391b794651d619e8d4ccc1a56aa10e1679","src/pe/exception.rs":"3935900334692a6f54f7176eca044688289834bcde1b579b88d6ed1af3c3c005","src/pe/export.rs":"c98f5ce0b1b18bb87f06d1d41dbf70f443d65ecb1624cb23a1ef6c5f93a892e1","src/pe/header.rs":"dea84fd7101aff56c7cb6ff08a1efdde5cf43a04328397b6177d36ab1c2a3774","src/pe/import.rs":"855276e46c01ccd7631104e4d1265592e36c9468aadcacc937a40c29d94aabe3","src/pe/mod.rs":"1d8a7cb3ddb8443e34939adda4794308a31737bc29f66668d36dfa22950ba69f","src/pe/optional_header.rs":"f2411a0f272e22c280a1fe3c15919b07d1f152448b47db31acaacad8a0a9a153","src/pe/options.rs":"457877197f768c331437297d787dc718b1053b813e3a1dd9b968133fb1540d44","src/pe/relocation.rs":"c479b80bb1d6910f2168505dda4f2d8925b7edc34bed4e25d069546f88f52bb3","src/pe/section_table.rs":"e4b1a2f78c2336aaa0355b5ef102dbe29138c4fa1ba29ed3f379aad1fc64bdff","src/pe/subsystem.rs":"162a851e217b617aa8afa1b83e37ea9c5a793f76a17be57b56b550d7cabb7b8a","src/pe/symbol.rs":"1a5fb5bec5727752a6506682ed2ab57829ea810f21f951932a0107861ec0e092","src/pe/utils.rs":"e6da9979ba5f2ae7d1274eef8230cdc4dd90c90a79c7bb9438f8b8ff0aef74be","src/strtab.rs":"110c774b2998514b4d0be1d575b3e2a8eb85f801b6f782e4ed3a8f7521920689","tests/bins/elf/gnu_hash/README.md":"52581e2ea7067a55bd8aedf4079200fb76448573ae9ffef7d886b9556e980db9"},"package":"1b363a30c165f666402fe6a3024d3bec7ebc898f96a4a23bd1c99f8dbf3f4f47"}
|
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.63.0"
|
||||
name = "goblin"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
authors = [
|
||||
"m4b <m4b.github.io@gmail.com>",
|
||||
"seu <seu@panopticon.re>",
|
||||
|
@ -74,7 +74,6 @@ default = [
|
|||
"mach64",
|
||||
"pe32",
|
||||
"pe64",
|
||||
"te",
|
||||
"archive",
|
||||
"endian_fd",
|
||||
]
|
||||
|
@ -103,10 +102,6 @@ std = [
|
|||
"alloc",
|
||||
"scroll/std",
|
||||
]
|
||||
te = [
|
||||
"alloc",
|
||||
"endian_fd",
|
||||
]
|
||||
|
||||
[badges.travis-ci]
|
||||
branch = "master"
|
||||
|
|
|
@ -97,7 +97,6 @@ Here are some things you could do with this crate (or help to implement so they
|
|||
* mach32 - 32-bit mach-o `repr(C)` struct defs
|
||||
* pe32 - 32-bit PE `repr(C)` struct defs
|
||||
* pe64 - 64-bit PE `repr(C)` struct defs
|
||||
+ te - Terse Executable (TE) `repr(C)` struct defs
|
||||
* archive - a Unix Archive parser
|
||||
* endian_fd - parses according to the endianness in the binary
|
||||
* std - to allow `no_std` environments
|
||||
|
|
|
@ -229,7 +229,6 @@ pub enum Hint {
|
|||
Mach(HintData),
|
||||
MachFat(usize),
|
||||
PE,
|
||||
TE,
|
||||
COFF,
|
||||
Archive,
|
||||
Unknown(u64),
|
||||
|
@ -237,7 +236,7 @@ pub enum Hint {
|
|||
|
||||
macro_rules! if_everything {
|
||||
($($i:item)*) => ($(
|
||||
#[cfg(all(feature = "endian_fd", feature = "elf64", feature = "elf32", feature = "pe64", feature = "pe32", feature = "te", feature = "mach64", feature = "mach32", feature = "archive"))]
|
||||
#[cfg(all(feature = "endian_fd", feature = "elf64", feature = "elf32", feature = "pe64", feature = "pe32", feature = "mach64", feature = "mach32", feature = "archive"))]
|
||||
$i
|
||||
)*)
|
||||
}
|
||||
|
@ -263,7 +262,6 @@ if_everything! {
|
|||
} else {
|
||||
match *&bytes[0..2].pread_with::<u16>(0, LE)? {
|
||||
pe::header::DOS_MAGIC => Ok(Hint::PE),
|
||||
pe::header::TE_MAGIC => Ok(Hint::TE),
|
||||
pe::header::COFF_MACHINE_X86 |
|
||||
pe::header::COFF_MACHINE_X86_64 |
|
||||
pe::header::COFF_MACHINE_ARM64 => Ok(Hint::COFF),
|
||||
|
@ -292,8 +290,6 @@ if_everything! {
|
|||
Elf(elf::Elf<'a>),
|
||||
/// A PE32/PE32+!
|
||||
PE(pe::PE<'a>),
|
||||
/// A TE!
|
||||
TE(pe::TE<'a>),
|
||||
/// A COFF
|
||||
COFF(pe::Coff<'a>),
|
||||
/// A 32/64-bit Mach-o binary _OR_ it is a multi-architecture binary container!
|
||||
|
@ -313,7 +309,6 @@ if_everything! {
|
|||
Hint::Mach(_) | Hint::MachFat(_) => Ok(Object::Mach(mach::Mach::parse(bytes)?)),
|
||||
Hint::Archive => Ok(Object::Archive(archive::Archive::parse(bytes)?)),
|
||||
Hint::PE => Ok(Object::PE(pe::PE::parse(bytes)?)),
|
||||
Hint::TE => Ok(Object::TE(pe::TE::parse(bytes)?)),
|
||||
Hint::COFF => Ok(Object::COFF(pe::Coff::parse(bytes)?)),
|
||||
Hint::Unknown(magic) => Ok(Object::Unknown(magic)),
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ impl ImageDebugDirectory {
|
|||
)
|
||||
}
|
||||
|
||||
pub(crate) fn parse_with_opts(
|
||||
fn parse_with_opts(
|
||||
bytes: &[u8],
|
||||
dd: data_directories::DataDirectory,
|
||||
sections: &[section_table::SectionTable],
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::error;
|
||||
use crate::pe::{data_directories, optional_header, section_table, symbol};
|
||||
use crate::pe::{optional_header, section_table, symbol};
|
||||
use crate::strtab;
|
||||
use alloc::vec::Vec;
|
||||
use log::debug;
|
||||
|
@ -835,147 +835,6 @@ impl ctx::TryIntoCtx<scroll::Endian> for Header {
|
|||
}
|
||||
}
|
||||
|
||||
/// The TE header is a reduced PE32/PE32+ header containing only fields
|
||||
/// required for execution in the Platform Initialization
|
||||
/// ([PI](https://uefi.org/specs/PI/1.8/V1_Introduction.html)) architecture.
|
||||
/// The TE header is described in this specification:
|
||||
/// <https://uefi.org/specs/PI/1.8/V1_TE_Image.html#te-header>
|
||||
#[cfg(feature = "te")]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, PartialEq, Copy, Clone, Pread, Pwrite)]
|
||||
pub struct TeHeader {
|
||||
/// Te signature, always [TE_MAGIC]
|
||||
pub signature: u16,
|
||||
/// The machine type
|
||||
pub machine: u16,
|
||||
/// The number of sections
|
||||
pub number_of_sections: u8,
|
||||
/// The subsystem
|
||||
pub subsystem: u8,
|
||||
/// the amount of bytes stripped from the header when converting from a
|
||||
/// PE32/PE32+ header to a TE header. Used to resolve addresses
|
||||
pub stripped_size: u16,
|
||||
/// The entry point of the binary
|
||||
pub entry_point: u32,
|
||||
/// The base of the code section
|
||||
pub base_of_code: u32,
|
||||
/// The image base
|
||||
pub image_base: u64,
|
||||
/// The size and address of the relocation directory
|
||||
pub reloc_dir: data_directories::DataDirectory,
|
||||
/// The size and address of the debug directory
|
||||
pub debug_dir: data_directories::DataDirectory,
|
||||
}
|
||||
|
||||
#[cfg(feature = "te")]
|
||||
#[doc(alias("IMAGE_TE_SIGNATURE"))]
|
||||
pub const TE_MAGIC: u16 = 0x5a56;
|
||||
|
||||
#[cfg(feature = "te")]
|
||||
impl TeHeader {
|
||||
/// Parse the TE header from the given bytes.
|
||||
pub fn parse(bytes: &[u8], offset: &mut usize) -> error::Result<Self> {
|
||||
let mut header: TeHeader = bytes.gread_with(offset, scroll::LE)?;
|
||||
let adj_offset = header.stripped_size as u32 - core::mem::size_of::<TeHeader>() as u32;
|
||||
header.fixup_header(adj_offset);
|
||||
Ok(header)
|
||||
}
|
||||
|
||||
/// Parse the sections from the TE header.
|
||||
pub fn sections(
|
||||
&self,
|
||||
bytes: &[u8],
|
||||
offset: &mut usize,
|
||||
) -> error::Result<Vec<section_table::SectionTable>> {
|
||||
let adj_offset = self.stripped_size as u32 - core::mem::size_of::<TeHeader>() as u32;
|
||||
let nsections = self.number_of_sections as usize;
|
||||
|
||||
// a section table is at least 40 bytes
|
||||
if nsections > bytes.len() / 40 {
|
||||
return Err(error::Error::BufferTooShort(nsections, "sections"));
|
||||
}
|
||||
|
||||
let mut sections = Vec::with_capacity(nsections);
|
||||
for i in 0..nsections {
|
||||
let mut section = section_table::SectionTable::parse(bytes, offset, 0)?;
|
||||
TeHeader::fixup_section(&mut section, adj_offset);
|
||||
debug!("({}) {:#?}", i, section);
|
||||
sections.push(section);
|
||||
}
|
||||
Ok(sections)
|
||||
}
|
||||
|
||||
// Adjust addresses in the header to account for the stripped size
|
||||
fn fixup_header(&mut self, adj_offset: u32) {
|
||||
debug!(
|
||||
"Entry point fixed up from: 0x{:x} to 0x{:X}",
|
||||
self.entry_point,
|
||||
self.entry_point.wrapping_sub(adj_offset)
|
||||
);
|
||||
self.entry_point = self.entry_point.wrapping_sub(adj_offset);
|
||||
|
||||
debug!(
|
||||
"Base of code fixed up from: 0x{:x} to 0x{:X}",
|
||||
self.base_of_code,
|
||||
self.base_of_code.wrapping_sub(adj_offset)
|
||||
);
|
||||
self.base_of_code = self.base_of_code.wrapping_sub(adj_offset);
|
||||
|
||||
debug!(
|
||||
"Relocation Directory fixed up from: 0x{:x} to 0x{:X}",
|
||||
self.reloc_dir.virtual_address,
|
||||
self.reloc_dir.virtual_address.wrapping_sub(adj_offset)
|
||||
);
|
||||
self.reloc_dir.virtual_address = self.reloc_dir.virtual_address.wrapping_sub(adj_offset);
|
||||
|
||||
debug!(
|
||||
"Debug Directory fixed up from: 0x{:x} to 0x{:X}",
|
||||
self.debug_dir.virtual_address,
|
||||
self.debug_dir.virtual_address.wrapping_sub(adj_offset)
|
||||
);
|
||||
self.debug_dir.virtual_address = self.debug_dir.virtual_address.wrapping_sub(adj_offset);
|
||||
}
|
||||
|
||||
// Adjust addresses in the section to account for the stripped size
|
||||
fn fixup_section(section: &mut section_table::SectionTable, adj_offset: u32) {
|
||||
debug!(
|
||||
"Section virtual address fixed up from: 0x{:X} to 0x{:X}",
|
||||
section.virtual_address,
|
||||
section.virtual_address.wrapping_sub(adj_offset)
|
||||
);
|
||||
section.virtual_address = section.virtual_address.wrapping_sub(adj_offset);
|
||||
|
||||
if section.pointer_to_linenumbers > 0 {
|
||||
debug!(
|
||||
"Section pointer to line numbers fixed up from: 0x{:X} to 0x{:X}",
|
||||
section.pointer_to_linenumbers,
|
||||
section.pointer_to_linenumbers.wrapping_sub(adj_offset)
|
||||
);
|
||||
section.pointer_to_linenumbers =
|
||||
section.pointer_to_linenumbers.wrapping_sub(adj_offset);
|
||||
}
|
||||
|
||||
if section.pointer_to_raw_data > 0 {
|
||||
debug!(
|
||||
"Section pointer to raw data fixed up from: 0x{:X} to 0x{:X}",
|
||||
section.pointer_to_raw_data,
|
||||
section.pointer_to_raw_data.wrapping_sub(adj_offset)
|
||||
);
|
||||
section.pointer_to_raw_data = section.pointer_to_raw_data.wrapping_sub(adj_offset);
|
||||
}
|
||||
|
||||
if section.pointer_to_relocations > 0 {
|
||||
debug!(
|
||||
"Section pointer to relocations fixed up from: 0x{:X} to 0x{:X}",
|
||||
section.pointer_to_relocations,
|
||||
section.pointer_to_relocations.wrapping_sub(adj_offset)
|
||||
);
|
||||
section.pointer_to_relocations =
|
||||
section.pointer_to_relocations.wrapping_sub(adj_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert machine to str representation. Any case of "COFF_UNKNOWN"
|
||||
/// should be expected to change to a more specific value.
|
||||
pub fn machine_to_str(machine: u16) -> &'static str {
|
||||
|
|
|
@ -467,98 +467,6 @@ impl<'a> ctx::TryIntoCtx<scroll::Endian> for PE<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// An analyzed TE binary
|
||||
///
|
||||
/// A TE binary is a PE/PE32+ binary that has had it's header stripped and
|
||||
/// re-formatted to the TE specification. This presents a challenge for
|
||||
/// parsing, as all relative addresses (RVAs) are not updated to take this into
|
||||
/// account, and are thus incorrect. The parsing of a TE must take this into
|
||||
/// account by using the [header::TeHeader::stripped_size`] field of the TE
|
||||
/// header to adjust the RVAs during parsing.
|
||||
#[cfg(feature = "te")]
|
||||
#[derive(Debug)]
|
||||
pub struct TE<'a> {
|
||||
/// The TE header
|
||||
pub header: header::TeHeader,
|
||||
/// A list of the sections in this TE binary
|
||||
pub sections: Vec<section_table::SectionTable>,
|
||||
/// Debug information, contained in the PE header
|
||||
pub debug_data: debug::DebugData<'a>,
|
||||
/// The offset to apply to addresses not parsed by the TE parser
|
||||
/// itself: [header::TeHeader::stripped_size] - size_of::<[header::TeHeader]>()
|
||||
pub rva_offset: usize,
|
||||
}
|
||||
|
||||
#[cfg(feature = "te")]
|
||||
impl<'a> TE<'a> {
|
||||
/// Reads a TE binary from the underlying `bytes`
|
||||
pub fn parse(bytes: &'a [u8]) -> error::Result<Self> {
|
||||
let opts = &options::ParseOptions {
|
||||
resolve_rva: false,
|
||||
parse_attribute_certificates: false,
|
||||
};
|
||||
|
||||
let mut offset = 0;
|
||||
|
||||
// Parse the TE header and adjust the offsets
|
||||
let header = header::TeHeader::parse(bytes, &mut offset)?;
|
||||
let rva_offset = header.stripped_size as usize - core::mem::size_of::<header::TeHeader>();
|
||||
|
||||
// Parse the sections and adjust the offsets
|
||||
let sections = header.sections(bytes, &mut offset)?;
|
||||
|
||||
// Parse the debug data. Must adjust offsets before parsing the image_debug_directory
|
||||
let mut debug_data = debug::DebugData::default();
|
||||
debug_data.image_debug_directory = debug::ImageDebugDirectory::parse_with_opts(
|
||||
bytes,
|
||||
header.debug_dir,
|
||||
§ions,
|
||||
0,
|
||||
opts,
|
||||
)?;
|
||||
TE::fixup_debug_data(&mut debug_data, rva_offset as u32);
|
||||
debug_data.codeview_pdb70_debug_info = debug::CodeviewPDB70DebugInfo::parse_with_opts(
|
||||
bytes,
|
||||
&debug_data.image_debug_directory,
|
||||
opts,
|
||||
)?;
|
||||
|
||||
Ok(TE {
|
||||
header,
|
||||
sections,
|
||||
debug_data,
|
||||
rva_offset,
|
||||
})
|
||||
}
|
||||
|
||||
/// Adjust all addresses in the TE binary debug data.
|
||||
fn fixup_debug_data(dd: &mut debug::DebugData, rva_offset: u32) {
|
||||
debug!(
|
||||
"ImageDebugDirectory address of raw data fixed up from: 0x{:X} to 0x{:X}",
|
||||
dd.image_debug_directory.address_of_raw_data,
|
||||
dd.image_debug_directory
|
||||
.address_of_raw_data
|
||||
.wrapping_sub(rva_offset),
|
||||
);
|
||||
dd.image_debug_directory.address_of_raw_data = dd
|
||||
.image_debug_directory
|
||||
.address_of_raw_data
|
||||
.wrapping_sub(rva_offset);
|
||||
|
||||
debug!(
|
||||
"ImageDebugDirectory pointer to raw data fixed up from: 0x{:X} to 0x{:X}",
|
||||
dd.image_debug_directory.pointer_to_raw_data,
|
||||
dd.image_debug_directory
|
||||
.pointer_to_raw_data
|
||||
.wrapping_sub(rva_offset),
|
||||
);
|
||||
dd.image_debug_directory.pointer_to_raw_data = dd
|
||||
.image_debug_directory
|
||||
.pointer_to_raw_data
|
||||
.wrapping_sub(rva_offset);
|
||||
}
|
||||
}
|
||||
|
||||
/// An analyzed COFF object
|
||||
#[derive(Debug)]
|
||||
pub struct Coff<'a> {
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
# TE binaries
|
||||
|
||||
Binaries located in this directory are precompiled PE32/PE32+ binaries using a
|
||||
terse executable (TE) header as defined in the Platform Initialization (PI)
|
||||
specification: [TE](https://uefi.org/specs/PI/1.8/V1_TE_Image.html#te-header).
|
||||
These binaries were compiled using the
|
||||
[EDK2](https://github.com/tianocore/edk2) build system.
|
||||
|
||||
## test_image.te
|
||||
|
||||
This binary is a simple Terse executable binary
|
||||
|
||||
## test_image_loaded.bin
|
||||
|
||||
This binary is the same as `test_image.te`, but it has been loaded by a loader,
|
||||
meaning the sections have been placed in the expected address. Please note that
|
||||
this particular binary has not been relocated, so no relocations have been
|
||||
applied
|
||||
|
||||
## test_image_relocated.bin
|
||||
|
||||
This binary is the same as `test_image.te`, but it has been loaded by a loader,
|
||||
meaning the sections have been placed in the expected address, and any any
|
||||
relocations have been applied.
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,56 @@
|
|||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.2.158](https://github.com/rust-lang/libc/compare/0.2.157...0.2.158) - 2024-08-19
|
||||
|
||||
### Other
|
||||
- WASI: fix missing `Iterator` with `rustc-dep-of-std` in <https://github.com/rust-lang/libc/pull/3856#event-13924913068>
|
||||
|
||||
## [0.2.157](https://github.com/rust-lang/libc/compare/0.2.156...0.2.157) - 2024-08-17
|
||||
|
||||
### Added
|
||||
|
||||
- Apple: add `_NSGetArgv`, `_NSGetArgc` and `_NSGetProgname` in <https://github.com/rust-lang/libc/pull/3702>
|
||||
- Build: add `RUSTC_WRAPPER` support in <https://github.com/rust-lang/libc/pull/3845>
|
||||
- FreeBSD: add `execvpe` support from 14.1 release in <https://github.com/rust-lang/libc/pull/3745>
|
||||
- Fuchsia: add `SO_BINDTOIFINDEX`
|
||||
- Linux: add `klogctl` in <https://github.com/rust-lang/libc/pull/3777>
|
||||
- MacOS: add `fcntl` OFD commands in <https://github.com/rust-lang/libc/pull/3563>
|
||||
- NetBSD: add `_lwp_park` in <https://github.com/rust-lang/libc/pull/3721>
|
||||
- Solaris: add missing networking support in <https://github.com/rust-lang/libc/pull/3717>
|
||||
- Unix: add `pthread_equal` in <https://github.com/rust-lang/libc/pull/3773>
|
||||
- WASI: add `select`, `FD_SET`, `FD_ZERO`, `FD_ISSET ` in <https://github.com/rust-lang/libc/pull/3681>
|
||||
|
||||
### Fixed
|
||||
- TEEOS: fix octal notation for `O_*` constants in <https://github.com/rust-lang/libc/pull/3841>
|
||||
|
||||
### Changed
|
||||
- FreeBSD: always use freebsd12 when `rustc_dep_of_std` is set in <https://github.com/rust-lang/libc/pull/3723>
|
||||
|
||||
## [0.2.156](https://github.com/rust-lang/libc/compare/v0.2.155...v0.2.156) - 2024-08-15
|
||||
|
||||
### Added
|
||||
- Apple: add `F_ALLOCATEPERSIST` in <https://github.com/rust-lang/libc/pull/3712>
|
||||
- Apple: add `os_sync_wait_on_address` and related definitions in <https://github.com/rust-lang/libc/pull/3769>
|
||||
- BSD: generalise `IPV6_DONTFRAG` to all BSD targets in <https://github.com/rust-lang/libc/pull/3716>
|
||||
- FreeBSD/DragonFly: add `IP_RECVTTL`/`IPV6_RECVHOPLIMIT` in <https://github.com/rust-lang/libc/pull/3751>
|
||||
- Hurd: add `XATTR_CREATE`, `XATTR_REPLACE` in <https://github.com/rust-lang/libc/pull/3739>
|
||||
- Linux GNU: `confstr` API and `_CS_*` in <https://github.com/rust-lang/libc/pull/3771>
|
||||
- Linux musl: add `preadv2` and `pwritev2` (1.2.5 min.) in <https://github.com/rust-lang/libc/pull/3762>
|
||||
- VxWorks: add the constant `SOMAXCONN` in <https://github.com/rust-lang/libc/pull/3761>
|
||||
- VxWorks: add a few errnoLib related constants in <https://github.com/rust-lang/libc/pull/3780>
|
||||
|
||||
### Fixed
|
||||
- Solaris/illumos: Change `ifa_flags` type to u64 in <https://github.com/rust-lang/libc/pull/3729>
|
||||
- QNX 7.0: Disable `libregex` in <https://github.com/rust-lang/libc/pull/3775>
|
||||
|
||||
### Changed
|
||||
- QNX NTO: update platform support in <https://github.com/rust-lang/libc/pull/3815>
|
||||
- `addr_of!(EXTERN_STATIC)` is now considered safe in <https://github.com/rust-lang/libc/pull/3776>
|
||||
|
||||
### Removed
|
||||
- Apple: remove `rmx_state` in <https://github.com/rust-lang/libc/pull/3776>
|
||||
|
||||
### Other
|
||||
- Update or remove CI tests that have been failing
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
[package]
|
||||
name = "libc"
|
||||
version = "0.2.153"
|
||||
version = "0.2.158"
|
||||
authors = ["The Rust Project Developers"]
|
||||
build = "build.rs"
|
||||
exclude = [
|
||||
|
@ -20,6 +20,10 @@ exclude = [
|
|||
"/.cirrus.yml",
|
||||
"/triagebot.toml",
|
||||
]
|
||||
autobins = false
|
||||
autoexamples = false
|
||||
autotests = false
|
||||
autobenches = false
|
||||
description = """
|
||||
Raw FFI bindings to platform libraries like libc.
|
||||
"""
|
||||
|
@ -76,7 +80,6 @@ targets = [
|
|||
"armv7-wrs-vxworks-eabihf",
|
||||
"armv7r-none-eabi",
|
||||
"armv7r-none-eabihf",
|
||||
"hexagon-unknown-linux-musl",
|
||||
"i586-pc-windows-msvc",
|
||||
"i586-unknown-linux-gnu",
|
||||
"i586-unknown-linux-musl",
|
||||
|
@ -158,6 +161,14 @@ targets = [
|
|||
"x86_64-wrs-vxworks",
|
||||
]
|
||||
|
||||
[lib]
|
||||
name = "libc"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[test]]
|
||||
name = "const_fn"
|
||||
path = "tests/const_fn.rs"
|
||||
|
||||
[dependencies.rustc-std-workspace-core]
|
||||
version = "1.0.0"
|
||||
optional = true
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use std::env;
|
||||
use std::process::Command;
|
||||
use std::str;
|
||||
use std::string::String;
|
||||
|
||||
// List of cfgs this build script is allowed to set. The list is needed to support check-cfg, as we
|
||||
// need to know all the possible cfgs that this script will set. If you need to set another cfg
|
||||
// make sure to add it to this list as well.
|
||||
const ALLOWED_CFGS: &'static [&'static str] = &[
|
||||
"emscripten_new_stat_abi",
|
||||
"espidf_time64",
|
||||
"freebsd10",
|
||||
"freebsd11",
|
||||
"freebsd12",
|
||||
|
@ -34,7 +34,7 @@ const ALLOWED_CFGS: &'static [&'static str] = &[
|
|||
|
||||
// Extra values to allow for check-cfg.
|
||||
const CHECK_CFG_EXTRA: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("target_os", &["switch", "aix", "ohos", "hurd"]),
|
||||
("target_os", &["switch", "aix", "ohos", "hurd", "visionos"]),
|
||||
("target_env", &["illumos", "wasi", "aix", "ohos"]),
|
||||
(
|
||||
"target_arch",
|
||||
|
@ -51,7 +51,7 @@ fn main() {
|
|||
let align_cargo_feature = env::var("CARGO_FEATURE_ALIGN").is_ok();
|
||||
let const_extern_fn_cargo_feature = env::var("CARGO_FEATURE_CONST_EXTERN_FN").is_ok();
|
||||
let libc_ci = env::var("LIBC_CI").is_ok();
|
||||
let libc_check_cfg = env::var("LIBC_CHECK_CFG").is_ok();
|
||||
let libc_check_cfg = env::var("LIBC_CHECK_CFG").is_ok() || rustc_minor_ver >= 80;
|
||||
|
||||
if env::var("CARGO_FEATURE_USE_STD").is_ok() {
|
||||
println!(
|
||||
|
@ -65,14 +65,21 @@ fn main() {
|
|||
//
|
||||
// On CI, we detect the actual FreeBSD version and match its ABI exactly,
|
||||
// running tests to ensure that the ABI is correct.
|
||||
match which_freebsd() {
|
||||
Some(10) if libc_ci => set_cfg("freebsd10"),
|
||||
Some(11) if libc_ci => set_cfg("freebsd11"),
|
||||
Some(12) if libc_ci || rustc_dep_of_std => set_cfg("freebsd12"),
|
||||
Some(13) if libc_ci => set_cfg("freebsd13"),
|
||||
Some(14) if libc_ci => set_cfg("freebsd14"),
|
||||
Some(15) if libc_ci => set_cfg("freebsd15"),
|
||||
Some(_) | None => set_cfg("freebsd11"),
|
||||
let which_freebsd = if libc_ci {
|
||||
which_freebsd().unwrap_or(11)
|
||||
} else if rustc_dep_of_std {
|
||||
12
|
||||
} else {
|
||||
11
|
||||
};
|
||||
match which_freebsd {
|
||||
x if x < 10 => panic!("FreeBSD older than 10 is not supported"),
|
||||
10 => set_cfg("freebsd10"),
|
||||
11 => set_cfg("freebsd11"),
|
||||
12 => set_cfg("freebsd12"),
|
||||
13 => set_cfg("freebsd13"),
|
||||
14 => set_cfg("freebsd14"),
|
||||
_ => set_cfg("freebsd15"),
|
||||
}
|
||||
|
||||
match emcc_version_code() {
|
||||
|
@ -196,8 +203,17 @@ fn rustc_minor_nightly() -> (u32, bool) {
|
|||
};
|
||||
}
|
||||
|
||||
let rustc = otry!(env::var_os("RUSTC"));
|
||||
let output = Command::new(rustc)
|
||||
let rustc = env::var_os("RUSTC").expect("Failed to get rustc version: missing RUSTC env");
|
||||
let mut cmd = match env::var_os("RUSTC_WRAPPER").as_ref() {
|
||||
Some(wrapper) if !wrapper.is_empty() => {
|
||||
let mut cmd = Command::new(wrapper);
|
||||
cmd.arg(rustc);
|
||||
cmd
|
||||
}
|
||||
_ => Command::new(rustc),
|
||||
};
|
||||
|
||||
let output = cmd
|
||||
.arg("--version")
|
||||
.output()
|
||||
.ok()
|
||||
|
|
|
@ -1334,9 +1334,9 @@ pub const GRPQUOTA: ::c_int = 1;
|
|||
|
||||
pub const SIGIOT: ::c_int = 6;
|
||||
|
||||
pub const S_ISUID: ::c_int = 0x800;
|
||||
pub const S_ISGID: ::c_int = 0x400;
|
||||
pub const S_ISVTX: ::c_int = 0x200;
|
||||
pub const S_ISUID: ::mode_t = 0o4000;
|
||||
pub const S_ISGID: ::mode_t = 0o2000;
|
||||
pub const S_ISVTX: ::mode_t = 0o1000;
|
||||
|
||||
pub const IF_NAMESIZE: ::size_t = 16;
|
||||
pub const IFNAMSIZ: ::size_t = IF_NAMESIZE;
|
||||
|
@ -2981,6 +2981,7 @@ pub const SO_MARK: ::c_int = 36;
|
|||
pub const SO_RXQ_OVFL: ::c_int = 40;
|
||||
pub const SO_PEEK_OFF: ::c_int = 42;
|
||||
pub const SO_BUSY_POLL: ::c_int = 46;
|
||||
pub const SO_BINDTOIFINDEX: ::c_int = 62;
|
||||
|
||||
pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56;
|
||||
pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
|
||||
|
|
|
@ -0,0 +1,446 @@
|
|||
//! Hermit C type definitions
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] {
|
||||
pub type c_char = u8;
|
||||
} else {
|
||||
pub type c_char = i8;
|
||||
}
|
||||
}
|
||||
|
||||
pub type c_schar = i8;
|
||||
pub type c_uchar = u8;
|
||||
pub type c_short = i16;
|
||||
pub type c_ushort = u16;
|
||||
pub type c_int = i32;
|
||||
pub type c_uint = u32;
|
||||
pub type c_long = i64;
|
||||
pub type c_ulong = u64;
|
||||
pub type c_longlong = i64;
|
||||
pub type c_ulonglong = u64;
|
||||
pub type intmax_t = i64;
|
||||
pub type uintmax_t = u64;
|
||||
pub type intptr_t = isize;
|
||||
pub type uintptr_t = usize;
|
||||
|
||||
pub type c_float = f32;
|
||||
pub type c_double = f64;
|
||||
|
||||
pub type size_t = usize;
|
||||
pub type ssize_t = isize;
|
||||
pub type ptrdiff_t = isize;
|
||||
|
||||
pub type clockid_t = i32;
|
||||
pub type in_addr_t = u32;
|
||||
pub type in_port_t = u16;
|
||||
pub type mode_t = u32;
|
||||
pub type nfds_t = usize;
|
||||
pub type pid_t = i32;
|
||||
pub type sa_family_t = u8;
|
||||
pub type socklen_t = u32;
|
||||
pub type time_t = i64;
|
||||
|
||||
s! {
|
||||
pub struct addrinfo {
|
||||
pub ai_flags: i32,
|
||||
pub ai_family: i32,
|
||||
pub ai_socktype: i32,
|
||||
pub ai_protocol: i32,
|
||||
pub ai_addrlen: socklen_t,
|
||||
pub ai_canonname: *mut c_char,
|
||||
pub ai_addr: *mut sockaddr,
|
||||
pub ai_next: *mut addrinfo,
|
||||
}
|
||||
|
||||
pub struct dirent64 {
|
||||
pub d_ino: u64,
|
||||
pub d_off: i64,
|
||||
pub d_reclen: u16,
|
||||
pub d_type: u8,
|
||||
pub d_name: [c_char; 256],
|
||||
}
|
||||
|
||||
#[repr(align(4))]
|
||||
pub struct in6_addr {
|
||||
pub s6_addr: [u8; 16],
|
||||
}
|
||||
|
||||
pub struct in_addr {
|
||||
pub s_addr: in_addr_t,
|
||||
}
|
||||
|
||||
pub struct iovec {
|
||||
iov_base: *mut c_void,
|
||||
iov_len: usize,
|
||||
}
|
||||
|
||||
pub struct pollfd {
|
||||
pub fd: i32,
|
||||
pub events: i16,
|
||||
pub revents: i16,
|
||||
}
|
||||
|
||||
pub struct sockaddr {
|
||||
pub sa_len: u8,
|
||||
pub sa_family: sa_family_t,
|
||||
pub sa_data: [c_char; 14],
|
||||
}
|
||||
|
||||
pub struct sockaddr_in {
|
||||
pub sin_len: u8,
|
||||
pub sin_family: sa_family_t,
|
||||
pub sin_port: in_port_t,
|
||||
pub sin_addr: in_addr,
|
||||
pub sin_zero: [c_char; 8],
|
||||
}
|
||||
|
||||
pub struct sockaddr_in6 {
|
||||
pub sin6_len: u8,
|
||||
pub sin6_family: sa_family_t,
|
||||
pub sin6_port: in_port_t,
|
||||
pub sin6_flowinfo: u32,
|
||||
pub sin6_addr: in6_addr,
|
||||
pub sin6_scope_id: u32,
|
||||
}
|
||||
|
||||
pub struct sockaddr_storage {
|
||||
pub ss_len: u8,
|
||||
pub ss_family: sa_family_t,
|
||||
__ss_pad1: [u8; 6],
|
||||
__ss_align: i64,
|
||||
__ss_pad2: [u8; 112],
|
||||
}
|
||||
|
||||
pub struct stat {
|
||||
pub st_dev: u64,
|
||||
pub st_ino: u64,
|
||||
pub st_nlink: u64,
|
||||
pub st_mode: mode_t,
|
||||
pub st_uid: u32,
|
||||
pub st_gid: u32,
|
||||
pub st_rdev: u64,
|
||||
pub st_size: u64,
|
||||
pub st_blksize: i64,
|
||||
pub st_blocks: i64,
|
||||
pub st_atim: timespec,
|
||||
pub st_mtim: timespec,
|
||||
pub st_ctim: timespec,
|
||||
}
|
||||
|
||||
pub struct timespec {
|
||||
pub tv_sec: time_t,
|
||||
pub tv_nsec: i32,
|
||||
}
|
||||
}
|
||||
|
||||
pub const AF_INET: i32 = 0;
|
||||
pub const AF_INET6: i32 = 1;
|
||||
|
||||
pub const CLOCK_REALTIME: clockid_t = 1;
|
||||
pub const CLOCK_MONOTONIC: clockid_t = 4;
|
||||
|
||||
pub const DT_UNKNOWN: u8 = 0;
|
||||
pub const DT_FIFO: u8 = 1;
|
||||
pub const DT_CHR: u8 = 2;
|
||||
pub const DT_DIR: u8 = 4;
|
||||
pub const DT_BLK: u8 = 6;
|
||||
pub const DT_REG: u8 = 8;
|
||||
pub const DT_LNK: u8 = 10;
|
||||
pub const DT_SOCK: u8 = 12;
|
||||
pub const DT_WHT: u8 = 14;
|
||||
|
||||
pub const EAI_AGAIN: i32 = 2;
|
||||
pub const EAI_BADFLAGS: i32 = 3;
|
||||
pub const EAI_FAIL: i32 = 4;
|
||||
pub const EAI_FAMILY: i32 = 5;
|
||||
pub const EAI_MEMORY: i32 = 6;
|
||||
pub const EAI_NODATA: i32 = 7;
|
||||
pub const EAI_NONAME: i32 = 8;
|
||||
pub const EAI_SERVICE: i32 = 9;
|
||||
pub const EAI_SOCKTYPE: i32 = 10;
|
||||
pub const EAI_SYSTEM: i32 = 11;
|
||||
pub const EAI_OVERFLOW: i32 = 14;
|
||||
|
||||
pub const EFD_SEMAPHORE: i16 = 0o1;
|
||||
pub const EFD_NONBLOCK: i16 = 0o4000;
|
||||
pub const EFD_CLOEXEC: i16 = 0o40000;
|
||||
|
||||
pub const F_DUPFD: i32 = 0;
|
||||
pub const F_GETFD: i32 = 1;
|
||||
pub const F_SETFD: i32 = 2;
|
||||
pub const F_GETFL: i32 = 3;
|
||||
pub const F_SETFL: i32 = 4;
|
||||
|
||||
pub const FD_CLOEXEC: i32 = 1;
|
||||
|
||||
pub const FIONBIO: i32 = 0x8008667e;
|
||||
|
||||
pub const FUTEX_RELATIVE_TIMEOUT: u32 = 1;
|
||||
|
||||
pub const IP_TOS: i32 = 1;
|
||||
pub const IP_TTL: i32 = 2;
|
||||
pub const IP_ADD_MEMBERSHIP: i32 = 3;
|
||||
pub const IP_DROP_MEMBERSHIP: i32 = 4;
|
||||
pub const IP_MULTICAST_TTL: i32 = 5;
|
||||
pub const IP_MULTICAST_LOOP: i32 = 7;
|
||||
|
||||
pub const IPPROTO_IP: i32 = 0;
|
||||
pub const IPPROTO_TCP: i32 = 6;
|
||||
pub const IPPROTO_UDP: i32 = 17;
|
||||
pub const IPPROTO_IPV6: i32 = 41;
|
||||
|
||||
pub const IPV6_ADD_MEMBERSHIP: i32 = 12;
|
||||
pub const IPV6_DROP_MEMBERSHIP: i32 = 13;
|
||||
pub const IPV6_MULTICAST_LOOP: i32 = 19;
|
||||
pub const IPV6_V6ONLY: i32 = 27;
|
||||
|
||||
pub const MSG_PEEK: i32 = 1;
|
||||
|
||||
pub const O_RDONLY: i32 = 0o0;
|
||||
pub const O_WRONLY: i32 = 0o1;
|
||||
pub const O_RDWR: i32 = 0o2;
|
||||
pub const O_CREAT: i32 = 0o100;
|
||||
pub const O_EXCL: i32 = 0o200;
|
||||
pub const O_TRUNC: i32 = 0o1000;
|
||||
pub const O_APPEND: i32 = 0o2000;
|
||||
pub const O_NONBLOCK: i32 = 0o4000;
|
||||
pub const O_DIRECTORY: i32 = 0o200000;
|
||||
|
||||
pub const POLLIN: i16 = 0x1;
|
||||
pub const POLLPRI: i16 = 0x2;
|
||||
pub const POLLOUT: i16 = 0x4;
|
||||
pub const POLLERR: i16 = 0x8;
|
||||
pub const POLLHUP: i16 = 0x10;
|
||||
pub const POLLNVAL: i16 = 0x20;
|
||||
pub const POLLRDNORM: i16 = 0x040;
|
||||
pub const POLLRDBAND: i16 = 0x080;
|
||||
pub const POLLWRNORM: i16 = 0x0100;
|
||||
pub const POLLWRBAND: i16 = 0x0200;
|
||||
pub const POLLRDHUP: i16 = 0x2000;
|
||||
|
||||
pub const S_IRWXU: mode_t = 0o0700;
|
||||
pub const S_IRUSR: mode_t = 0o0400;
|
||||
pub const S_IWUSR: mode_t = 0o0200;
|
||||
pub const S_IXUSR: mode_t = 0o0100;
|
||||
pub const S_IRWXG: mode_t = 0o0070;
|
||||
pub const S_IRGRP: mode_t = 0o0040;
|
||||
pub const S_IWGRP: mode_t = 0o0020;
|
||||
pub const S_IXGRP: mode_t = 0o0010;
|
||||
pub const S_IRWXO: mode_t = 0o0007;
|
||||
pub const S_IROTH: mode_t = 0o0004;
|
||||
pub const S_IWOTH: mode_t = 0o0002;
|
||||
pub const S_IXOTH: mode_t = 0o0001;
|
||||
|
||||
pub const S_IFMT: mode_t = 0o17_0000;
|
||||
pub const S_IFSOCK: mode_t = 0o14_0000;
|
||||
pub const S_IFLNK: mode_t = 0o12_0000;
|
||||
pub const S_IFREG: mode_t = 0o10_0000;
|
||||
pub const S_IFBLK: mode_t = 0o6_0000;
|
||||
pub const S_IFDIR: mode_t = 0o4_0000;
|
||||
pub const S_IFCHR: mode_t = 0o2_0000;
|
||||
pub const S_IFIFO: mode_t = 0o1_0000;
|
||||
|
||||
pub const SHUT_RD: i32 = 0;
|
||||
pub const SHUT_WR: i32 = 1;
|
||||
pub const SHUT_RDWR: i32 = 2;
|
||||
|
||||
pub const SO_REUSEADDR: i32 = 0x0004;
|
||||
pub const SO_KEEPALIVE: i32 = 0x0008;
|
||||
pub const SO_BROADCAST: i32 = 0x0020;
|
||||
pub const SO_LINGER: i32 = 0x0080;
|
||||
pub const SO_SNDBUF: i32 = 0x1001;
|
||||
pub const SO_RCVBUF: i32 = 0x1002;
|
||||
pub const SO_SNDTIMEO: i32 = 0x1005;
|
||||
pub const SO_RCVTIMEO: i32 = 0x1006;
|
||||
pub const SO_ERROR: i32 = 0x1007;
|
||||
|
||||
pub const SOCK_STREAM: i32 = 1;
|
||||
pub const SOCK_DGRAM: i32 = 2;
|
||||
pub const SOCK_NONBLOCK: i32 = 0o4000;
|
||||
pub const SOCK_CLOEXEC: i32 = 0o40000;
|
||||
|
||||
pub const SOL_SOCKET: i32 = 4095;
|
||||
|
||||
pub const STDIN_FILENO: c_int = 0;
|
||||
pub const STDOUT_FILENO: c_int = 1;
|
||||
pub const STDERR_FILENO: c_int = 2;
|
||||
|
||||
pub const TCP_NODELAY: i32 = 1;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "sys_alloc"]
|
||||
pub fn alloc(size: usize, align: usize) -> *mut u8;
|
||||
|
||||
#[link_name = "sys_alloc_zeroed"]
|
||||
pub fn alloc_zeroed(size: usize, align: usize) -> *mut u8;
|
||||
|
||||
#[link_name = "sys_realloc"]
|
||||
pub fn realloc(ptr: *mut u8, size: usize, align: usize, new_size: usize) -> *mut u8;
|
||||
|
||||
#[link_name = "sys_dealloc"]
|
||||
pub fn dealloc(ptr: *mut u8, size: usize, align: usize);
|
||||
|
||||
#[link_name = "sys_exit"]
|
||||
pub fn exit(status: i32) -> !;
|
||||
|
||||
#[link_name = "sys_abort"]
|
||||
pub fn abort() -> !;
|
||||
|
||||
#[link_name = "sys_errno"]
|
||||
pub fn errno() -> i32;
|
||||
|
||||
#[link_name = "sys_clock_gettime"]
|
||||
pub fn clock_gettime(clockid: clockid_t, tp: *mut timespec) -> i32;
|
||||
|
||||
#[link_name = "sys_nanosleep"]
|
||||
pub fn nanosleep(req: *const timespec) -> i32;
|
||||
|
||||
#[link_name = "sys_available_parallelism"]
|
||||
pub fn available_parallelism() -> usize;
|
||||
|
||||
#[link_name = "sys_futex_wait"]
|
||||
pub fn futex_wait(
|
||||
address: *mut u32,
|
||||
expected: u32,
|
||||
timeout: *const timespec,
|
||||
flags: u32,
|
||||
) -> i32;
|
||||
|
||||
#[link_name = "sys_futex_wake"]
|
||||
pub fn futex_wake(address: *mut u32, count: i32) -> i32;
|
||||
|
||||
#[link_name = "sys_stat"]
|
||||
pub fn stat(path: *const c_char, stat: *mut stat) -> i32;
|
||||
|
||||
#[link_name = "sys_fstat"]
|
||||
pub fn fstat(fd: i32, stat: *mut stat) -> i32;
|
||||
|
||||
#[link_name = "sys_lstat"]
|
||||
pub fn lstat(path: *const c_char, stat: *mut stat) -> i32;
|
||||
|
||||
#[link_name = "sys_open"]
|
||||
pub fn open(path: *const c_char, flags: i32, mode: mode_t) -> i32;
|
||||
|
||||
#[link_name = "sys_unlink"]
|
||||
pub fn unlink(path: *const c_char) -> i32;
|
||||
|
||||
#[link_name = "sys_mkdir"]
|
||||
pub fn mkdir(path: *const c_char, mode: mode_t) -> i32;
|
||||
|
||||
#[link_name = "sys_rmdir"]
|
||||
pub fn rmdir(path: *const c_char) -> i32;
|
||||
|
||||
#[link_name = "sys_read"]
|
||||
pub fn read(fd: i32, buf: *mut u8, len: usize) -> isize;
|
||||
|
||||
#[link_name = "sys_write"]
|
||||
pub fn write(fd: i32, buf: *const u8, len: usize) -> isize;
|
||||
|
||||
#[link_name = "sys_readv"]
|
||||
pub fn readv(fd: i32, iov: *const iovec, iovcnt: usize) -> isize;
|
||||
|
||||
#[link_name = "sys_writev"]
|
||||
pub fn writev(fd: i32, iov: *const iovec, iovcnt: usize) -> isize;
|
||||
|
||||
#[link_name = "sys_close"]
|
||||
pub fn close(fd: i32) -> i32;
|
||||
|
||||
#[link_name = "sys_dup"]
|
||||
pub fn dup(fd: i32) -> i32;
|
||||
|
||||
#[link_name = "sys_fcntl"]
|
||||
pub fn fcntl(fd: i32, cmd: i32, arg: i32) -> i32;
|
||||
|
||||
#[link_name = "sys_getdents64"]
|
||||
pub fn getdents64(fd: i32, dirp: *mut dirent64, count: usize) -> isize;
|
||||
|
||||
#[link_name = "sys_getaddrinfo"]
|
||||
pub fn getaddrinfo(
|
||||
nodename: *const c_char,
|
||||
servname: *const c_char,
|
||||
hints: *const addrinfo,
|
||||
res: *mut *mut addrinfo,
|
||||
) -> i32;
|
||||
|
||||
#[link_name = "sys_freeaddrinfo"]
|
||||
pub fn freeaddrinfo(ai: *mut addrinfo);
|
||||
|
||||
#[link_name = "sys_socket"]
|
||||
pub fn socket(domain: i32, ty: i32, protocol: i32) -> i32;
|
||||
|
||||
#[link_name = "sys_bind"]
|
||||
pub fn bind(sockfd: i32, addr: *const sockaddr, addrlen: socklen_t) -> i32;
|
||||
|
||||
#[link_name = "sys_listen"]
|
||||
pub fn listen(sockfd: i32, backlog: i32) -> i32;
|
||||
|
||||
#[link_name = "sys_accept"]
|
||||
pub fn accept(sockfd: i32, addr: *mut sockaddr, addrlen: *mut socklen_t) -> i32;
|
||||
|
||||
#[link_name = "sys_connect"]
|
||||
pub fn connect(sockfd: i32, addr: *const sockaddr, addrlen: socklen_t) -> i32;
|
||||
|
||||
#[link_name = "sys_recv"]
|
||||
pub fn recv(sockfd: i32, buf: *mut u8, len: usize, flags: i32) -> isize;
|
||||
|
||||
#[link_name = "sys_recvfrom"]
|
||||
pub fn recvfrom(
|
||||
sockfd: i32,
|
||||
buf: *mut c_void,
|
||||
len: usize,
|
||||
flags: i32,
|
||||
addr: *mut sockaddr,
|
||||
addrlen: *mut socklen_t,
|
||||
) -> isize;
|
||||
|
||||
#[link_name = "sys_send"]
|
||||
pub fn send(sockfd: i32, buf: *const c_void, len: usize, flags: i32) -> isize;
|
||||
|
||||
#[link_name = "sys_sendto"]
|
||||
pub fn sendto(
|
||||
sockfd: i32,
|
||||
buf: *const c_void,
|
||||
len: usize,
|
||||
flags: i32,
|
||||
to: *const sockaddr,
|
||||
tolen: socklen_t,
|
||||
) -> isize;
|
||||
|
||||
#[link_name = "sys_getpeername"]
|
||||
pub fn getpeername(sockfd: i32, addr: *mut sockaddr, addrlen: *mut socklen_t) -> i32;
|
||||
|
||||
#[link_name = "sys_getsockname"]
|
||||
pub fn getsockname(sockfd: i32, addr: *mut sockaddr, addrlen: *mut socklen_t) -> i32;
|
||||
|
||||
#[link_name = "sys_getsockopt"]
|
||||
pub fn getsockopt(
|
||||
sockfd: i32,
|
||||
level: i32,
|
||||
optname: i32,
|
||||
optval: *mut c_void,
|
||||
optlen: *mut socklen_t,
|
||||
) -> i32;
|
||||
|
||||
#[link_name = "sys_setsockopt"]
|
||||
pub fn setsockopt(
|
||||
sockfd: i32,
|
||||
level: i32,
|
||||
optname: i32,
|
||||
optval: *const c_void,
|
||||
optlen: socklen_t,
|
||||
) -> i32;
|
||||
|
||||
#[link_name = "sys_ioctl"]
|
||||
pub fn ioctl(sockfd: i32, cmd: i32, argp: *mut c_void) -> i32;
|
||||
|
||||
#[link_name = "sys_shutdown"]
|
||||
pub fn shutdown(sockfd: i32, how: i32) -> i32;
|
||||
|
||||
#[link_name = "sys_eventfd"]
|
||||
pub fn eventfd(initval: u64, flags: i16) -> i32;
|
||||
|
||||
#[link_name = "sys_poll"]
|
||||
pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: i32) -> i32;
|
||||
}
|
||||
|
||||
pub use ffi::c_void;
|
|
@ -1,2 +0,0 @@
|
|||
pub type c_char = u8;
|
||||
pub type wchar_t = u32;
|
|
@ -1,61 +0,0 @@
|
|||
//! Hermit C types definition
|
||||
|
||||
pub type c_schar = i8;
|
||||
pub type c_uchar = u8;
|
||||
pub type c_short = i16;
|
||||
pub type c_ushort = u16;
|
||||
pub type c_int = i32;
|
||||
pub type c_uint = u32;
|
||||
pub type c_float = f32;
|
||||
pub type c_double = f64;
|
||||
pub type c_longlong = i64;
|
||||
pub type c_ulonglong = u64;
|
||||
pub type intmax_t = i64;
|
||||
pub type uintmax_t = u64;
|
||||
|
||||
pub type size_t = usize;
|
||||
pub type ptrdiff_t = isize;
|
||||
pub type intptr_t = isize;
|
||||
pub type uintptr_t = usize;
|
||||
pub type ssize_t = isize;
|
||||
|
||||
pub type c_long = i64;
|
||||
pub type c_ulong = u64;
|
||||
|
||||
pub type wint_t = u32;
|
||||
pub type wctype_t = i64;
|
||||
|
||||
pub type regoff_t = size_t;
|
||||
pub type off_t = c_long;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch = "aarch64")] {
|
||||
mod aarch64;
|
||||
pub use self::aarch64::*;
|
||||
} else if #[cfg(target_arch = "x86_64")] {
|
||||
mod x86_64;
|
||||
pub use self::x86_64::*;
|
||||
} else {
|
||||
// Unknown target_arch
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(libc_core_cvoid)] {
|
||||
pub use ::ffi::c_void;
|
||||
} else {
|
||||
// Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help
|
||||
// enable more optimization opportunities around it recognizing things
|
||||
// like malloc/free.
|
||||
#[repr(u8)]
|
||||
#[allow(missing_copy_implementations)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub enum c_void {
|
||||
// Two dummy variants so the #[repr] attribute can be used.
|
||||
#[doc(hidden)]
|
||||
__variant1,
|
||||
#[doc(hidden)]
|
||||
__variant2,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
pub type c_char = i8;
|
||||
pub type wchar_t = i32;
|
|
@ -12,6 +12,10 @@
|
|||
redundant_semicolons,
|
||||
unused_macros,
|
||||
unused_macro_rules,
|
||||
// FIXME: temporarily allow dead_code to fix CI:
|
||||
// - https://github.com/rust-lang/libc/issues/3740
|
||||
// - https://github.com/rust-lang/rust/pull/126456
|
||||
dead_code,
|
||||
)]
|
||||
#![cfg_attr(libc_deny_warnings, deny(warnings))]
|
||||
// Attributes needed when building as part of the standard library
|
||||
|
|
|
@ -177,41 +177,41 @@ pub struct div_t {
|
|||
}
|
||||
|
||||
// fcntl
|
||||
pub const O_CREAT: u32 = 0100;
|
||||
pub const O_CREAT: u32 = 0o100;
|
||||
|
||||
pub const O_EXCL: u32 = 0200;
|
||||
pub const O_EXCL: u32 = 0o200;
|
||||
|
||||
pub const O_NOCTTY: u32 = 0400;
|
||||
pub const O_NOCTTY: u32 = 0o400;
|
||||
|
||||
pub const O_TRUNC: u32 = 01000;
|
||||
pub const O_TRUNC: u32 = 0o1000;
|
||||
|
||||
pub const O_APPEND: u32 = 02000;
|
||||
pub const O_APPEND: u32 = 0o2000;
|
||||
|
||||
pub const O_NONBLOCK: u32 = 04000;
|
||||
pub const O_NONBLOCK: u32 = 0o4000;
|
||||
|
||||
pub const O_DSYNC: u32 = 010000;
|
||||
pub const O_DSYNC: u32 = 0o10000;
|
||||
|
||||
pub const O_SYNC: u32 = 04010000;
|
||||
pub const O_SYNC: u32 = 0o4010000;
|
||||
|
||||
pub const O_RSYNC: u32 = 04010000;
|
||||
pub const O_RSYNC: u32 = 0o4010000;
|
||||
|
||||
pub const O_DIRECTORY: u32 = 0200000;
|
||||
pub const O_DIRECTORY: u32 = 0o200000;
|
||||
|
||||
pub const O_NOFOLLOW: u32 = 0400000;
|
||||
pub const O_NOFOLLOW: u32 = 0o400000;
|
||||
|
||||
pub const O_CLOEXEC: u32 = 02000000;
|
||||
pub const O_CLOEXEC: u32 = 0o2000000;
|
||||
|
||||
pub const O_ASYNC: u32 = 020000;
|
||||
pub const O_ASYNC: u32 = 0o20000;
|
||||
|
||||
pub const O_DIRECT: u32 = 040000;
|
||||
pub const O_DIRECT: u32 = 0o40000;
|
||||
|
||||
pub const O_LARGEFILE: u32 = 0100000;
|
||||
pub const O_LARGEFILE: u32 = 0o100000;
|
||||
|
||||
pub const O_NOATIME: u32 = 01000000;
|
||||
pub const O_NOATIME: u32 = 0o1000000;
|
||||
|
||||
pub const O_PATH: u32 = 010000000;
|
||||
pub const O_PATH: u32 = 0o10000000;
|
||||
|
||||
pub const O_TMPFILE: u32 = 020200000;
|
||||
pub const O_TMPFILE: u32 = 0o20200000;
|
||||
|
||||
pub const O_NDELAY: u32 = O_NONBLOCK;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pub type c_char = i8;
|
||||
pub type c_char = u8;
|
||||
pub type caddr_t = *mut ::c_char;
|
||||
pub type clockid_t = ::c_longlong;
|
||||
pub type blkcnt_t = ::c_long;
|
||||
|
@ -1210,6 +1210,7 @@ pub const TCP_KEEPCNT: ::c_int = 0x13;
|
|||
pub const TCP_NODELAYACK: ::c_int = 0x14;
|
||||
|
||||
// pthread.h
|
||||
pub const PTHREAD_BARRIER_SERIAL_THREAD: ::c_int = -1;
|
||||
pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0;
|
||||
pub const PTHREAD_CREATE_DETACHED: ::c_int = 1;
|
||||
pub const PTHREAD_PROCESS_SHARED: ::c_int = 0;
|
||||
|
|
|
@ -121,6 +121,11 @@ pub type pthread_introspection_hook_t =
|
|||
extern "C" fn(event: ::c_uint, thread: ::pthread_t, addr: *mut ::c_void, size: ::size_t);
|
||||
pub type pthread_jit_write_callback_t = ::Option<extern "C" fn(ctx: *mut ::c_void) -> ::c_int>;
|
||||
|
||||
pub type os_clockid_t = u32;
|
||||
|
||||
pub type os_sync_wait_on_address_flags_t = u32;
|
||||
pub type os_sync_wake_by_address_flags_t = u32;
|
||||
|
||||
pub type os_unfair_lock = os_unfair_lock_s;
|
||||
pub type os_unfair_lock_t = *mut os_unfair_lock;
|
||||
|
||||
|
@ -504,6 +509,8 @@ s! {
|
|||
pub rmx_rtt: u32,
|
||||
pub rmx_rttvar: u32,
|
||||
pub rmx_pksent: u32,
|
||||
/// This field does not exist anymore, the u32 is now part of a resized
|
||||
/// `rmx_filler` array.
|
||||
pub rmx_state: u32,
|
||||
pub rmx_filler: [u32; 3],
|
||||
}
|
||||
|
@ -3227,6 +3234,24 @@ pub const _PC_PIPE_BUF: ::c_int = 6;
|
|||
pub const _PC_CHOWN_RESTRICTED: ::c_int = 7;
|
||||
pub const _PC_NO_TRUNC: ::c_int = 8;
|
||||
pub const _PC_VDISABLE: ::c_int = 9;
|
||||
pub const _PC_NAME_CHARS_MAX: ::c_int = 10;
|
||||
pub const _PC_CASE_SENSITIVE: ::c_int = 11;
|
||||
pub const _PC_CASE_PRESERVING: ::c_int = 12;
|
||||
pub const _PC_EXTENDED_SECURITY_NP: ::c_int = 13;
|
||||
pub const _PC_AUTH_OPAQUE_NP: ::c_int = 14;
|
||||
pub const _PC_2_SYMLINKS: ::c_int = 15;
|
||||
pub const _PC_ALLOC_SIZE_MIN: ::c_int = 16;
|
||||
pub const _PC_ASYNC_IO: ::c_int = 17;
|
||||
pub const _PC_FILESIZEBITS: ::c_int = 18;
|
||||
pub const _PC_PRIO_IO: ::c_int = 19;
|
||||
pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 20;
|
||||
pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 21;
|
||||
pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 22;
|
||||
pub const _PC_REC_XFER_ALIGN: ::c_int = 23;
|
||||
pub const _PC_SYMLINK_MAX: ::c_int = 24;
|
||||
pub const _PC_SYNC_IO: ::c_int = 25;
|
||||
pub const _PC_XATTR_SIZE_BITS: ::c_int = 26;
|
||||
pub const _PC_MIN_HOLE_SIZE: ::c_int = 27;
|
||||
pub const O_EVTONLY: ::c_int = 0x00008000;
|
||||
pub const O_NOCTTY: ::c_int = 0x00020000;
|
||||
pub const O_DIRECTORY: ::c_int = 0x00100000;
|
||||
|
@ -3234,6 +3259,8 @@ pub const O_SYMLINK: ::c_int = 0x00200000;
|
|||
pub const O_DSYNC: ::c_int = 0x00400000;
|
||||
pub const O_CLOEXEC: ::c_int = 0x01000000;
|
||||
pub const O_NOFOLLOW_ANY: ::c_int = 0x20000000;
|
||||
pub const O_EXEC: ::c_int = 0x40000000;
|
||||
pub const O_SEARCH: ::c_int = O_EXEC | O_DIRECTORY;
|
||||
pub const S_IFIFO: mode_t = 4096;
|
||||
pub const S_IFCHR: mode_t = 8192;
|
||||
pub const S_IFBLK: mode_t = 24576;
|
||||
|
@ -3582,6 +3609,10 @@ pub const F_GLOBAL_NOCACHE: ::c_int = 55;
|
|||
pub const F_NODIRECT: ::c_int = 62;
|
||||
pub const F_LOG2PHYS_EXT: ::c_int = 65;
|
||||
pub const F_BARRIERFSYNC: ::c_int = 85;
|
||||
// See https://github.com/apple/darwin-xnu/blob/main/bsd/sys/fcntl.h
|
||||
pub const F_OFD_SETLK: ::c_int = 90; /* Acquire or release open file description lock */
|
||||
pub const F_OFD_SETLKW: ::c_int = 91; /* (as F_OFD_SETLK but blocking if conflicting lock) */
|
||||
pub const F_OFD_GETLK: ::c_int = 92; /* Examine OFD lock */
|
||||
pub const F_PUNCHHOLE: ::c_int = 99;
|
||||
pub const F_TRIM_ACTIVE_FILE: ::c_int = 100;
|
||||
pub const F_SPECULATIVE_READ: ::c_int = 101;
|
||||
|
@ -3589,6 +3620,7 @@ pub const F_GETPATH_NOFIRMLINK: ::c_int = 102;
|
|||
|
||||
pub const F_ALLOCATECONTIG: ::c_uint = 0x02;
|
||||
pub const F_ALLOCATEALL: ::c_uint = 0x04;
|
||||
pub const F_ALLOCATEPERSIST: ::c_uint = 0x08;
|
||||
|
||||
pub const F_PEOFPOSMODE: ::c_int = 3;
|
||||
pub const F_VOLPOSMODE: ::c_int = 4;
|
||||
|
@ -4132,7 +4164,6 @@ pub const IPV6_RECVHOPLIMIT: ::c_int = 37;
|
|||
pub const IPV6_PKTINFO: ::c_int = 46;
|
||||
pub const IPV6_HOPLIMIT: ::c_int = 47;
|
||||
pub const IPV6_RECVPKTINFO: ::c_int = 61;
|
||||
pub const IPV6_DONTFRAG: ::c_int = 62;
|
||||
pub const IP_ADD_SOURCE_MEMBERSHIP: ::c_int = 70;
|
||||
pub const IP_DROP_SOURCE_MEMBERSHIP: ::c_int = 71;
|
||||
pub const IP_BLOCK_SOURCE: ::c_int = 72;
|
||||
|
@ -5421,6 +5452,15 @@ pub const VOL_CAP_INT_RENAME_SWAP: attrgroup_t = 0x00040000;
|
|||
pub const VOL_CAP_INT_RENAME_EXCL: attrgroup_t = 0x00080000;
|
||||
pub const VOL_CAP_INT_RENAME_OPENFAIL: attrgroup_t = 0x00100000;
|
||||
|
||||
// os/clock.h
|
||||
pub const OS_CLOCK_MACH_ABSOLUTE_TIME: os_clockid_t = 32;
|
||||
|
||||
// os/os_sync_wait_on_address.h
|
||||
pub const OS_SYNC_WAIT_ON_ADDRESS_NONE: os_sync_wait_on_address_flags_t = 0x00000000;
|
||||
pub const OS_SYNC_WAIT_ON_ADDRESS_SHARED: os_sync_wait_on_address_flags_t = 0x00000001;
|
||||
pub const OS_SYNC_WAKE_BY_ADDRESS_NONE: os_sync_wake_by_address_flags_t = 0x00000000;
|
||||
pub const OS_SYNC_WAKE_BY_ADDRESS_SHARED: os_sync_wake_by_address_flags_t = 0x00000001;
|
||||
|
||||
// <proc.h>
|
||||
/// Process being created by fork.
|
||||
pub const SIDL: u32 = 1;
|
||||
|
@ -5814,6 +5854,40 @@ extern "C" {
|
|||
pub fn pthread_jit_write_freeze_callbacks_np();
|
||||
pub fn pthread_cpu_number_np(cpu_number_out: *mut ::size_t) -> ::c_int;
|
||||
|
||||
// Available starting with macOS 14.4.
|
||||
pub fn os_sync_wait_on_address(
|
||||
addr: *mut ::c_void,
|
||||
value: u64,
|
||||
size: ::size_t,
|
||||
flags: os_sync_wait_on_address_flags_t,
|
||||
) -> ::c_int;
|
||||
pub fn os_sync_wait_on_address_with_deadline(
|
||||
addr: *mut ::c_void,
|
||||
value: u64,
|
||||
size: ::size_t,
|
||||
flags: os_sync_wait_on_address_flags_t,
|
||||
clockid: os_clockid_t,
|
||||
deadline: u64,
|
||||
) -> ::c_int;
|
||||
pub fn os_sync_wait_on_address_with_timeout(
|
||||
addr: *mut ::c_void,
|
||||
value: u64,
|
||||
size: ::size_t,
|
||||
flags: os_sync_wait_on_address_flags_t,
|
||||
clockid: os_clockid_t,
|
||||
timeout_ns: u64,
|
||||
) -> ::c_int;
|
||||
pub fn os_sync_wake_by_address_any(
|
||||
addr: *mut ::c_void,
|
||||
size: ::size_t,
|
||||
flags: os_sync_wake_by_address_flags_t,
|
||||
) -> ::c_int;
|
||||
pub fn os_sync_wake_by_address_all(
|
||||
addr: *mut ::c_void,
|
||||
size: ::size_t,
|
||||
flags: os_sync_wake_by_address_flags_t,
|
||||
) -> ::c_int;
|
||||
|
||||
pub fn os_unfair_lock_lock(lock: os_unfair_lock_t);
|
||||
pub fn os_unfair_lock_trylock(lock: os_unfair_lock_t) -> bool;
|
||||
pub fn os_unfair_lock_unlock(lock: os_unfair_lock_t);
|
||||
|
@ -6303,7 +6377,12 @@ extern "C" {
|
|||
pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int;
|
||||
|
||||
pub fn _NSGetExecutablePath(buf: *mut ::c_char, bufsize: *mut u32) -> ::c_int;
|
||||
|
||||
// crt_externs.h
|
||||
pub fn _NSGetArgv() -> *mut *mut *mut ::c_char;
|
||||
pub fn _NSGetArgc() -> *mut ::c_int;
|
||||
pub fn _NSGetEnviron() -> *mut *mut *mut ::c_char;
|
||||
pub fn _NSGetProgname() -> *mut *mut ::c_char;
|
||||
|
||||
pub fn mach_vm_map(
|
||||
target_task: ::vm_map_t,
|
||||
|
@ -6475,7 +6554,7 @@ cfg_if! {
|
|||
}
|
||||
}
|
||||
cfg_if! {
|
||||
if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))] {
|
||||
if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "visionos"))] {
|
||||
extern "C" {
|
||||
pub fn memmem(
|
||||
haystack: *const ::c_void,
|
||||
|
|
|
@ -1637,6 +1637,23 @@ s_no_extra_traits! {
|
|||
pub cause: sctp_error_cause,
|
||||
pub hmac_id: u16,
|
||||
}
|
||||
|
||||
pub struct kinfo_file {
|
||||
pub kf_structsize: ::c_int,
|
||||
pub kf_type: ::c_int,
|
||||
pub kf_fd: ::c_int,
|
||||
pub kf_ref_count: ::c_int,
|
||||
pub kf_flags: ::c_int,
|
||||
_kf_pad0: ::c_int,
|
||||
pub kf_offset: i64,
|
||||
_priv: [::uintptr_t; 38], // FIXME if needed
|
||||
pub kf_status: u16,
|
||||
_kf_pad1: u16,
|
||||
_kf_ispare0: ::c_int,
|
||||
pub kf_cap_rights: ::cap_rights_t,
|
||||
_kf_cap_spare: u64,
|
||||
pub kf_path: [::c_char; ::PATH_MAX as usize],
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
|
@ -2593,6 +2610,52 @@ cfg_if! {
|
|||
{self.hmac_id}.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for kinfo_file {
|
||||
fn eq(&self, other: &kinfo_file) -> bool {
|
||||
self.kf_structsize == other.kf_structsize &&
|
||||
self.kf_type == other.kf_type &&
|
||||
self.kf_fd == other.kf_fd &&
|
||||
self.kf_ref_count == other.kf_ref_count &&
|
||||
self.kf_flags == other.kf_flags &&
|
||||
self.kf_offset == other.kf_offset &&
|
||||
self.kf_status == other.kf_status &&
|
||||
self.kf_cap_rights == other.kf_cap_rights &&
|
||||
self.kf_path
|
||||
.iter()
|
||||
.zip(other.kf_path.iter())
|
||||
.all(|(a,b)| a == b)
|
||||
}
|
||||
}
|
||||
impl Eq for kinfo_file {}
|
||||
impl ::fmt::Debug for kinfo_file {
|
||||
fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
|
||||
f.debug_struct("kinfo_file")
|
||||
.field("kf_structsize", &self.kf_structsize)
|
||||
.field("kf_type", &self.kf_type)
|
||||
.field("kf_fd", &self.kf_fd)
|
||||
.field("kf_ref_count", &self.kf_ref_count)
|
||||
.field("kf_flags", &self.kf_flags)
|
||||
.field("kf_offset", &self.kf_offset)
|
||||
.field("kf_status", &self.kf_status)
|
||||
.field("kf_cap_rights", &self.kf_cap_rights)
|
||||
.field("kf_path", &&self.kf_path[..])
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
impl ::hash::Hash for kinfo_file {
|
||||
fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
|
||||
self.kf_structsize.hash(state);
|
||||
self.kf_type.hash(state);
|
||||
self.kf_fd.hash(state);
|
||||
self.kf_ref_count.hash(state);
|
||||
self.kf_flags.hash(state);
|
||||
self.kf_offset.hash(state);
|
||||
self.kf_status.hash(state);
|
||||
self.kf_cap_rights.hash(state);
|
||||
self.kf_path.hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2618,6 +2681,129 @@ pub const LIO_VECTORED: ::c_int = 4;
|
|||
pub const LIO_WRITEV: ::c_int = 5;
|
||||
pub const LIO_READV: ::c_int = 6;
|
||||
|
||||
// sys/caprights.h
|
||||
pub const CAP_RIGHTS_VERSION_00: i32 = 0;
|
||||
pub const CAP_RIGHTS_VERSION: i32 = CAP_RIGHTS_VERSION_00;
|
||||
|
||||
// sys/capsicum.h
|
||||
macro_rules! cap_right {
|
||||
($idx:expr, $bit:expr) => {
|
||||
((1u64 << (57 + ($idx))) | ($bit))
|
||||
};
|
||||
}
|
||||
pub const CAP_READ: u64 = cap_right!(0, 0x0000000000000001u64);
|
||||
pub const CAP_WRITE: u64 = cap_right!(0, 0x0000000000000002u64);
|
||||
pub const CAP_SEEK_TELL: u64 = cap_right!(0, 0x0000000000000004u64);
|
||||
pub const CAP_SEEK: u64 = CAP_SEEK_TELL | 0x0000000000000008u64;
|
||||
pub const CAP_PREAD: u64 = CAP_SEEK | CAP_READ;
|
||||
pub const CAP_PWRITE: u64 = CAP_SEEK | CAP_WRITE;
|
||||
pub const CAP_MMAP: u64 = cap_right!(0, 0x0000000000000010u64);
|
||||
pub const CAP_MMAP_R: u64 = CAP_MMAP | CAP_SEEK | CAP_READ;
|
||||
pub const CAP_MMAP_W: u64 = CAP_MMAP | CAP_SEEK | CAP_WRITE;
|
||||
pub const CAP_MMAP_X: u64 = CAP_MMAP | CAP_SEEK | 0x0000000000000020u64;
|
||||
pub const CAP_MMAP_RW: u64 = CAP_MMAP_R | CAP_MMAP_W;
|
||||
pub const CAP_MMAP_RX: u64 = CAP_MMAP_R | CAP_MMAP_X;
|
||||
pub const CAP_MMAP_WX: u64 = CAP_MMAP_W | CAP_MMAP_X;
|
||||
pub const CAP_MMAP_RWX: u64 = CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X;
|
||||
pub const CAP_CREATE: u64 = cap_right!(0, 0x0000000000000040u64);
|
||||
pub const CAP_FEXECVE: u64 = cap_right!(0, 0x0000000000000080u64);
|
||||
pub const CAP_FSYNC: u64 = cap_right!(0, 0x0000000000000100u64);
|
||||
pub const CAP_FTRUNCATE: u64 = cap_right!(0, 0x0000000000000200u64);
|
||||
pub const CAP_LOOKUP: u64 = cap_right!(0, 0x0000000000000400u64);
|
||||
pub const CAP_FCHDIR: u64 = cap_right!(0, 0x0000000000000800u64);
|
||||
pub const CAP_FCHFLAGS: u64 = cap_right!(0, 0x0000000000001000u64);
|
||||
pub const CAP_CHFLAGSAT: u64 = CAP_FCHFLAGS | CAP_LOOKUP;
|
||||
pub const CAP_FCHMOD: u64 = cap_right!(0, 0x0000000000002000u64);
|
||||
pub const CAP_FCHMODAT: u64 = CAP_FCHMOD | CAP_LOOKUP;
|
||||
pub const CAP_FCHOWN: u64 = cap_right!(0, 0x0000000000004000u64);
|
||||
pub const CAP_FCHOWNAT: u64 = CAP_FCHOWN | CAP_LOOKUP;
|
||||
pub const CAP_FCNTL: u64 = cap_right!(0, 0x0000000000008000u64);
|
||||
pub const CAP_FLOCK: u64 = cap_right!(0, 0x0000000000010000u64);
|
||||
pub const CAP_FPATHCONF: u64 = cap_right!(0, 0x0000000000020000u64);
|
||||
pub const CAP_FSCK: u64 = cap_right!(0, 0x0000000000040000u64);
|
||||
pub const CAP_FSTAT: u64 = cap_right!(0, 0x0000000000080000u64);
|
||||
pub const CAP_FSTATAT: u64 = CAP_FSTAT | CAP_LOOKUP;
|
||||
pub const CAP_FSTATFS: u64 = cap_right!(0, 0x0000000000100000u64);
|
||||
pub const CAP_FUTIMES: u64 = cap_right!(0, 0x0000000000200000u64);
|
||||
pub const CAP_FUTIMESAT: u64 = CAP_FUTIMES | CAP_LOOKUP;
|
||||
// Note: this was named CAP_LINKAT prior to FreeBSD 11.0.
|
||||
pub const CAP_LINKAT_TARGET: u64 = CAP_LOOKUP | 0x0000000000400000u64;
|
||||
pub const CAP_MKDIRAT: u64 = CAP_LOOKUP | 0x0000000000800000u64;
|
||||
pub const CAP_MKFIFOAT: u64 = CAP_LOOKUP | 0x0000000001000000u64;
|
||||
pub const CAP_MKNODAT: u64 = CAP_LOOKUP | 0x0000000002000000u64;
|
||||
// Note: this was named CAP_RENAMEAT prior to FreeBSD 11.0.
|
||||
pub const CAP_RENAMEAT_SOURCE: u64 = CAP_LOOKUP | 0x0000000004000000u64;
|
||||
pub const CAP_SYMLINKAT: u64 = CAP_LOOKUP | 0x0000000008000000u64;
|
||||
pub const CAP_UNLINKAT: u64 = CAP_LOOKUP | 0x0000000010000000u64;
|
||||
pub const CAP_ACCEPT: u64 = cap_right!(0, 0x0000000020000000u64);
|
||||
pub const CAP_BIND: u64 = cap_right!(0, 0x0000000040000000u64);
|
||||
pub const CAP_CONNECT: u64 = cap_right!(0, 0x0000000080000000u64);
|
||||
pub const CAP_GETPEERNAME: u64 = cap_right!(0, 0x0000000100000000u64);
|
||||
pub const CAP_GETSOCKNAME: u64 = cap_right!(0, 0x0000000200000000u64);
|
||||
pub const CAP_GETSOCKOPT: u64 = cap_right!(0, 0x0000000400000000u64);
|
||||
pub const CAP_LISTEN: u64 = cap_right!(0, 0x0000000800000000u64);
|
||||
pub const CAP_PEELOFF: u64 = cap_right!(0, 0x0000001000000000u64);
|
||||
pub const CAP_RECV: u64 = CAP_READ;
|
||||
pub const CAP_SEND: u64 = CAP_WRITE;
|
||||
pub const CAP_SETSOCKOPT: u64 = cap_right!(0, 0x0000002000000000u64);
|
||||
pub const CAP_SHUTDOWN: u64 = cap_right!(0, 0x0000004000000000u64);
|
||||
pub const CAP_BINDAT: u64 = CAP_LOOKUP | 0x0000008000000000u64;
|
||||
pub const CAP_CONNECTAT: u64 = CAP_LOOKUP | 0x0000010000000000u64;
|
||||
pub const CAP_LINKAT_SOURCE: u64 = CAP_LOOKUP | 0x0000020000000000u64;
|
||||
pub const CAP_RENAMEAT_TARGET: u64 = CAP_LOOKUP | 0x0000040000000000u64;
|
||||
pub const CAP_SOCK_CLIENT: u64 = CAP_CONNECT
|
||||
| CAP_GETPEERNAME
|
||||
| CAP_GETSOCKNAME
|
||||
| CAP_GETSOCKOPT
|
||||
| CAP_PEELOFF
|
||||
| CAP_RECV
|
||||
| CAP_SEND
|
||||
| CAP_SETSOCKOPT
|
||||
| CAP_SHUTDOWN;
|
||||
pub const CAP_SOCK_SERVER: u64 = CAP_ACCEPT
|
||||
| CAP_BIND
|
||||
| CAP_GETPEERNAME
|
||||
| CAP_GETSOCKNAME
|
||||
| CAP_GETSOCKOPT
|
||||
| CAP_LISTEN
|
||||
| CAP_PEELOFF
|
||||
| CAP_RECV
|
||||
| CAP_SEND
|
||||
| CAP_SETSOCKOPT
|
||||
| CAP_SHUTDOWN;
|
||||
pub const CAP_ALL0: u64 = cap_right!(0, 0x000007FFFFFFFFFFu64);
|
||||
pub const CAP_UNUSED0_44: u64 = cap_right!(0, 0x0000080000000000u64);
|
||||
pub const CAP_UNUSED0_57: u64 = cap_right!(0, 0x0100000000000000u64);
|
||||
pub const CAP_MAC_GET: u64 = cap_right!(1, 0x0000000000000001u64);
|
||||
pub const CAP_MAC_SET: u64 = cap_right!(1, 0x0000000000000002u64);
|
||||
pub const CAP_SEM_GETVALUE: u64 = cap_right!(1, 0x0000000000000004u64);
|
||||
pub const CAP_SEM_POST: u64 = cap_right!(1, 0x0000000000000008u64);
|
||||
pub const CAP_SEM_WAIT: u64 = cap_right!(1, 0x0000000000000010u64);
|
||||
pub const CAP_EVENT: u64 = cap_right!(1, 0x0000000000000020u64);
|
||||
pub const CAP_KQUEUE_EVENT: u64 = cap_right!(1, 0x0000000000000040u64);
|
||||
pub const CAP_IOCTL: u64 = cap_right!(1, 0x0000000000000080u64);
|
||||
pub const CAP_TTYHOOK: u64 = cap_right!(1, 0x0000000000000100u64);
|
||||
pub const CAP_PDGETPID: u64 = cap_right!(1, 0x0000000000000200u64);
|
||||
pub const CAP_PDWAIT: u64 = cap_right!(1, 0x0000000000000400u64);
|
||||
pub const CAP_PDKILL: u64 = cap_right!(1, 0x0000000000000800u64);
|
||||
pub const CAP_EXTATTR_DELETE: u64 = cap_right!(1, 0x0000000000001000u64);
|
||||
pub const CAP_EXTATTR_GET: u64 = cap_right!(1, 0x0000000000002000u64);
|
||||
pub const CAP_EXTATTR_LIST: u64 = cap_right!(1, 0x0000000000004000u64);
|
||||
pub const CAP_EXTATTR_SET: u64 = cap_right!(1, 0x0000000000008000u64);
|
||||
pub const CAP_ACL_CHECK: u64 = cap_right!(1, 0x0000000000010000u64);
|
||||
pub const CAP_ACL_DELETE: u64 = cap_right!(1, 0x0000000000020000u64);
|
||||
pub const CAP_ACL_GET: u64 = cap_right!(1, 0x0000000000040000u64);
|
||||
pub const CAP_ACL_SET: u64 = cap_right!(1, 0x0000000000080000u64);
|
||||
pub const CAP_KQUEUE_CHANGE: u64 = cap_right!(1, 0x0000000000100000u64);
|
||||
pub const CAP_KQUEUE: u64 = CAP_KQUEUE_EVENT | CAP_KQUEUE_CHANGE;
|
||||
pub const CAP_ALL1: u64 = cap_right!(1, 0x00000000001FFFFFu64);
|
||||
pub const CAP_UNUSED1_22: u64 = cap_right!(1, 0x0000000000200000u64);
|
||||
pub const CAP_UNUSED1_57: u64 = cap_right!(1, 0x0100000000000000u64);
|
||||
pub const CAP_FCNTL_GETFL: u32 = 1 << 3;
|
||||
pub const CAP_FCNTL_SETFL: u32 = 1 << 4;
|
||||
pub const CAP_FCNTL_GETOWN: u32 = 1 << 5;
|
||||
pub const CAP_FCNTL_SETOWN: u32 = 1 << 6;
|
||||
|
||||
// sys/devicestat.h
|
||||
pub const DEVSTAT_N_TRANS_FLAGS: ::c_int = 4;
|
||||
pub const DEVSTAT_NAME_LEN: ::c_int = 16;
|
||||
|
@ -3875,11 +4061,6 @@ pub const F_SEAL_WRITE: ::c_int = 8;
|
|||
// for use with fspacectl
|
||||
pub const SPACECTL_DEALLOC: ::c_int = 1;
|
||||
|
||||
// For getrandom()
|
||||
pub const GRND_NONBLOCK: ::c_uint = 0x1;
|
||||
pub const GRND_RANDOM: ::c_uint = 0x2;
|
||||
pub const GRND_INSECURE: ::c_uint = 0x4;
|
||||
|
||||
// For realhostname* api
|
||||
pub const HOSTNAME_FOUND: ::c_int = 0;
|
||||
pub const HOSTNAME_INCORRECTNAME: ::c_int = 1;
|
||||
|
@ -5393,8 +5574,6 @@ extern "C" {
|
|||
|
||||
pub fn fdatasync(fd: ::c_int) -> ::c_int;
|
||||
|
||||
pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t;
|
||||
pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int;
|
||||
pub fn elf_aux_info(aux: ::c_int, buf: *mut ::c_void, buflen: ::c_int) -> ::c_int;
|
||||
pub fn setproctitle_fast(fmt: *const ::c_char, ...);
|
||||
pub fn timingsafe_bcmp(a: *const ::c_void, b: *const ::c_void, len: ::size_t) -> ::c_int;
|
||||
|
@ -5469,6 +5648,12 @@ extern "C" {
|
|||
) -> ::c_int;
|
||||
pub fn closefrom(lowfd: ::c_int);
|
||||
pub fn close_range(lowfd: ::c_uint, highfd: ::c_uint, flags: ::c_int) -> ::c_int;
|
||||
|
||||
pub fn execvpe(
|
||||
file: *const ::c_char,
|
||||
argv: *const *const ::c_char,
|
||||
envp: *const *const ::c_char,
|
||||
) -> ::c_int;
|
||||
}
|
||||
|
||||
#[link(name = "memstat")]
|
||||
|
|
|
@ -199,3 +199,5 @@ cfg_if! {
|
|||
}
|
||||
|
||||
pub const MINSIGSTKSZ: ::size_t = 2048; // 512 * 4
|
||||
|
||||
pub const KINFO_FILE_SIZE: ::c_int = 1392;
|
||||
|
|
|
@ -93,23 +93,6 @@ s_no_extra_traits! {
|
|||
#[cfg(libc_union)]
|
||||
pub a_un: __c_anonymous_elf64_auxv_union,
|
||||
}
|
||||
|
||||
pub struct kinfo_file {
|
||||
pub kf_structsize: ::c_int,
|
||||
pub kf_type: ::c_int,
|
||||
pub kf_fd: ::c_int,
|
||||
pub kf_ref_count: ::c_int,
|
||||
pub kf_flags: ::c_int,
|
||||
_kf_pad0: ::c_int,
|
||||
pub kf_offset: i64,
|
||||
_priv: [::uintptr_t; 38], // FIXME if needed
|
||||
pub kf_status: u16,
|
||||
_kf_pad1: u16,
|
||||
_kf_ispare0: ::c_int,
|
||||
pub kf_cap_rights: ::cap_rights_t,
|
||||
_kf_cap_spare: u64,
|
||||
pub kf_path: [::c_char; ::PATH_MAX as usize],
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
|
@ -253,52 +236,6 @@ cfg_if! {
|
|||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for kinfo_file {
|
||||
fn eq(&self, other: &kinfo_file) -> bool {
|
||||
self.kf_structsize == other.kf_structsize &&
|
||||
self.kf_type == other.kf_type &&
|
||||
self.kf_fd == other.kf_fd &&
|
||||
self.kf_ref_count == other.kf_ref_count &&
|
||||
self.kf_flags == other.kf_flags &&
|
||||
self.kf_offset == other.kf_offset &&
|
||||
self.kf_status == other.kf_status &&
|
||||
self.kf_cap_rights == other.kf_cap_rights &&
|
||||
self.kf_path
|
||||
.iter()
|
||||
.zip(other.kf_path.iter())
|
||||
.all(|(a,b)| a == b)
|
||||
}
|
||||
}
|
||||
impl Eq for kinfo_file {}
|
||||
impl ::fmt::Debug for kinfo_file {
|
||||
fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
|
||||
f.debug_struct("kinfo_file")
|
||||
.field("kf_structsize", &self.kf_structsize)
|
||||
.field("kf_type", &self.kf_type)
|
||||
.field("kf_fd", &self.kf_fd)
|
||||
.field("kf_ref_count", &self.kf_ref_count)
|
||||
.field("kf_flags", &self.kf_flags)
|
||||
.field("kf_offset", &self.kf_offset)
|
||||
.field("kf_status", &self.kf_status)
|
||||
.field("kf_cap_rights", &self.kf_cap_rights)
|
||||
.field("kf_path", &&self.kf_path[..])
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
impl ::hash::Hash for kinfo_file {
|
||||
fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
|
||||
self.kf_structsize.hash(state);
|
||||
self.kf_type.hash(state);
|
||||
self.kf_fd.hash(state);
|
||||
self.kf_ref_count.hash(state);
|
||||
self.kf_flags.hash(state);
|
||||
self.kf_offset.hash(state);
|
||||
self.kf_status.hash(state);
|
||||
self.kf_cap_rights.hash(state);
|
||||
self.kf_path.hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,6 +263,8 @@ pub const _MC_FPOWNED_NONE: c_long = 0x20000;
|
|||
pub const _MC_FPOWNED_FPU: c_long = 0x20001;
|
||||
pub const _MC_FPOWNED_PCB: c_long = 0x20002;
|
||||
|
||||
pub const KINFO_FILE_SIZE: ::c_int = 1392;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(libc_align)] {
|
||||
mod align;
|
||||
|
|
|
@ -797,6 +797,7 @@ pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2;
|
|||
pub const POSIX_MADV_WILLNEED: ::c_int = 3;
|
||||
pub const POSIX_MADV_DONTNEED: ::c_int = 4;
|
||||
|
||||
pub const PTHREAD_BARRIER_SERIAL_THREAD: ::c_int = -1;
|
||||
pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0;
|
||||
pub const PTHREAD_PROCESS_SHARED: ::c_int = 1;
|
||||
pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0;
|
||||
|
@ -970,6 +971,8 @@ pub const IP_SENDSRCADDR: ::c_int = IP_RECVDSTADDR;
|
|||
pub const IP_ADD_MEMBERSHIP: ::c_int = 12;
|
||||
pub const IP_DROP_MEMBERSHIP: ::c_int = 13;
|
||||
pub const IP_RECVIF: ::c_int = 20;
|
||||
pub const IP_RECVTTL: ::c_int = 65;
|
||||
pub const IPV6_RECVHOPLIMIT: ::c_int = 37;
|
||||
pub const IPV6_JOIN_GROUP: ::c_int = 12;
|
||||
pub const IPV6_LEAVE_GROUP: ::c_int = 13;
|
||||
pub const IPV6_CHECKSUM: ::c_int = 26;
|
||||
|
@ -978,7 +981,6 @@ pub const IPV6_PKTINFO: ::c_int = 46;
|
|||
pub const IPV6_HOPLIMIT: ::c_int = 47;
|
||||
pub const IPV6_RECVTCLASS: ::c_int = 57;
|
||||
pub const IPV6_TCLASS: ::c_int = 61;
|
||||
pub const IPV6_DONTFRAG: ::c_int = 62;
|
||||
pub const IP_ADD_SOURCE_MEMBERSHIP: ::c_int = 70;
|
||||
pub const IP_DROP_SOURCE_MEMBERSHIP: ::c_int = 71;
|
||||
pub const IP_BLOCK_SOURCE: ::c_int = 72;
|
||||
|
@ -1456,6 +1458,11 @@ pub const RB_GDB: ::c_int = 0x8000;
|
|||
pub const RB_MUTE: ::c_int = 0x10000;
|
||||
pub const RB_SELFTEST: ::c_int = 0x20000;
|
||||
|
||||
// For getrandom()
|
||||
pub const GRND_NONBLOCK: ::c_uint = 0x1;
|
||||
pub const GRND_RANDOM: ::c_uint = 0x2;
|
||||
pub const GRND_INSECURE: ::c_uint = 0x4;
|
||||
|
||||
safe_f! {
|
||||
pub {const} fn WIFCONTINUED(status: ::c_int) -> bool {
|
||||
status == 0x13
|
||||
|
@ -1829,6 +1836,9 @@ extern "C" {
|
|||
abs_timeout: *const ::timespec,
|
||||
) -> ::c_int;
|
||||
pub fn mq_unlink(name: *const ::c_char) -> ::c_int;
|
||||
|
||||
pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t;
|
||||
pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int;
|
||||
}
|
||||
|
||||
#[link(name = "util")]
|
||||
|
|
|
@ -39,6 +39,7 @@ s! {
|
|||
target_os = "ios",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos",
|
||||
target_os = "visionos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd")))]
|
||||
pub pw_fields: ::c_int,
|
||||
|
@ -310,6 +311,7 @@ pub const IPV6_MULTICAST_IF: ::c_int = 9;
|
|||
pub const IPV6_MULTICAST_HOPS: ::c_int = 10;
|
||||
pub const IPV6_MULTICAST_LOOP: ::c_int = 11;
|
||||
pub const IPV6_V6ONLY: ::c_int = 27;
|
||||
pub const IPV6_DONTFRAG: ::c_int = 62;
|
||||
|
||||
pub const IPTOS_ECN_NOTECT: u8 = 0x00;
|
||||
pub const IPTOS_ECN_MASK: u8 = 0x03;
|
||||
|
@ -917,7 +919,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] {
|
||||
if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))] {
|
||||
mod apple;
|
||||
pub use self::apple::*;
|
||||
} else if #[cfg(any(target_os = "openbsd", target_os = "netbsd"))] {
|
||||
|
|
|
@ -2884,6 +2884,22 @@ extern "C" {
|
|||
pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t;
|
||||
|
||||
pub fn reboot(mode: ::c_int, bootstr: *mut ::c_char) -> ::c_int;
|
||||
|
||||
#[link_name = "___lwp_park60"]
|
||||
pub fn _lwp_park(
|
||||
clock: ::clockid_t,
|
||||
flags: ::c_int,
|
||||
ts: *const ::timespec,
|
||||
unpark: ::lwpid_t,
|
||||
hint: *const ::c_void,
|
||||
unparkhint: *mut ::c_void,
|
||||
) -> ::c_int;
|
||||
pub fn _lwp_unpark(lwp: ::lwpid_t, hint: *const ::c_void) -> ::c_int;
|
||||
pub fn _lwp_unpark_all(
|
||||
targets: *const ::lwpid_t,
|
||||
ntargets: ::size_t,
|
||||
hint: *const ::c_void,
|
||||
) -> ::c_int;
|
||||
}
|
||||
|
||||
#[link(name = "rt")]
|
||||
|
|
|
@ -706,7 +706,7 @@ pub const F_RDLCK: ::c_int = 0x0040;
|
|||
pub const F_UNLCK: ::c_int = 0x0200;
|
||||
pub const F_WRLCK: ::c_int = 0x0400;
|
||||
|
||||
pub const AT_FDCWD: ::c_int = -1;
|
||||
pub const AT_FDCWD: ::c_int = -100;
|
||||
pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x01;
|
||||
pub const AT_SYMLINK_FOLLOW: ::c_int = 0x02;
|
||||
pub const AT_REMOVEDIR: ::c_int = 0x04;
|
||||
|
@ -1192,6 +1192,80 @@ pub const _SC_REGEXP: ::c_int = 62;
|
|||
pub const _SC_SYMLOOP_MAX: ::c_int = 63;
|
||||
pub const _SC_SHELL: ::c_int = 64;
|
||||
pub const _SC_TTY_NAME_MAX: ::c_int = 65;
|
||||
pub const _SC_ADVISORY_INFO: ::c_int = 66;
|
||||
pub const _SC_BARRIERS: ::c_int = 67;
|
||||
pub const _SC_CLOCK_SELECTION: ::c_int = 68;
|
||||
pub const _SC_FSYNC: ::c_int = 69;
|
||||
pub const _SC_IPV6: ::c_int = 70;
|
||||
pub const _SC_MEMLOCK: ::c_int = 71;
|
||||
pub const _SC_MEMLOCK_RANGE: ::c_int = 72;
|
||||
pub const _SC_MESSAGE_PASSING: ::c_int = 73;
|
||||
pub const _SC_PRIORITIZED_IO: ::c_int = 74;
|
||||
pub const _SC_PRIORITY_SCHEDULING: ::c_int = 75;
|
||||
pub const _SC_READER_WRITER_LOCKS: ::c_int = 76;
|
||||
pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 77;
|
||||
pub const _SC_SPAWN: ::c_int = 78;
|
||||
pub const _SC_SPIN_LOCKS: ::c_int = 79;
|
||||
pub const _SC_SPORADIC_SERVER: ::c_int = 80;
|
||||
pub const _SC_SYNCHRONIZED_IO: ::c_int = 81;
|
||||
pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 82;
|
||||
pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 83;
|
||||
pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 84;
|
||||
pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 85;
|
||||
pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 86;
|
||||
pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 87;
|
||||
pub const _SC_TIMEOUTS: ::c_int = 88;
|
||||
pub const _SC_TRACE: ::c_int = 89;
|
||||
pub const _SC_TRACE_EVENT_FILTER: ::c_int = 90;
|
||||
pub const _SC_TRACE_INHERIT: ::c_int = 91;
|
||||
pub const _SC_TRACE_LOG: ::c_int = 92;
|
||||
pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 93;
|
||||
pub const _SC_V6_ILP32_OFF32: ::c_int = 94;
|
||||
pub const _SC_V6_ILP32_OFFBIG: ::c_int = 95;
|
||||
pub const _SC_V6_LP64_OFF64: ::c_int = 96;
|
||||
pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 97;
|
||||
pub const _SC_V7_ILP32_OFF32: ::c_int = 98;
|
||||
pub const _SC_V7_ILP32_OFFBIG: ::c_int = 99;
|
||||
pub const _SC_V7_LP64_OFF64: ::c_int = 100;
|
||||
pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 101;
|
||||
pub const _SC_2_C_BIND: ::c_int = 102;
|
||||
pub const _SC_2_C_DEV: ::c_int = 103;
|
||||
pub const _SC_2_CHAR_TERM: ::c_int = 104;
|
||||
pub const _SC_2_FORT_DEV: ::c_int = 105;
|
||||
pub const _SC_2_FORT_RUN: ::c_int = 106;
|
||||
pub const _SC_2_LOCALEDEF: ::c_int = 107;
|
||||
pub const _SC_2_PBS: ::c_int = 108;
|
||||
pub const _SC_2_PBS_ACCOUNTING: ::c_int = 109;
|
||||
pub const _SC_2_PBS_CHECKPOINT: ::c_int = 110;
|
||||
pub const _SC_2_PBS_LOCATE: ::c_int = 111;
|
||||
pub const _SC_2_PBS_MESSAGE: ::c_int = 112;
|
||||
pub const _SC_2_PBS_TRACK: ::c_int = 113;
|
||||
pub const _SC_2_SW_DEV: ::c_int = 114;
|
||||
pub const _SC_2_UPE: ::c_int = 115;
|
||||
pub const _SC_2_VERSION: ::c_int = 116;
|
||||
pub const _SC_XOPEN_CRYPT: ::c_int = 117;
|
||||
pub const _SC_XOPEN_ENH_I18N: ::c_int = 118;
|
||||
pub const _SC_XOPEN_REALTIME: ::c_int = 119;
|
||||
pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 120;
|
||||
pub const _SC_XOPEN_SHM: ::c_int = 121;
|
||||
pub const _SC_XOPEN_STREAMS: ::c_int = 122;
|
||||
pub const _SC_XOPEN_UNIX: ::c_int = 123;
|
||||
pub const _SC_XOPEN_UUCP: ::c_int = 124;
|
||||
pub const _SC_XOPEN_VERSION: ::c_int = 125;
|
||||
pub const _SC_BC_BASE_MAX: ::c_int = 129;
|
||||
pub const _SC_BC_DIM_MAX: ::c_int = 130;
|
||||
pub const _SC_BC_SCALE_MAX: ::c_int = 131;
|
||||
pub const _SC_BC_STRING_MAX: ::c_int = 132;
|
||||
pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 133;
|
||||
pub const _SC_EXPR_NEST_MAX: ::c_int = 134;
|
||||
pub const _SC_LINE_MAX: ::c_int = 135;
|
||||
pub const _SC_LOGIN_NAME_MAX: ::c_int = 136;
|
||||
pub const _SC_MQ_OPEN_MAX: ::c_int = 137;
|
||||
pub const _SC_MQ_PRIO_MAX: ::c_int = 138;
|
||||
pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 139;
|
||||
pub const _SC_THREAD_KEYS_MAX: ::c_int = 140;
|
||||
pub const _SC_THREAD_THREADS_MAX: ::c_int = 141;
|
||||
pub const _SC_RE_DUP_MAX: ::c_int = 142;
|
||||
|
||||
pub const PTHREAD_STACK_MIN: ::size_t = 8192;
|
||||
|
||||
|
@ -1386,8 +1460,9 @@ pub const TCGB_RI: ::c_int = 0x04;
|
|||
pub const TCGB_DCD: ::c_int = 0x08;
|
||||
pub const TIOCM_CTS: ::c_int = TCGB_CTS;
|
||||
pub const TIOCM_CD: ::c_int = TCGB_DCD;
|
||||
pub const TIOCM_CAR: ::c_int = TIOCM_CD;
|
||||
pub const TIOCM_CAR: ::c_int = TCGB_DCD;
|
||||
pub const TIOCM_RI: ::c_int = TCGB_RI;
|
||||
pub const TIOCM_RNG: ::c_int = TCGB_RI;
|
||||
pub const TIOCM_DSR: ::c_int = TCGB_DSR;
|
||||
pub const TIOCM_DTR: ::c_int = 0x10;
|
||||
pub const TIOCM_RTS: ::c_int = 0x20;
|
||||
|
@ -1430,17 +1505,14 @@ pub const TCGETA: ::c_ulong = 0x8000;
|
|||
pub const TCSETA: ::c_ulong = TCGETA + 1;
|
||||
pub const TCSETAF: ::c_ulong = TCGETA + 2;
|
||||
pub const TCSETAW: ::c_ulong = TCGETA + 3;
|
||||
pub const TCWAITEVENT: ::c_ulong = TCGETA + 4;
|
||||
pub const TCSBRK: ::c_ulong = TCGETA + 5;
|
||||
pub const TCFLSH: ::c_ulong = TCGETA + 6;
|
||||
pub const TCXONC: ::c_ulong = TCGETA + 7;
|
||||
pub const TCQUERYCONNECTED: ::c_ulong = TCGETA + 8;
|
||||
pub const TCGETBITS: ::c_ulong = TCGETA + 9;
|
||||
pub const TCSETDTR: ::c_ulong = TCGETA + 10;
|
||||
pub const TCSETRTS: ::c_ulong = TCGETA + 11;
|
||||
pub const TIOCGWINSZ: ::c_ulong = TCGETA + 12;
|
||||
pub const TIOCSWINSZ: ::c_ulong = TCGETA + 13;
|
||||
pub const TCVTIME: ::c_ulong = TCGETA + 14;
|
||||
pub const TIOCGPGRP: ::c_ulong = TCGETA + 15;
|
||||
pub const TIOCSPGRP: ::c_ulong = TCGETA + 16;
|
||||
pub const TIOCSCTTY: ::c_ulong = TCGETA + 17;
|
||||
|
@ -1450,6 +1522,10 @@ pub const TIOCSBRK: ::c_ulong = TCGETA + 20;
|
|||
pub const TIOCCBRK: ::c_ulong = TCGETA + 21;
|
||||
pub const TIOCMBIS: ::c_ulong = TCGETA + 22;
|
||||
pub const TIOCMBIC: ::c_ulong = TCGETA + 23;
|
||||
pub const TIOCGSID: ::c_ulong = TCGETA + 24;
|
||||
pub const TIOCOUTQ: ::c_ulong = TCGETA + 25;
|
||||
pub const TIOCEXCL: ::c_ulong = TCGETA + 26;
|
||||
pub const TIOCNXCL: ::c_ulong = TCGETA + 27;
|
||||
|
||||
pub const PRIO_PROCESS: ::c_int = 0;
|
||||
pub const PRIO_PGRP: ::c_int = 1;
|
||||
|
@ -1715,6 +1791,7 @@ extern "C" {
|
|||
lock: *mut pthread_mutex_t,
|
||||
abstime: *const ::timespec,
|
||||
) -> ::c_int;
|
||||
pub fn pthread_sigqueue(thread: ::pthread_t, sig: ::c_int, value: ::sigval) -> ::c_int;
|
||||
pub fn pthread_spin_init(lock: *mut ::pthread_spinlock_t, pshared: ::c_int) -> ::c_int;
|
||||
pub fn pthread_spin_destroy(lock: *mut ::pthread_spinlock_t) -> ::c_int;
|
||||
pub fn pthread_spin_lock(lock: *mut ::pthread_spinlock_t) -> ::c_int;
|
||||
|
|
|
@ -956,6 +956,7 @@ pub const B_XATTR_TYPE: u32 = haiku_constant!('X', 'A', 'T', 'R');
|
|||
pub const B_NETWORK_ADDRESS_TYPE: u32 = haiku_constant!('N', 'W', 'A', 'D');
|
||||
pub const B_MIME_STRING_TYPE: u32 = haiku_constant!('M', 'I', 'M', 'S');
|
||||
pub const B_ASCII_TYPE: u32 = haiku_constant!('T', 'E', 'X', 'T');
|
||||
pub const B_APP_IMAGE_SYMBOL: *const ::c_void = core::ptr::null();
|
||||
|
||||
extern "C" {
|
||||
// kernel/OS.h
|
||||
|
|
|
@ -2760,6 +2760,10 @@ pub const MREMAP_FIXED: ::c_int = 2;
|
|||
pub const MCL_CURRENT: ::c_int = 0x0001;
|
||||
pub const MCL_FUTURE: ::c_int = 0x0002;
|
||||
|
||||
// sys/xattr.h
|
||||
pub const XATTR_CREATE: ::c_int = 0x1;
|
||||
pub const XATTR_REPLACE: ::c_int = 0x2;
|
||||
|
||||
// spawn.h
|
||||
pub const POSIX_SPAWN_USEVFORK: ::c_int = 64;
|
||||
pub const POSIX_SPAWN_SETSID: ::c_int = 128;
|
||||
|
|
|
@ -191,6 +191,7 @@ pub const SYS_vhangup: ::c_long = 58;
|
|||
pub const SYS_pipe2: ::c_long = 59;
|
||||
pub const SYS_quotactl: ::c_long = 60;
|
||||
pub const SYS_getdents64: ::c_long = 61;
|
||||
pub const SYS_lseek: ::c_long = 62;
|
||||
pub const SYS_read: ::c_long = 63;
|
||||
pub const SYS_write: ::c_long = 64;
|
||||
pub const SYS_readv: ::c_long = 65;
|
||||
|
@ -347,6 +348,7 @@ pub const SYS_request_key: ::c_long = 218;
|
|||
pub const SYS_keyctl: ::c_long = 219;
|
||||
pub const SYS_clone: ::c_long = 220;
|
||||
pub const SYS_execve: ::c_long = 221;
|
||||
pub const SYS_mmap: ::c_long = 222;
|
||||
pub const SYS_swapon: ::c_long = 224;
|
||||
pub const SYS_swapoff: ::c_long = 225;
|
||||
pub const SYS_mprotect: ::c_long = 226;
|
||||
|
|
|
@ -288,6 +288,7 @@ pub const AT_BASE_PLATFORM: ::c_ulong = 24;
|
|||
pub const AT_RANDOM: ::c_ulong = 25;
|
||||
pub const AT_HWCAP2: ::c_ulong = 26;
|
||||
pub const AT_EXECFN: ::c_ulong = 31;
|
||||
pub const AT_MINSIGSTKSZ: ::c_ulong = 51;
|
||||
|
||||
pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
|
||||
value: 0,
|
||||
|
|
|
@ -48,6 +48,10 @@ pub type Elf64_Xword = u64;
|
|||
|
||||
pub type eventfd_t = u64;
|
||||
|
||||
// these structs sit behind a heap allocation on Android
|
||||
pub type posix_spawn_file_actions_t = *mut ::c_void;
|
||||
pub type posix_spawnattr_t = *mut ::c_void;
|
||||
|
||||
s! {
|
||||
pub struct stack_t {
|
||||
pub ss_sp: *mut ::c_void,
|
||||
|
@ -1182,140 +1186,155 @@ pub const _PC_SYNC_IO: ::c_int = 19;
|
|||
|
||||
pub const FIONBIO: ::c_int = 0x5421;
|
||||
|
||||
pub const _SC_ARG_MAX: ::c_int = 0;
|
||||
pub const _SC_BC_BASE_MAX: ::c_int = 1;
|
||||
pub const _SC_BC_DIM_MAX: ::c_int = 2;
|
||||
pub const _SC_BC_SCALE_MAX: ::c_int = 3;
|
||||
pub const _SC_BC_STRING_MAX: ::c_int = 4;
|
||||
pub const _SC_CHILD_MAX: ::c_int = 5;
|
||||
pub const _SC_CLK_TCK: ::c_int = 6;
|
||||
pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 7;
|
||||
pub const _SC_EXPR_NEST_MAX: ::c_int = 8;
|
||||
pub const _SC_LINE_MAX: ::c_int = 9;
|
||||
pub const _SC_NGROUPS_MAX: ::c_int = 10;
|
||||
pub const _SC_OPEN_MAX: ::c_int = 11;
|
||||
pub const _SC_PASS_MAX: ::c_int = 12;
|
||||
pub const _SC_2_C_BIND: ::c_int = 13;
|
||||
pub const _SC_2_C_DEV: ::c_int = 14;
|
||||
pub const _SC_2_C_VERSION: ::c_int = 15;
|
||||
pub const _SC_2_CHAR_TERM: ::c_int = 16;
|
||||
pub const _SC_2_FORT_DEV: ::c_int = 17;
|
||||
pub const _SC_2_FORT_RUN: ::c_int = 18;
|
||||
pub const _SC_2_LOCALEDEF: ::c_int = 19;
|
||||
pub const _SC_2_SW_DEV: ::c_int = 20;
|
||||
pub const _SC_2_UPE: ::c_int = 21;
|
||||
pub const _SC_2_VERSION: ::c_int = 22;
|
||||
pub const _SC_JOB_CONTROL: ::c_int = 23;
|
||||
pub const _SC_SAVED_IDS: ::c_int = 24;
|
||||
pub const _SC_VERSION: ::c_int = 25;
|
||||
pub const _SC_RE_DUP_MAX: ::c_int = 26;
|
||||
pub const _SC_STREAM_MAX: ::c_int = 27;
|
||||
pub const _SC_TZNAME_MAX: ::c_int = 28;
|
||||
pub const _SC_XOPEN_CRYPT: ::c_int = 29;
|
||||
pub const _SC_XOPEN_ENH_I18N: ::c_int = 30;
|
||||
pub const _SC_XOPEN_SHM: ::c_int = 31;
|
||||
pub const _SC_XOPEN_VERSION: ::c_int = 32;
|
||||
pub const _SC_XOPEN_XCU_VERSION: ::c_int = 33;
|
||||
pub const _SC_XOPEN_REALTIME: ::c_int = 34;
|
||||
pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 35;
|
||||
pub const _SC_XOPEN_LEGACY: ::c_int = 36;
|
||||
pub const _SC_ATEXIT_MAX: ::c_int = 37;
|
||||
pub const _SC_IOV_MAX: ::c_int = 38;
|
||||
pub const _SC_PAGESIZE: ::c_int = 39;
|
||||
pub const _SC_PAGE_SIZE: ::c_int = 40;
|
||||
pub const _SC_XOPEN_UNIX: ::c_int = 41;
|
||||
pub const _SC_XBS5_ILP32_OFF32: ::c_int = 42;
|
||||
pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 43;
|
||||
pub const _SC_XBS5_LP64_OFF64: ::c_int = 44;
|
||||
pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 45;
|
||||
pub const _SC_AIO_LISTIO_MAX: ::c_int = 46;
|
||||
pub const _SC_AIO_MAX: ::c_int = 47;
|
||||
pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 48;
|
||||
pub const _SC_DELAYTIMER_MAX: ::c_int = 49;
|
||||
pub const _SC_MQ_OPEN_MAX: ::c_int = 50;
|
||||
pub const _SC_MQ_PRIO_MAX: ::c_int = 51;
|
||||
pub const _SC_RTSIG_MAX: ::c_int = 52;
|
||||
pub const _SC_SEM_NSEMS_MAX: ::c_int = 53;
|
||||
pub const _SC_SEM_VALUE_MAX: ::c_int = 54;
|
||||
pub const _SC_SIGQUEUE_MAX: ::c_int = 55;
|
||||
pub const _SC_TIMER_MAX: ::c_int = 56;
|
||||
pub const _SC_ASYNCHRONOUS_IO: ::c_int = 57;
|
||||
pub const _SC_FSYNC: ::c_int = 58;
|
||||
pub const _SC_MAPPED_FILES: ::c_int = 59;
|
||||
pub const _SC_MEMLOCK: ::c_int = 60;
|
||||
pub const _SC_MEMLOCK_RANGE: ::c_int = 61;
|
||||
pub const _SC_MEMORY_PROTECTION: ::c_int = 62;
|
||||
pub const _SC_MESSAGE_PASSING: ::c_int = 63;
|
||||
pub const _SC_PRIORITIZED_IO: ::c_int = 64;
|
||||
pub const _SC_PRIORITY_SCHEDULING: ::c_int = 65;
|
||||
pub const _SC_REALTIME_SIGNALS: ::c_int = 66;
|
||||
pub const _SC_SEMAPHORES: ::c_int = 67;
|
||||
pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 68;
|
||||
pub const _SC_SYNCHRONIZED_IO: ::c_int = 69;
|
||||
pub const _SC_TIMERS: ::c_int = 70;
|
||||
pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 71;
|
||||
pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 72;
|
||||
pub const _SC_LOGIN_NAME_MAX: ::c_int = 73;
|
||||
pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 74;
|
||||
pub const _SC_THREAD_KEYS_MAX: ::c_int = 75;
|
||||
pub const _SC_THREAD_STACK_MIN: ::c_int = 76;
|
||||
pub const _SC_THREAD_THREADS_MAX: ::c_int = 77;
|
||||
pub const _SC_TTY_NAME_MAX: ::c_int = 78;
|
||||
pub const _SC_THREADS: ::c_int = 79;
|
||||
pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 80;
|
||||
pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 81;
|
||||
pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 82;
|
||||
pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 83;
|
||||
pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 84;
|
||||
pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 85;
|
||||
pub const _SC_NPROCESSORS_CONF: ::c_int = 96;
|
||||
pub const _SC_NPROCESSORS_ONLN: ::c_int = 97;
|
||||
pub const _SC_PHYS_PAGES: ::c_int = 98;
|
||||
pub const _SC_AVPHYS_PAGES: ::c_int = 99;
|
||||
pub const _SC_MONOTONIC_CLOCK: ::c_int = 100;
|
||||
|
||||
pub const _SC_2_PBS: ::c_int = 101;
|
||||
pub const _SC_2_PBS_ACCOUNTING: ::c_int = 102;
|
||||
pub const _SC_2_PBS_CHECKPOINT: ::c_int = 103;
|
||||
pub const _SC_2_PBS_LOCATE: ::c_int = 104;
|
||||
pub const _SC_2_PBS_MESSAGE: ::c_int = 105;
|
||||
pub const _SC_2_PBS_TRACK: ::c_int = 106;
|
||||
pub const _SC_ADVISORY_INFO: ::c_int = 107;
|
||||
pub const _SC_BARRIERS: ::c_int = 108;
|
||||
pub const _SC_CLOCK_SELECTION: ::c_int = 109;
|
||||
pub const _SC_CPUTIME: ::c_int = 110;
|
||||
pub const _SC_HOST_NAME_MAX: ::c_int = 111;
|
||||
pub const _SC_IPV6: ::c_int = 112;
|
||||
pub const _SC_RAW_SOCKETS: ::c_int = 113;
|
||||
pub const _SC_READER_WRITER_LOCKS: ::c_int = 114;
|
||||
pub const _SC_REGEXP: ::c_int = 115;
|
||||
pub const _SC_SHELL: ::c_int = 116;
|
||||
pub const _SC_SPAWN: ::c_int = 117;
|
||||
pub const _SC_SPIN_LOCKS: ::c_int = 118;
|
||||
pub const _SC_SPORADIC_SERVER: ::c_int = 119;
|
||||
pub const _SC_SS_REPL_MAX: ::c_int = 120;
|
||||
pub const _SC_SYMLOOP_MAX: ::c_int = 121;
|
||||
pub const _SC_THREAD_CPUTIME: ::c_int = 122;
|
||||
pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 123;
|
||||
pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 124;
|
||||
pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 125;
|
||||
pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 126;
|
||||
pub const _SC_TIMEOUTS: ::c_int = 127;
|
||||
pub const _SC_TRACE: ::c_int = 128;
|
||||
pub const _SC_TRACE_EVENT_FILTER: ::c_int = 129;
|
||||
pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 130;
|
||||
pub const _SC_TRACE_INHERIT: ::c_int = 131;
|
||||
pub const _SC_TRACE_LOG: ::c_int = 132;
|
||||
pub const _SC_TRACE_NAME_MAX: ::c_int = 133;
|
||||
pub const _SC_TRACE_SYS_MAX: ::c_int = 134;
|
||||
pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 135;
|
||||
pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 136;
|
||||
pub const _SC_V7_ILP32_OFF32: ::c_int = 137;
|
||||
pub const _SC_V7_ILP32_OFFBIG: ::c_int = 138;
|
||||
pub const _SC_V7_LP64_OFF64: ::c_int = 139;
|
||||
pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 140;
|
||||
pub const _SC_XOPEN_STREAMS: ::c_int = 141;
|
||||
pub const _SC_XOPEN_UUCP: ::c_int = 142;
|
||||
pub const _SC_ARG_MAX: ::c_int = 0x0000;
|
||||
pub const _SC_BC_BASE_MAX: ::c_int = 0x0001;
|
||||
pub const _SC_BC_DIM_MAX: ::c_int = 0x0002;
|
||||
pub const _SC_BC_SCALE_MAX: ::c_int = 0x0003;
|
||||
pub const _SC_BC_STRING_MAX: ::c_int = 0x0004;
|
||||
pub const _SC_CHILD_MAX: ::c_int = 0x0005;
|
||||
pub const _SC_CLK_TCK: ::c_int = 0x0006;
|
||||
pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 0x0007;
|
||||
pub const _SC_EXPR_NEST_MAX: ::c_int = 0x0008;
|
||||
pub const _SC_LINE_MAX: ::c_int = 0x0009;
|
||||
pub const _SC_NGROUPS_MAX: ::c_int = 0x000a;
|
||||
pub const _SC_OPEN_MAX: ::c_int = 0x000b;
|
||||
pub const _SC_PASS_MAX: ::c_int = 0x000c;
|
||||
pub const _SC_2_C_BIND: ::c_int = 0x000d;
|
||||
pub const _SC_2_C_DEV: ::c_int = 0x000e;
|
||||
pub const _SC_2_C_VERSION: ::c_int = 0x000f;
|
||||
pub const _SC_2_CHAR_TERM: ::c_int = 0x0010;
|
||||
pub const _SC_2_FORT_DEV: ::c_int = 0x0011;
|
||||
pub const _SC_2_FORT_RUN: ::c_int = 0x0012;
|
||||
pub const _SC_2_LOCALEDEF: ::c_int = 0x0013;
|
||||
pub const _SC_2_SW_DEV: ::c_int = 0x0014;
|
||||
pub const _SC_2_UPE: ::c_int = 0x0015;
|
||||
pub const _SC_2_VERSION: ::c_int = 0x0016;
|
||||
pub const _SC_JOB_CONTROL: ::c_int = 0x0017;
|
||||
pub const _SC_SAVED_IDS: ::c_int = 0x0018;
|
||||
pub const _SC_VERSION: ::c_int = 0x0019;
|
||||
pub const _SC_RE_DUP_MAX: ::c_int = 0x001a;
|
||||
pub const _SC_STREAM_MAX: ::c_int = 0x001b;
|
||||
pub const _SC_TZNAME_MAX: ::c_int = 0x001c;
|
||||
pub const _SC_XOPEN_CRYPT: ::c_int = 0x001d;
|
||||
pub const _SC_XOPEN_ENH_I18N: ::c_int = 0x001e;
|
||||
pub const _SC_XOPEN_SHM: ::c_int = 0x001f;
|
||||
pub const _SC_XOPEN_VERSION: ::c_int = 0x0020;
|
||||
pub const _SC_XOPEN_XCU_VERSION: ::c_int = 0x0021;
|
||||
pub const _SC_XOPEN_REALTIME: ::c_int = 0x0022;
|
||||
pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 0x0023;
|
||||
pub const _SC_XOPEN_LEGACY: ::c_int = 0x0024;
|
||||
pub const _SC_ATEXIT_MAX: ::c_int = 0x0025;
|
||||
pub const _SC_IOV_MAX: ::c_int = 0x0026;
|
||||
pub const _SC_UIO_MAXIOV: ::c_int = _SC_IOV_MAX;
|
||||
pub const _SC_PAGESIZE: ::c_int = 0x0027;
|
||||
pub const _SC_PAGE_SIZE: ::c_int = 0x0028;
|
||||
pub const _SC_XOPEN_UNIX: ::c_int = 0x0029;
|
||||
pub const _SC_XBS5_ILP32_OFF32: ::c_int = 0x002a;
|
||||
pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 0x002b;
|
||||
pub const _SC_XBS5_LP64_OFF64: ::c_int = 0x002c;
|
||||
pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 0x002d;
|
||||
pub const _SC_AIO_LISTIO_MAX: ::c_int = 0x002e;
|
||||
pub const _SC_AIO_MAX: ::c_int = 0x002f;
|
||||
pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 0x0030;
|
||||
pub const _SC_DELAYTIMER_MAX: ::c_int = 0x0031;
|
||||
pub const _SC_MQ_OPEN_MAX: ::c_int = 0x0032;
|
||||
pub const _SC_MQ_PRIO_MAX: ::c_int = 0x0033;
|
||||
pub const _SC_RTSIG_MAX: ::c_int = 0x0034;
|
||||
pub const _SC_SEM_NSEMS_MAX: ::c_int = 0x0035;
|
||||
pub const _SC_SEM_VALUE_MAX: ::c_int = 0x0036;
|
||||
pub const _SC_SIGQUEUE_MAX: ::c_int = 0x0037;
|
||||
pub const _SC_TIMER_MAX: ::c_int = 0x0038;
|
||||
pub const _SC_ASYNCHRONOUS_IO: ::c_int = 0x0039;
|
||||
pub const _SC_FSYNC: ::c_int = 0x003a;
|
||||
pub const _SC_MAPPED_FILES: ::c_int = 0x003b;
|
||||
pub const _SC_MEMLOCK: ::c_int = 0x003c;
|
||||
pub const _SC_MEMLOCK_RANGE: ::c_int = 0x003d;
|
||||
pub const _SC_MEMORY_PROTECTION: ::c_int = 0x003e;
|
||||
pub const _SC_MESSAGE_PASSING: ::c_int = 0x003f;
|
||||
pub const _SC_PRIORITIZED_IO: ::c_int = 0x0040;
|
||||
pub const _SC_PRIORITY_SCHEDULING: ::c_int = 0x0041;
|
||||
pub const _SC_REALTIME_SIGNALS: ::c_int = 0x0042;
|
||||
pub const _SC_SEMAPHORES: ::c_int = 0x0043;
|
||||
pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 0x0044;
|
||||
pub const _SC_SYNCHRONIZED_IO: ::c_int = 0x0045;
|
||||
pub const _SC_TIMERS: ::c_int = 0x0046;
|
||||
pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 0x0047;
|
||||
pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 0x0048;
|
||||
pub const _SC_LOGIN_NAME_MAX: ::c_int = 0x0049;
|
||||
pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 0x004a;
|
||||
pub const _SC_THREAD_KEYS_MAX: ::c_int = 0x004b;
|
||||
pub const _SC_THREAD_STACK_MIN: ::c_int = 0x004c;
|
||||
pub const _SC_THREAD_THREADS_MAX: ::c_int = 0x004d;
|
||||
pub const _SC_TTY_NAME_MAX: ::c_int = 0x004e;
|
||||
pub const _SC_THREADS: ::c_int = 0x004f;
|
||||
pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 0x0050;
|
||||
pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 0x0051;
|
||||
pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 0x0052;
|
||||
pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 0x0053;
|
||||
pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 0x0054;
|
||||
pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 0x0055;
|
||||
pub const _SC_NPROCESSORS_CONF: ::c_int = 0x0060;
|
||||
pub const _SC_NPROCESSORS_ONLN: ::c_int = 0x0061;
|
||||
pub const _SC_PHYS_PAGES: ::c_int = 0x0062;
|
||||
pub const _SC_AVPHYS_PAGES: ::c_int = 0x0063;
|
||||
pub const _SC_MONOTONIC_CLOCK: ::c_int = 0x0064;
|
||||
pub const _SC_2_PBS: ::c_int = 0x0065;
|
||||
pub const _SC_2_PBS_ACCOUNTING: ::c_int = 0x0066;
|
||||
pub const _SC_2_PBS_CHECKPOINT: ::c_int = 0x0067;
|
||||
pub const _SC_2_PBS_LOCATE: ::c_int = 0x0068;
|
||||
pub const _SC_2_PBS_MESSAGE: ::c_int = 0x0069;
|
||||
pub const _SC_2_PBS_TRACK: ::c_int = 0x006a;
|
||||
pub const _SC_ADVISORY_INFO: ::c_int = 0x006b;
|
||||
pub const _SC_BARRIERS: ::c_int = 0x006c;
|
||||
pub const _SC_CLOCK_SELECTION: ::c_int = 0x006d;
|
||||
pub const _SC_CPUTIME: ::c_int = 0x006e;
|
||||
pub const _SC_HOST_NAME_MAX: ::c_int = 0x006f;
|
||||
pub const _SC_IPV6: ::c_int = 0x0070;
|
||||
pub const _SC_RAW_SOCKETS: ::c_int = 0x0071;
|
||||
pub const _SC_READER_WRITER_LOCKS: ::c_int = 0x0072;
|
||||
pub const _SC_REGEXP: ::c_int = 0x0073;
|
||||
pub const _SC_SHELL: ::c_int = 0x0074;
|
||||
pub const _SC_SPAWN: ::c_int = 0x0075;
|
||||
pub const _SC_SPIN_LOCKS: ::c_int = 0x0076;
|
||||
pub const _SC_SPORADIC_SERVER: ::c_int = 0x0077;
|
||||
pub const _SC_SS_REPL_MAX: ::c_int = 0x0078;
|
||||
pub const _SC_SYMLOOP_MAX: ::c_int = 0x0079;
|
||||
pub const _SC_THREAD_CPUTIME: ::c_int = 0x007a;
|
||||
pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 0x007b;
|
||||
pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 0x007c;
|
||||
pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 0x007d;
|
||||
pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 0x007e;
|
||||
pub const _SC_TIMEOUTS: ::c_int = 0x007f;
|
||||
pub const _SC_TRACE: ::c_int = 0x0080;
|
||||
pub const _SC_TRACE_EVENT_FILTER: ::c_int = 0x0081;
|
||||
pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 0x0082;
|
||||
pub const _SC_TRACE_INHERIT: ::c_int = 0x0083;
|
||||
pub const _SC_TRACE_LOG: ::c_int = 0x0084;
|
||||
pub const _SC_TRACE_NAME_MAX: ::c_int = 0x0085;
|
||||
pub const _SC_TRACE_SYS_MAX: ::c_int = 0x0086;
|
||||
pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 0x0087;
|
||||
pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 0x0088;
|
||||
pub const _SC_V7_ILP32_OFF32: ::c_int = 0x0089;
|
||||
pub const _SC_V7_ILP32_OFFBIG: ::c_int = 0x008a;
|
||||
pub const _SC_V7_LP64_OFF64: ::c_int = 0x008b;
|
||||
pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 0x008c;
|
||||
pub const _SC_XOPEN_STREAMS: ::c_int = 0x008d;
|
||||
pub const _SC_XOPEN_UUCP: ::c_int = 0x008e;
|
||||
pub const _SC_LEVEL1_ICACHE_SIZE: ::c_int = 0x008f;
|
||||
pub const _SC_LEVEL1_ICACHE_ASSOC: ::c_int = 0x0090;
|
||||
pub const _SC_LEVEL1_ICACHE_LINESIZE: ::c_int = 0x0091;
|
||||
pub const _SC_LEVEL1_DCACHE_SIZE: ::c_int = 0x0092;
|
||||
pub const _SC_LEVEL1_DCACHE_ASSOC: ::c_int = 0x0093;
|
||||
pub const _SC_LEVEL1_DCACHE_LINESIZE: ::c_int = 0x0094;
|
||||
pub const _SC_LEVEL2_CACHE_SIZE: ::c_int = 0x0095;
|
||||
pub const _SC_LEVEL2_CACHE_ASSOC: ::c_int = 0x0096;
|
||||
pub const _SC_LEVEL2_CACHE_LINESIZE: ::c_int = 0x0097;
|
||||
pub const _SC_LEVEL3_CACHE_SIZE: ::c_int = 0x0098;
|
||||
pub const _SC_LEVEL3_CACHE_ASSOC: ::c_int = 0x0099;
|
||||
pub const _SC_LEVEL3_CACHE_LINESIZE: ::c_int = 0x009a;
|
||||
pub const _SC_LEVEL4_CACHE_SIZE: ::c_int = 0x009b;
|
||||
pub const _SC_LEVEL4_CACHE_ASSOC: ::c_int = 0x009c;
|
||||
pub const _SC_LEVEL4_CACHE_LINESIZE: ::c_int = 0x009d;
|
||||
|
||||
pub const F_LOCK: ::c_int = 1;
|
||||
pub const F_TEST: ::c_int = 3;
|
||||
|
@ -1328,6 +1347,7 @@ pub const IFF_LOWER_UP: ::c_int = 0x10000;
|
|||
pub const IFF_DORMANT: ::c_int = 0x20000;
|
||||
pub const IFF_ECHO: ::c_int = 0x40000;
|
||||
|
||||
pub const PTHREAD_BARRIER_SERIAL_THREAD: ::c_int = -1;
|
||||
pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0;
|
||||
pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1;
|
||||
pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2;
|
||||
|
@ -1741,6 +1761,7 @@ pub const ST_NODIRATIME: ::c_ulong = 2048;
|
|||
pub const ST_RELATIME: ::c_ulong = 4096;
|
||||
|
||||
pub const RTLD_NOLOAD: ::c_int = 0x4;
|
||||
pub const RTLD_NODELETE: ::c_int = 0x1000;
|
||||
|
||||
pub const SEM_FAILED: *mut sem_t = 0 as *mut sem_t;
|
||||
|
||||
|
@ -3002,6 +3023,7 @@ pub const FUTEX_WAIT_BITSET: ::c_int = 9;
|
|||
pub const FUTEX_WAKE_BITSET: ::c_int = 10;
|
||||
pub const FUTEX_WAIT_REQUEUE_PI: ::c_int = 11;
|
||||
pub const FUTEX_CMP_REQUEUE_PI: ::c_int = 12;
|
||||
pub const FUTEX_LOCK_PI2: ::c_int = 13;
|
||||
|
||||
pub const FUTEX_PRIVATE_FLAG: ::c_int = 128;
|
||||
pub const FUTEX_CLOCK_REALTIME: ::c_int = 256;
|
||||
|
@ -3501,6 +3523,18 @@ pub const PF_MEMALLOC_PIN: ::c_int = 0x10000000;
|
|||
|
||||
pub const PF_SUSPEND_TASK: ::c_int = 0x80000000;
|
||||
|
||||
pub const KLOG_CLOSE: ::c_int = 0;
|
||||
pub const KLOG_OPEN: ::c_int = 1;
|
||||
pub const KLOG_READ: ::c_int = 2;
|
||||
pub const KLOG_READ_ALL: ::c_int = 3;
|
||||
pub const KLOG_READ_CLEAR: ::c_int = 4;
|
||||
pub const KLOG_CLEAR: ::c_int = 5;
|
||||
pub const KLOG_CONSOLE_OFF: ::c_int = 6;
|
||||
pub const KLOG_CONSOLE_ON: ::c_int = 7;
|
||||
pub const KLOG_CONSOLE_LEVEL: ::c_int = 8;
|
||||
pub const KLOG_SIZE_UNREAD: ::c_int = 9;
|
||||
pub const KLOG_SIZE_BUFFER: ::c_int = 10;
|
||||
|
||||
// Most `*_SUPER_MAGIC` constants are defined at the `linux_like` level; the
|
||||
// following are only available on newer Linux versions than the versions
|
||||
// currently used in CI in some configurations, so we define them here.
|
||||
|
@ -4073,6 +4107,8 @@ extern "C" {
|
|||
) -> ::size_t;
|
||||
pub fn fflush_unlocked(stream: *mut ::FILE) -> ::c_int;
|
||||
pub fn fgets_unlocked(buf: *mut ::c_char, size: ::c_int, stream: *mut ::FILE) -> *mut ::c_char;
|
||||
|
||||
pub fn klogctl(syslog_type: ::c_int, bufp: *mut ::c_char, len: ::c_int) -> ::c_int;
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
|
|
|
@ -218,7 +218,7 @@ cfg_if! {
|
|||
// where S stands for size (int, long, struct...)
|
||||
// where T stands for type ('f','v','X'...)
|
||||
// where N stands for NR (NumbeR)
|
||||
if #[cfg(any(target_arch = "x86", target_arch = "arm"))] {
|
||||
if #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "csky"))] {
|
||||
pub const FS_IOC_GETFLAGS: ::Ioctl = 0x80046601;
|
||||
pub const FS_IOC_SETFLAGS: ::Ioctl = 0x40046602;
|
||||
pub const FS_IOC_GETVERSION: ::Ioctl = 0x80047601;
|
||||
|
|
|
@ -200,7 +200,7 @@ cfg_if! {
|
|||
// where S stands for size (int, long, struct...)
|
||||
// where T stands for type ('f','v','X'...)
|
||||
// where N stands for NR (NumbeR)
|
||||
if #[cfg(target_arch = "mips")] {
|
||||
if #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] {
|
||||
pub const FS_IOC_GETFLAGS: ::Ioctl = 0x40046601;
|
||||
pub const FS_IOC_SETFLAGS: ::Ioctl = 0x80046602;
|
||||
pub const FS_IOC_GETVERSION: ::Ioctl = 0x40047601;
|
||||
|
@ -209,7 +209,7 @@ cfg_if! {
|
|||
pub const FS_IOC32_SETFLAGS: ::Ioctl = 0x80046602;
|
||||
pub const FS_IOC32_GETVERSION: ::Ioctl = 0x40047601;
|
||||
pub const FS_IOC32_SETVERSION: ::Ioctl = 0x80047602;
|
||||
} else if #[cfg(target_arch = "mips64")] {
|
||||
} else if #[cfg(any(target_arch = "mips64", target_arch = "mips64r6"))] {
|
||||
pub const FS_IOC_GETFLAGS: ::Ioctl = 0x40086601;
|
||||
pub const FS_IOC_SETFLAGS: ::Ioctl = 0x80086602;
|
||||
pub const FS_IOC_GETVERSION: ::Ioctl = 0x40087601;
|
||||
|
|
|
@ -264,20 +264,20 @@ align_const! {
|
|||
};
|
||||
}
|
||||
|
||||
pub const HWCAP_CPUCFG: ::c_ulong = 1 << 0;
|
||||
pub const HWCAP_LAM: ::c_ulong = 1 << 1;
|
||||
pub const HWCAP_UAL: ::c_ulong = 1 << 2;
|
||||
pub const HWCAP_FPU: ::c_ulong = 1 << 3;
|
||||
pub const HWCAP_LSX: ::c_ulong = 1 << 4;
|
||||
pub const HWCAP_LASX: ::c_ulong = 1 << 5;
|
||||
pub const HWCAP_CRC32: ::c_ulong = 1 << 6;
|
||||
pub const HWCAP_COMPLEX: ::c_ulong = 1 << 7;
|
||||
pub const HWCAP_CRYPTO: ::c_ulong = 1 << 8;
|
||||
pub const HWCAP_LVZ: ::c_ulong = 1 << 9;
|
||||
pub const HWCAP_LBT_X86: ::c_ulong = 1 << 10;
|
||||
pub const HWCAP_LBT_ARM: ::c_ulong = 1 << 11;
|
||||
pub const HWCAP_LBT_MIPS: ::c_ulong = 1 << 12;
|
||||
pub const HWCAP_PTW: ::c_ulong = 1 << 13;
|
||||
pub const HWCAP_LOONGARCH_CPUCFG: ::c_ulong = 1 << 0;
|
||||
pub const HWCAP_LOONGARCH_LAM: ::c_ulong = 1 << 1;
|
||||
pub const HWCAP_LOONGARCH_UAL: ::c_ulong = 1 << 2;
|
||||
pub const HWCAP_LOONGARCH_FPU: ::c_ulong = 1 << 3;
|
||||
pub const HWCAP_LOONGARCH_LSX: ::c_ulong = 1 << 4;
|
||||
pub const HWCAP_LOONGARCH_LASX: ::c_ulong = 1 << 5;
|
||||
pub const HWCAP_LOONGARCH_CRC32: ::c_ulong = 1 << 6;
|
||||
pub const HWCAP_LOONGARCH_COMPLEX: ::c_ulong = 1 << 7;
|
||||
pub const HWCAP_LOONGARCH_CRYPTO: ::c_ulong = 1 << 8;
|
||||
pub const HWCAP_LOONGARCH_LVZ: ::c_ulong = 1 << 9;
|
||||
pub const HWCAP_LOONGARCH_LBT_X86: ::c_ulong = 1 << 10;
|
||||
pub const HWCAP_LOONGARCH_LBT_ARM: ::c_ulong = 1 << 11;
|
||||
pub const HWCAP_LOONGARCH_LBT_MIPS: ::c_ulong = 1 << 12;
|
||||
pub const HWCAP_LOONGARCH_PTW: ::c_ulong = 1 << 13;
|
||||
|
||||
pub const SYS_io_setup: ::c_long = 0;
|
||||
pub const SYS_io_destroy: ::c_long = 1;
|
||||
|
|
|
@ -42,3 +42,20 @@ s_no_extra_traits! {
|
|||
pub __glibc_reserved: [::c_uint; 3],
|
||||
}
|
||||
}
|
||||
|
||||
s! {
|
||||
#[repr(align(8))]
|
||||
pub struct clone_args {
|
||||
pub flags: ::c_ulonglong,
|
||||
pub pidfd: ::c_ulonglong,
|
||||
pub child_tid: ::c_ulonglong,
|
||||
pub parent_tid: ::c_ulonglong,
|
||||
pub exit_signal: ::c_ulonglong,
|
||||
pub stack: ::c_ulonglong,
|
||||
pub stack_size: ::c_ulonglong,
|
||||
pub tls: ::c_ulonglong,
|
||||
pub set_tid: ::c_ulonglong,
|
||||
pub set_tid_size: ::c_ulonglong,
|
||||
pub cgroup: ::c_ulonglong,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -540,6 +540,14 @@ pub const REG_A0: usize = 10;
|
|||
pub const REG_S2: usize = 18;
|
||||
pub const REG_NARGS: usize = 8;
|
||||
|
||||
pub const COMPAT_HWCAP_ISA_I: ::c_ulong = 1 << (b'I' - b'A');
|
||||
pub const COMPAT_HWCAP_ISA_M: ::c_ulong = 1 << (b'M' - b'A');
|
||||
pub const COMPAT_HWCAP_ISA_A: ::c_ulong = 1 << (b'A' - b'A');
|
||||
pub const COMPAT_HWCAP_ISA_F: ::c_ulong = 1 << (b'F' - b'A');
|
||||
pub const COMPAT_HWCAP_ISA_D: ::c_ulong = 1 << (b'D' - b'A');
|
||||
pub const COMPAT_HWCAP_ISA_C: ::c_ulong = 1 << (b'C' - b'A');
|
||||
pub const COMPAT_HWCAP_ISA_V: ::c_ulong = 1 << (b'V' - b'A');
|
||||
|
||||
pub const SYS_read: ::c_long = 63;
|
||||
pub const SYS_write: ::c_long = 64;
|
||||
pub const SYS_close: ::c_long = 57;
|
||||
|
|
|
@ -835,6 +835,9 @@ pub const TMP_MAX: ::c_uint = 238328;
|
|||
pub const FOPEN_MAX: ::c_uint = 16;
|
||||
pub const FILENAME_MAX: ::c_uint = 4096;
|
||||
pub const POSIX_MADV_DONTNEED: ::c_int = 4;
|
||||
pub const _CS_GNU_LIBC_VERSION: ::c_int = 2;
|
||||
pub const _CS_GNU_LIBPTHREAD_VERSION: ::c_int = 3;
|
||||
pub const _CS_PATH: ::c_int = 0;
|
||||
pub const _SC_EQUIV_CLASS_MAX: ::c_int = 41;
|
||||
pub const _SC_CHARCLASS_NAME_MAX: ::c_int = 45;
|
||||
pub const _SC_PII: ::c_int = 53;
|
||||
|
@ -1478,21 +1481,7 @@ extern "C" {
|
|||
pub fn asctime_r(tm: *const ::tm, buf: *mut ::c_char) -> *mut ::c_char;
|
||||
pub fn ctime_r(timep: *const time_t, buf: *mut ::c_char) -> *mut ::c_char;
|
||||
|
||||
pub fn strftime(
|
||||
s: *mut ::c_char,
|
||||
max: ::size_t,
|
||||
format: *const ::c_char,
|
||||
tm: *const ::tm,
|
||||
) -> ::size_t;
|
||||
pub fn strftime_l(
|
||||
s: *mut ::c_char,
|
||||
max: ::size_t,
|
||||
format: *const ::c_char,
|
||||
tm: *const ::tm,
|
||||
locale: ::locale_t,
|
||||
) -> ::size_t;
|
||||
pub fn strptime(s: *const ::c_char, format: *const ::c_char, tm: *mut ::tm) -> *mut ::c_char;
|
||||
|
||||
pub fn confstr(name: ::c_int, buf: *mut ::c_char, len: ::size_t) -> ::size_t;
|
||||
pub fn dirname(path: *mut ::c_char) -> *mut ::c_char;
|
||||
/// POSIX version of `basename(3)`, defined in `libgen.h`.
|
||||
#[link_name = "__xpg_basename"]
|
||||
|
|
|
@ -327,13 +327,14 @@ s! {
|
|||
// to false. So I'm just removing these, and if uClibc changes
|
||||
// the #if block in the future to include the following fields, these
|
||||
// will probably need including here. tsidea, skrap
|
||||
#[cfg(not(target_env = "uclibc"))]
|
||||
// QNX (NTO) platform does not define these fields
|
||||
#[cfg(not(any(target_env = "uclibc", target_os = "nto")))]
|
||||
pub dlpi_adds: ::c_ulonglong,
|
||||
#[cfg(not(target_env = "uclibc"))]
|
||||
#[cfg(not(any(target_env = "uclibc", target_os = "nto")))]
|
||||
pub dlpi_subs: ::c_ulonglong,
|
||||
#[cfg(not(target_env = "uclibc"))]
|
||||
#[cfg(not(any(target_env = "uclibc", target_os = "nto")))]
|
||||
pub dlpi_tls_modid: ::size_t,
|
||||
#[cfg(not(target_env = "uclibc"))]
|
||||
#[cfg(not(any(target_env = "uclibc", target_os = "nto")))]
|
||||
pub dlpi_tls_data: *mut ::c_void,
|
||||
}
|
||||
|
||||
|
@ -1841,6 +1842,7 @@ pub const AT_EXECFN: ::c_ulong = 31;
|
|||
// defined in arch/<arch>/include/uapi/asm/auxvec.h but has the same value
|
||||
// wherever it is defined.
|
||||
pub const AT_SYSINFO_EHDR: ::c_ulong = 33;
|
||||
pub const AT_MINSIGSTKSZ: ::c_ulong = 51;
|
||||
|
||||
pub const GLOB_ERR: ::c_int = 1 << 0;
|
||||
pub const GLOB_MARK: ::c_int = 1 << 1;
|
||||
|
@ -2063,6 +2065,7 @@ align_const! {
|
|||
size: [0; __SIZEOF_PTHREAD_RWLOCK_T],
|
||||
};
|
||||
}
|
||||
pub const PTHREAD_BARRIER_SERIAL_THREAD: ::c_int = -1;
|
||||
pub const PTHREAD_ONCE_INIT: pthread_once_t = 0;
|
||||
pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0;
|
||||
pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1;
|
||||
|
@ -4102,7 +4105,7 @@ pub const FAN_MARK_IGNORED_MASK: ::c_uint = 0x0000_0020;
|
|||
pub const FAN_MARK_IGNORED_SURV_MODIFY: ::c_uint = 0x0000_0040;
|
||||
pub const FAN_MARK_FLUSH: ::c_uint = 0x0000_0080;
|
||||
pub const FAN_MARK_EVICTABLE: ::c_uint = 0x0000_0200;
|
||||
pub const FAN_MARK_IGNORE: ::c_uint = 0x0000_0100;
|
||||
pub const FAN_MARK_IGNORE: ::c_uint = 0x0000_0400;
|
||||
|
||||
pub const FAN_MARK_INODE: ::c_uint = 0x0000_0000;
|
||||
pub const FAN_MARK_MOUNT: ::c_uint = 0x0000_0010;
|
||||
|
@ -4133,6 +4136,7 @@ pub const FAN_NOFD: ::c_int = -1;
|
|||
pub const FAN_NOPIDFD: ::c_int = FAN_NOFD;
|
||||
pub const FAN_EPIDFD: ::c_int = -2;
|
||||
|
||||
// linux/futex.h
|
||||
pub const FUTEX_WAIT: ::c_int = 0;
|
||||
pub const FUTEX_WAKE: ::c_int = 1;
|
||||
pub const FUTEX_FD: ::c_int = 2;
|
||||
|
@ -4152,6 +4156,10 @@ pub const FUTEX_PRIVATE_FLAG: ::c_int = 128;
|
|||
pub const FUTEX_CLOCK_REALTIME: ::c_int = 256;
|
||||
pub const FUTEX_CMD_MASK: ::c_int = !(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME);
|
||||
|
||||
pub const FUTEX_WAITERS: u32 = 0x80000000;
|
||||
pub const FUTEX_OWNER_DIED: u32 = 0x40000000;
|
||||
pub const FUTEX_TID_MASK: u32 = 0x3fffffff;
|
||||
|
||||
pub const FUTEX_BITSET_MATCH_ANY: ::c_int = 0xffffffff;
|
||||
|
||||
pub const FUTEX_OP_SET: ::c_int = 0;
|
||||
|
@ -4678,7 +4686,7 @@ f! {
|
|||
as *mut cmsghdr;
|
||||
let max = (*mhdr).msg_control as usize
|
||||
+ (*mhdr).msg_controllen as usize;
|
||||
if (next.offset(1)) as usize > max ||
|
||||
if (next.wrapping_offset(1)) as usize > max ||
|
||||
next as usize + super::CMSG_ALIGN((*next).cmsg_len as usize) > max
|
||||
{
|
||||
0 as *mut cmsghdr
|
||||
|
@ -4923,9 +4931,6 @@ cfg_if! {
|
|||
spbufp: *mut *mut spwd,
|
||||
) -> ::c_int;
|
||||
|
||||
pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int;
|
||||
pub fn shm_unlink(name: *const ::c_char) -> ::c_int;
|
||||
|
||||
pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t;
|
||||
pub fn mq_close(mqd: ::mqd_t) -> ::c_int;
|
||||
pub fn mq_unlink(name: *const ::c_char) -> ::c_int;
|
||||
|
@ -5012,6 +5017,9 @@ extern "C" {
|
|||
|
||||
pub fn getspnam(name: *const ::c_char) -> *mut spwd;
|
||||
|
||||
pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int;
|
||||
pub fn shm_unlink(name: *const ::c_char) -> ::c_int;
|
||||
|
||||
// System V IPC
|
||||
pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int;
|
||||
pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void;
|
||||
|
@ -5618,6 +5626,8 @@ extern "C" {
|
|||
len: ::size_t,
|
||||
flags: ::c_uint,
|
||||
) -> ::ssize_t;
|
||||
|
||||
pub fn klogctl(syslog_type: ::c_int, bufp: *mut ::c_char, len: ::c_int) -> ::c_int;
|
||||
}
|
||||
|
||||
// LFS64 extensions
|
||||
|
|
40
third_party/rust/libc/src/unix/linux_like/linux/musl/b64/loongarch64/align.rs
поставляемый
Normal file
40
third_party/rust/libc/src/unix/linux_like/linux/musl/b64/loongarch64/align.rs
поставляемый
Normal file
|
@ -0,0 +1,40 @@
|
|||
s_no_extra_traits! {
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[repr(align(16))]
|
||||
pub struct max_align_t {
|
||||
priv_: [f64; 4]
|
||||
}
|
||||
}
|
||||
|
||||
s! {
|
||||
pub struct ucontext_t {
|
||||
pub uc_flags: ::c_ulong,
|
||||
pub uc_link: *mut ucontext_t,
|
||||
pub uc_stack: ::stack_t,
|
||||
pub uc_sigmask: ::sigset_t,
|
||||
pub uc_mcontext: mcontext_t,
|
||||
}
|
||||
|
||||
#[repr(align(16))]
|
||||
pub struct mcontext_t {
|
||||
pub __pc: ::c_ulonglong,
|
||||
pub __gregs: [::c_ulonglong; 32],
|
||||
pub __flags: ::c_uint,
|
||||
pub __extcontext: [::c_ulonglong; 0],
|
||||
}
|
||||
|
||||
#[repr(align(8))]
|
||||
pub struct clone_args {
|
||||
pub flags: ::c_ulonglong,
|
||||
pub pidfd: ::c_ulonglong,
|
||||
pub child_tid: ::c_ulonglong,
|
||||
pub parent_tid: ::c_ulonglong,
|
||||
pub exit_signal: ::c_ulonglong,
|
||||
pub stack: ::c_ulonglong,
|
||||
pub stack_size: ::c_ulonglong,
|
||||
pub tls: ::c_ulonglong,
|
||||
pub set_tid: ::c_ulonglong,
|
||||
pub set_tid_size: ::c_ulonglong,
|
||||
pub cgroup: ::c_ulonglong,
|
||||
}
|
||||
}
|
669
third_party/rust/libc/src/unix/linux_like/linux/musl/b64/loongarch64/mod.rs
поставляемый
Normal file
669
third_party/rust/libc/src/unix/linux_like/linux/musl/b64/loongarch64/mod.rs
поставляемый
Normal file
|
@ -0,0 +1,669 @@
|
|||
//! LoongArch-specific definitions for 64-bit linux-like values
|
||||
|
||||
pub type c_char = i8;
|
||||
pub type wchar_t = ::c_int;
|
||||
|
||||
pub type nlink_t = ::c_uint;
|
||||
pub type blksize_t = ::c_int;
|
||||
pub type fsblkcnt64_t = ::c_ulong;
|
||||
pub type fsfilcnt64_t = ::c_ulong;
|
||||
pub type __u64 = ::c_ulonglong;
|
||||
pub type __s64 = ::c_longlong;
|
||||
|
||||
s! {
|
||||
pub struct pthread_attr_t {
|
||||
__size: [::c_ulong; 7],
|
||||
}
|
||||
|
||||
pub struct stat {
|
||||
pub st_dev: ::dev_t,
|
||||
pub st_ino: ::ino_t,
|
||||
pub st_mode: ::mode_t,
|
||||
pub st_nlink: ::nlink_t,
|
||||
pub st_uid: ::uid_t,
|
||||
pub st_gid: ::gid_t,
|
||||
pub st_rdev: ::dev_t,
|
||||
__pad1: ::dev_t,
|
||||
pub st_size: ::off_t,
|
||||
pub st_blksize: ::blksize_t,
|
||||
__pad2: ::c_int,
|
||||
pub st_blocks: ::blkcnt_t,
|
||||
pub st_atime: ::time_t,
|
||||
pub st_atime_nsec: ::c_long,
|
||||
pub st_mtime: ::time_t,
|
||||
pub st_mtime_nsec: ::c_long,
|
||||
pub st_ctime: ::time_t,
|
||||
pub st_ctime_nsec: ::c_long,
|
||||
__unused: [::c_int; 2usize],
|
||||
}
|
||||
|
||||
pub struct stat64 {
|
||||
pub st_dev: ::dev_t,
|
||||
pub st_ino: ::ino64_t,
|
||||
pub st_mode: ::mode_t,
|
||||
pub st_nlink: ::nlink_t,
|
||||
pub st_uid: ::uid_t,
|
||||
pub st_gid: ::gid_t,
|
||||
pub st_rdev: ::dev_t,
|
||||
pub __pad1: ::dev_t,
|
||||
pub st_size: ::off64_t,
|
||||
pub st_blksize: ::blksize_t,
|
||||
pub __pad2: ::c_int,
|
||||
pub st_blocks: ::blkcnt_t,
|
||||
pub st_atime: ::time_t,
|
||||
pub st_atime_nsec: ::c_long,
|
||||
pub st_mtime: ::time_t,
|
||||
pub st_mtime_nsec: ::c_long,
|
||||
pub st_ctime: ::time_t,
|
||||
pub st_ctime_nsec: ::c_long,
|
||||
__unused: [::c_int; 2],
|
||||
}
|
||||
|
||||
pub struct statfs {
|
||||
pub f_type: ::c_long,
|
||||
pub f_bsize: ::c_long,
|
||||
pub f_blocks: ::fsblkcnt_t,
|
||||
pub f_bfree: ::fsblkcnt_t,
|
||||
pub f_bavail: ::fsblkcnt_t,
|
||||
pub f_files: ::fsfilcnt_t,
|
||||
pub f_ffree: ::fsfilcnt_t,
|
||||
pub f_fsid: ::fsid_t,
|
||||
pub f_namelen: ::c_long,
|
||||
pub f_frsize: ::c_long,
|
||||
pub f_flags: ::c_long,
|
||||
pub f_spare: [::c_long; 4],
|
||||
}
|
||||
|
||||
pub struct statfs64 {
|
||||
pub f_type: ::c_long,
|
||||
pub f_bsize: ::c_long,
|
||||
pub f_blocks: ::fsblkcnt64_t,
|
||||
pub f_bfree: ::fsblkcnt64_t,
|
||||
pub f_bavail: ::fsblkcnt64_t,
|
||||
pub f_files: ::fsfilcnt64_t,
|
||||
pub f_ffree: ::fsfilcnt64_t,
|
||||
pub f_fsid: ::fsid_t,
|
||||
pub f_namelen: ::c_long,
|
||||
pub f_frsize: ::c_long,
|
||||
pub f_flags: ::c_long,
|
||||
pub f_spare: [::c_long; 4],
|
||||
}
|
||||
|
||||
pub struct ipc_perm {
|
||||
pub __key: ::key_t,
|
||||
pub uid: ::uid_t,
|
||||
pub gid: ::gid_t,
|
||||
pub cuid: ::uid_t,
|
||||
pub cgid: ::gid_t,
|
||||
pub mode: ::c_uint,
|
||||
pub __seq: ::c_ushort,
|
||||
__pad2: ::c_ushort,
|
||||
__unused1: ::c_ulong,
|
||||
__unused2: ::c_ulong,
|
||||
}
|
||||
|
||||
pub struct user_regs_struct {
|
||||
pub regs: [u64; 32],
|
||||
pub orig_a0: u64,
|
||||
pub csr_era: u64,
|
||||
pub csr_badv: u64,
|
||||
pub reserved: [u64; 10],
|
||||
|
||||
}
|
||||
|
||||
pub struct user_fp_struct {
|
||||
pub fpr: [u64; 32],
|
||||
pub fcc: u64,
|
||||
pub fcsr: u32,
|
||||
}
|
||||
}
|
||||
|
||||
pub const SYS_io_setup: ::c_long = 0;
|
||||
pub const SYS_io_destroy: ::c_long = 1;
|
||||
pub const SYS_io_submit: ::c_long = 2;
|
||||
pub const SYS_io_cancel: ::c_long = 3;
|
||||
pub const SYS_io_getevents: ::c_long = 4;
|
||||
pub const SYS_setxattr: ::c_long = 5;
|
||||
pub const SYS_lsetxattr: ::c_long = 6;
|
||||
pub const SYS_fsetxattr: ::c_long = 7;
|
||||
pub const SYS_getxattr: ::c_long = 8;
|
||||
pub const SYS_lgetxattr: ::c_long = 9;
|
||||
pub const SYS_fgetxattr: ::c_long = 10;
|
||||
pub const SYS_listxattr: ::c_long = 11;
|
||||
pub const SYS_llistxattr: ::c_long = 12;
|
||||
pub const SYS_flistxattr: ::c_long = 13;
|
||||
pub const SYS_removexattr: ::c_long = 14;
|
||||
pub const SYS_lremovexattr: ::c_long = 15;
|
||||
pub const SYS_fremovexattr: ::c_long = 16;
|
||||
pub const SYS_getcwd: ::c_long = 17;
|
||||
pub const SYS_lookup_dcookie: ::c_long = 18;
|
||||
pub const SYS_eventfd2: ::c_long = 19;
|
||||
pub const SYS_epoll_create1: ::c_long = 20;
|
||||
pub const SYS_epoll_ctl: ::c_long = 21;
|
||||
pub const SYS_epoll_pwait: ::c_long = 22;
|
||||
pub const SYS_dup: ::c_long = 23;
|
||||
pub const SYS_dup3: ::c_long = 24;
|
||||
pub const SYS_fcntl: ::c_long = 25;
|
||||
pub const SYS_inotify_init1: ::c_long = 26;
|
||||
pub const SYS_inotify_add_watch: ::c_long = 27;
|
||||
pub const SYS_inotify_rm_watch: ::c_long = 28;
|
||||
pub const SYS_ioctl: ::c_long = 29;
|
||||
pub const SYS_ioprio_set: ::c_long = 30;
|
||||
pub const SYS_ioprio_get: ::c_long = 31;
|
||||
pub const SYS_flock: ::c_long = 32;
|
||||
pub const SYS_mknodat: ::c_long = 33;
|
||||
pub const SYS_mkdirat: ::c_long = 34;
|
||||
pub const SYS_unlinkat: ::c_long = 35;
|
||||
pub const SYS_symlinkat: ::c_long = 36;
|
||||
pub const SYS_linkat: ::c_long = 37;
|
||||
pub const SYS_umount2: ::c_long = 39;
|
||||
pub const SYS_mount: ::c_long = 40;
|
||||
pub const SYS_pivot_root: ::c_long = 41;
|
||||
pub const SYS_nfsservctl: ::c_long = 42;
|
||||
pub const SYS_statfs: ::c_long = 43;
|
||||
pub const SYS_fstatfs: ::c_long = 44;
|
||||
pub const SYS_truncate: ::c_long = 45;
|
||||
pub const SYS_ftruncate: ::c_long = 46;
|
||||
pub const SYS_fallocate: ::c_long = 47;
|
||||
pub const SYS_faccessat: ::c_long = 48;
|
||||
pub const SYS_chdir: ::c_long = 49;
|
||||
pub const SYS_fchdir: ::c_long = 50;
|
||||
pub const SYS_chroot: ::c_long = 51;
|
||||
pub const SYS_fchmod: ::c_long = 52;
|
||||
pub const SYS_fchmodat: ::c_long = 53;
|
||||
pub const SYS_fchownat: ::c_long = 54;
|
||||
pub const SYS_fchown: ::c_long = 55;
|
||||
pub const SYS_openat: ::c_long = 56;
|
||||
pub const SYS_close: ::c_long = 57;
|
||||
pub const SYS_vhangup: ::c_long = 58;
|
||||
pub const SYS_pipe2: ::c_long = 59;
|
||||
pub const SYS_quotactl: ::c_long = 60;
|
||||
pub const SYS_getdents64: ::c_long = 61;
|
||||
pub const SYS_lseek: ::c_long = 62;
|
||||
pub const SYS_read: ::c_long = 63;
|
||||
pub const SYS_write: ::c_long = 64;
|
||||
pub const SYS_readv: ::c_long = 65;
|
||||
pub const SYS_writev: ::c_long = 66;
|
||||
pub const SYS_pread64: ::c_long = 67;
|
||||
pub const SYS_pwrite64: ::c_long = 68;
|
||||
pub const SYS_preadv: ::c_long = 69;
|
||||
pub const SYS_pwritev: ::c_long = 70;
|
||||
pub const SYS_sendfile: ::c_long = 71;
|
||||
pub const SYS_pselect6: ::c_long = 72;
|
||||
pub const SYS_ppoll: ::c_long = 73;
|
||||
pub const SYS_signalfd4: ::c_long = 74;
|
||||
pub const SYS_vmsplice: ::c_long = 75;
|
||||
pub const SYS_splice: ::c_long = 76;
|
||||
pub const SYS_tee: ::c_long = 77;
|
||||
pub const SYS_readlinkat: ::c_long = 78;
|
||||
pub const SYS_sync: ::c_long = 81;
|
||||
pub const SYS_fsync: ::c_long = 82;
|
||||
pub const SYS_fdatasync: ::c_long = 83;
|
||||
pub const SYS_sync_file_range: ::c_long = 84;
|
||||
pub const SYS_timerfd_create: ::c_long = 85;
|
||||
pub const SYS_timerfd_settime: ::c_long = 86;
|
||||
pub const SYS_timerfd_gettime: ::c_long = 87;
|
||||
pub const SYS_utimensat: ::c_long = 88;
|
||||
pub const SYS_acct: ::c_long = 89;
|
||||
pub const SYS_capget: ::c_long = 90;
|
||||
pub const SYS_capset: ::c_long = 91;
|
||||
pub const SYS_personality: ::c_long = 92;
|
||||
pub const SYS_exit: ::c_long = 93;
|
||||
pub const SYS_exit_group: ::c_long = 94;
|
||||
pub const SYS_waitid: ::c_long = 95;
|
||||
pub const SYS_set_tid_address: ::c_long = 96;
|
||||
pub const SYS_unshare: ::c_long = 97;
|
||||
pub const SYS_futex: ::c_long = 98;
|
||||
pub const SYS_set_robust_list: ::c_long = 99;
|
||||
pub const SYS_get_robust_list: ::c_long = 100;
|
||||
pub const SYS_nanosleep: ::c_long = 101;
|
||||
pub const SYS_getitimer: ::c_long = 102;
|
||||
pub const SYS_setitimer: ::c_long = 103;
|
||||
pub const SYS_kexec_load: ::c_long = 104;
|
||||
pub const SYS_init_module: ::c_long = 105;
|
||||
pub const SYS_delete_module: ::c_long = 106;
|
||||
pub const SYS_timer_create: ::c_long = 107;
|
||||
pub const SYS_timer_gettime: ::c_long = 108;
|
||||
pub const SYS_timer_getoverrun: ::c_long = 109;
|
||||
pub const SYS_timer_settime: ::c_long = 110;
|
||||
pub const SYS_timer_delete: ::c_long = 111;
|
||||
pub const SYS_clock_settime: ::c_long = 112;
|
||||
pub const SYS_clock_gettime: ::c_long = 113;
|
||||
pub const SYS_clock_getres: ::c_long = 114;
|
||||
pub const SYS_clock_nanosleep: ::c_long = 115;
|
||||
pub const SYS_syslog: ::c_long = 116;
|
||||
pub const SYS_ptrace: ::c_long = 117;
|
||||
pub const SYS_sched_setparam: ::c_long = 118;
|
||||
pub const SYS_sched_setscheduler: ::c_long = 119;
|
||||
pub const SYS_sched_getscheduler: ::c_long = 120;
|
||||
pub const SYS_sched_getparam: ::c_long = 121;
|
||||
pub const SYS_sched_setaffinity: ::c_long = 122;
|
||||
pub const SYS_sched_getaffinity: ::c_long = 123;
|
||||
pub const SYS_sched_yield: ::c_long = 124;
|
||||
pub const SYS_sched_get_priority_max: ::c_long = 125;
|
||||
pub const SYS_sched_get_priority_min: ::c_long = 126;
|
||||
pub const SYS_sched_rr_get_interval: ::c_long = 127;
|
||||
pub const SYS_restart_syscall: ::c_long = 128;
|
||||
pub const SYS_kill: ::c_long = 129;
|
||||
pub const SYS_tkill: ::c_long = 130;
|
||||
pub const SYS_tgkill: ::c_long = 131;
|
||||
pub const SYS_sigaltstack: ::c_long = 132;
|
||||
pub const SYS_rt_sigsuspend: ::c_long = 133;
|
||||
pub const SYS_rt_sigaction: ::c_long = 134;
|
||||
pub const SYS_rt_sigprocmask: ::c_long = 135;
|
||||
pub const SYS_rt_sigpending: ::c_long = 136;
|
||||
pub const SYS_rt_sigtimedwait: ::c_long = 137;
|
||||
pub const SYS_rt_sigqueueinfo: ::c_long = 138;
|
||||
pub const SYS_rt_sigreturn: ::c_long = 139;
|
||||
pub const SYS_setpriority: ::c_long = 140;
|
||||
pub const SYS_getpriority: ::c_long = 141;
|
||||
pub const SYS_reboot: ::c_long = 142;
|
||||
pub const SYS_setregid: ::c_long = 143;
|
||||
pub const SYS_setgid: ::c_long = 144;
|
||||
pub const SYS_setreuid: ::c_long = 145;
|
||||
pub const SYS_setuid: ::c_long = 146;
|
||||
pub const SYS_setresuid: ::c_long = 147;
|
||||
pub const SYS_getresuid: ::c_long = 148;
|
||||
pub const SYS_setresgid: ::c_long = 149;
|
||||
pub const SYS_getresgid: ::c_long = 150;
|
||||
pub const SYS_setfsuid: ::c_long = 151;
|
||||
pub const SYS_setfsgid: ::c_long = 152;
|
||||
pub const SYS_times: ::c_long = 153;
|
||||
pub const SYS_setpgid: ::c_long = 154;
|
||||
pub const SYS_getpgid: ::c_long = 155;
|
||||
pub const SYS_getsid: ::c_long = 156;
|
||||
pub const SYS_setsid: ::c_long = 157;
|
||||
pub const SYS_getgroups: ::c_long = 158;
|
||||
pub const SYS_setgroups: ::c_long = 159;
|
||||
pub const SYS_uname: ::c_long = 160;
|
||||
pub const SYS_sethostname: ::c_long = 161;
|
||||
pub const SYS_setdomainname: ::c_long = 162;
|
||||
pub const SYS_getrusage: ::c_long = 165;
|
||||
pub const SYS_umask: ::c_long = 166;
|
||||
pub const SYS_prctl: ::c_long = 167;
|
||||
pub const SYS_getcpu: ::c_long = 168;
|
||||
pub const SYS_gettimeofday: ::c_long = 169;
|
||||
pub const SYS_settimeofday: ::c_long = 170;
|
||||
pub const SYS_adjtimex: ::c_long = 171;
|
||||
pub const SYS_getpid: ::c_long = 172;
|
||||
pub const SYS_getppid: ::c_long = 173;
|
||||
pub const SYS_getuid: ::c_long = 174;
|
||||
pub const SYS_geteuid: ::c_long = 175;
|
||||
pub const SYS_getgid: ::c_long = 176;
|
||||
pub const SYS_getegid: ::c_long = 177;
|
||||
pub const SYS_gettid: ::c_long = 178;
|
||||
pub const SYS_sysinfo: ::c_long = 179;
|
||||
pub const SYS_mq_open: ::c_long = 180;
|
||||
pub const SYS_mq_unlink: ::c_long = 181;
|
||||
pub const SYS_mq_timedsend: ::c_long = 182;
|
||||
pub const SYS_mq_timedreceive: ::c_long = 183;
|
||||
pub const SYS_mq_notify: ::c_long = 184;
|
||||
pub const SYS_mq_getsetattr: ::c_long = 185;
|
||||
pub const SYS_msgget: ::c_long = 186;
|
||||
pub const SYS_msgctl: ::c_long = 187;
|
||||
pub const SYS_msgrcv: ::c_long = 188;
|
||||
pub const SYS_msgsnd: ::c_long = 189;
|
||||
pub const SYS_semget: ::c_long = 190;
|
||||
pub const SYS_semctl: ::c_long = 191;
|
||||
pub const SYS_semtimedop: ::c_long = 192;
|
||||
pub const SYS_semop: ::c_long = 193;
|
||||
pub const SYS_shmget: ::c_long = 194;
|
||||
pub const SYS_shmctl: ::c_long = 195;
|
||||
pub const SYS_shmat: ::c_long = 196;
|
||||
pub const SYS_shmdt: ::c_long = 197;
|
||||
pub const SYS_socket: ::c_long = 198;
|
||||
pub const SYS_socketpair: ::c_long = 199;
|
||||
pub const SYS_bind: ::c_long = 200;
|
||||
pub const SYS_listen: ::c_long = 201;
|
||||
pub const SYS_accept: ::c_long = 202;
|
||||
pub const SYS_connect: ::c_long = 203;
|
||||
pub const SYS_getsockname: ::c_long = 204;
|
||||
pub const SYS_getpeername: ::c_long = 205;
|
||||
pub const SYS_sendto: ::c_long = 206;
|
||||
pub const SYS_recvfrom: ::c_long = 207;
|
||||
pub const SYS_setsockopt: ::c_long = 208;
|
||||
pub const SYS_getsockopt: ::c_long = 209;
|
||||
pub const SYS_shutdown: ::c_long = 210;
|
||||
pub const SYS_sendmsg: ::c_long = 211;
|
||||
pub const SYS_recvmsg: ::c_long = 212;
|
||||
pub const SYS_readahead: ::c_long = 213;
|
||||
pub const SYS_brk: ::c_long = 214;
|
||||
pub const SYS_munmap: ::c_long = 215;
|
||||
pub const SYS_mremap: ::c_long = 216;
|
||||
pub const SYS_add_key: ::c_long = 217;
|
||||
pub const SYS_request_key: ::c_long = 218;
|
||||
pub const SYS_keyctl: ::c_long = 219;
|
||||
pub const SYS_clone: ::c_long = 220;
|
||||
pub const SYS_execve: ::c_long = 221;
|
||||
pub const SYS_mmap: ::c_long = 222;
|
||||
pub const SYS_fadvise64: ::c_long = 223;
|
||||
pub const SYS_swapon: ::c_long = 224;
|
||||
pub const SYS_swapoff: ::c_long = 225;
|
||||
pub const SYS_mprotect: ::c_long = 226;
|
||||
pub const SYS_msync: ::c_long = 227;
|
||||
pub const SYS_mlock: ::c_long = 228;
|
||||
pub const SYS_munlock: ::c_long = 229;
|
||||
pub const SYS_mlockall: ::c_long = 230;
|
||||
pub const SYS_munlockall: ::c_long = 231;
|
||||
pub const SYS_mincore: ::c_long = 232;
|
||||
pub const SYS_madvise: ::c_long = 233;
|
||||
pub const SYS_remap_file_pages: ::c_long = 234;
|
||||
pub const SYS_mbind: ::c_long = 235;
|
||||
pub const SYS_get_mempolicy: ::c_long = 236;
|
||||
pub const SYS_set_mempolicy: ::c_long = 237;
|
||||
pub const SYS_migrate_pages: ::c_long = 238;
|
||||
pub const SYS_move_pages: ::c_long = 239;
|
||||
pub const SYS_rt_tgsigqueueinfo: ::c_long = 240;
|
||||
pub const SYS_perf_event_open: ::c_long = 241;
|
||||
pub const SYS_accept4: ::c_long = 242;
|
||||
pub const SYS_recvmmsg: ::c_long = 243;
|
||||
pub const SYS_arch_specific_syscall: ::c_long = 244;
|
||||
pub const SYS_wait4: ::c_long = 260;
|
||||
pub const SYS_prlimit64: ::c_long = 261;
|
||||
pub const SYS_fanotify_init: ::c_long = 262;
|
||||
pub const SYS_fanotify_mark: ::c_long = 263;
|
||||
pub const SYS_name_to_handle_at: ::c_long = 264;
|
||||
pub const SYS_open_by_handle_at: ::c_long = 265;
|
||||
pub const SYS_clock_adjtime: ::c_long = 266;
|
||||
pub const SYS_syncfs: ::c_long = 267;
|
||||
pub const SYS_setns: ::c_long = 268;
|
||||
pub const SYS_sendmmsg: ::c_long = 269;
|
||||
pub const SYS_process_vm_readv: ::c_long = 270;
|
||||
pub const SYS_process_vm_writev: ::c_long = 271;
|
||||
pub const SYS_kcmp: ::c_long = 272;
|
||||
pub const SYS_finit_module: ::c_long = 273;
|
||||
pub const SYS_sched_setattr: ::c_long = 274;
|
||||
pub const SYS_sched_getattr: ::c_long = 275;
|
||||
pub const SYS_renameat2: ::c_long = 276;
|
||||
pub const SYS_seccomp: ::c_long = 277;
|
||||
pub const SYS_getrandom: ::c_long = 278;
|
||||
pub const SYS_memfd_create: ::c_long = 279;
|
||||
pub const SYS_bpf: ::c_long = 280;
|
||||
pub const SYS_execveat: ::c_long = 281;
|
||||
pub const SYS_userfaultfd: ::c_long = 282;
|
||||
pub const SYS_membarrier: ::c_long = 283;
|
||||
pub const SYS_mlock2: ::c_long = 284;
|
||||
pub const SYS_copy_file_range: ::c_long = 285;
|
||||
pub const SYS_preadv2: ::c_long = 286;
|
||||
pub const SYS_pwritev2: ::c_long = 287;
|
||||
pub const SYS_pkey_mprotect: ::c_long = 288;
|
||||
pub const SYS_pkey_alloc: ::c_long = 289;
|
||||
pub const SYS_pkey_free: ::c_long = 290;
|
||||
pub const SYS_statx: ::c_long = 291;
|
||||
pub const SYS_io_pgetevents: ::c_long = 292;
|
||||
pub const SYS_rseq: ::c_long = 293;
|
||||
pub const SYS_kexec_file_load: ::c_long = 294;
|
||||
pub const SYS_pidfd_send_signal: ::c_long = 424;
|
||||
pub const SYS_io_uring_setup: ::c_long = 425;
|
||||
pub const SYS_io_uring_enter: ::c_long = 426;
|
||||
pub const SYS_io_uring_register: ::c_long = 427;
|
||||
pub const SYS_open_tree: ::c_long = 428;
|
||||
pub const SYS_move_mount: ::c_long = 429;
|
||||
pub const SYS_fsopen: ::c_long = 430;
|
||||
pub const SYS_fsconfig: ::c_long = 431;
|
||||
pub const SYS_fsmount: ::c_long = 432;
|
||||
pub const SYS_fspick: ::c_long = 433;
|
||||
pub const SYS_pidfd_open: ::c_long = 434;
|
||||
pub const SYS_clone3: ::c_long = 435;
|
||||
pub const SYS_close_range: ::c_long = 436;
|
||||
pub const SYS_openat2: ::c_long = 437;
|
||||
pub const SYS_pidfd_getfd: ::c_long = 438;
|
||||
pub const SYS_faccessat2: ::c_long = 439;
|
||||
pub const SYS_process_madvise: ::c_long = 440;
|
||||
pub const SYS_epoll_pwait2: ::c_long = 441;
|
||||
pub const SYS_mount_setattr: ::c_long = 442;
|
||||
pub const SYS_quotactl_fd: ::c_long = 443;
|
||||
pub const SYS_landlock_create_ruleset: ::c_long = 444;
|
||||
pub const SYS_landlock_add_rule: ::c_long = 445;
|
||||
pub const SYS_landlock_restrict_self: ::c_long = 446;
|
||||
pub const SYS_process_mrelease: ::c_long = 448;
|
||||
pub const SYS_futex_waitv: ::c_long = 449;
|
||||
pub const SYS_set_mempolicy_home_node: ::c_long = 450;
|
||||
pub const SYS_cachestat: ::c_long = 451;
|
||||
pub const SYS_fchmodat2: ::c_long = 452;
|
||||
pub const SYS_map_shadow_stack: ::c_long = 453;
|
||||
pub const SYS_futex_wake: ::c_long = 454;
|
||||
pub const SYS_futex_wait: ::c_long = 455;
|
||||
pub const SYS_futex_requeue: ::c_long = 456;
|
||||
|
||||
pub const O_APPEND: ::c_int = 1024;
|
||||
pub const O_DIRECT: ::c_int = 0x4000;
|
||||
pub const O_DIRECTORY: ::c_int = 0x10000;
|
||||
pub const O_LARGEFILE: ::c_int = 0;
|
||||
pub const O_NOFOLLOW: ::c_int = 0x20000;
|
||||
pub const O_CREAT: ::c_int = 64;
|
||||
pub const O_EXCL: ::c_int = 128;
|
||||
pub const O_NOCTTY: ::c_int = 256;
|
||||
pub const O_NONBLOCK: ::c_int = 2048;
|
||||
pub const O_SYNC: ::c_int = 1052672;
|
||||
pub const O_RSYNC: ::c_int = 1052672;
|
||||
pub const O_DSYNC: ::c_int = 4096;
|
||||
pub const O_ASYNC: ::c_int = 4096;
|
||||
|
||||
pub const SIGSTKSZ: ::size_t = 16384;
|
||||
pub const MINSIGSTKSZ: ::size_t = 4096;
|
||||
|
||||
pub const ENAMETOOLONG: ::c_int = 36;
|
||||
pub const ENOLCK: ::c_int = 37;
|
||||
pub const ENOSYS: ::c_int = 38;
|
||||
pub const ENOTEMPTY: ::c_int = 39;
|
||||
pub const ELOOP: ::c_int = 40;
|
||||
pub const ENOMSG: ::c_int = 42;
|
||||
pub const EIDRM: ::c_int = 43;
|
||||
pub const ECHRNG: ::c_int = 44;
|
||||
pub const EL2NSYNC: ::c_int = 45;
|
||||
pub const EL3HLT: ::c_int = 46;
|
||||
pub const EL3RST: ::c_int = 47;
|
||||
pub const ELNRNG: ::c_int = 48;
|
||||
pub const EUNATCH: ::c_int = 49;
|
||||
pub const ENOCSI: ::c_int = 50;
|
||||
pub const EL2HLT: ::c_int = 51;
|
||||
pub const EBADE: ::c_int = 52;
|
||||
pub const EBADR: ::c_int = 53;
|
||||
pub const EXFULL: ::c_int = 54;
|
||||
pub const ENOANO: ::c_int = 55;
|
||||
pub const EBADRQC: ::c_int = 56;
|
||||
pub const EBADSLT: ::c_int = 57;
|
||||
pub const EMULTIHOP: ::c_int = 72;
|
||||
pub const EOVERFLOW: ::c_int = 75;
|
||||
pub const ENOTUNIQ: ::c_int = 76;
|
||||
pub const EBADFD: ::c_int = 77;
|
||||
pub const EBADMSG: ::c_int = 74;
|
||||
pub const EREMCHG: ::c_int = 78;
|
||||
pub const ELIBACC: ::c_int = 79;
|
||||
pub const ELIBBAD: ::c_int = 80;
|
||||
pub const ELIBSCN: ::c_int = 81;
|
||||
pub const ELIBMAX: ::c_int = 82;
|
||||
pub const ELIBEXEC: ::c_int = 83;
|
||||
pub const EILSEQ: ::c_int = 84;
|
||||
pub const ERESTART: ::c_int = 85;
|
||||
pub const ESTRPIPE: ::c_int = 86;
|
||||
pub const EUSERS: ::c_int = 87;
|
||||
pub const ENOTSOCK: ::c_int = 88;
|
||||
pub const EDESTADDRREQ: ::c_int = 89;
|
||||
pub const EMSGSIZE: ::c_int = 90;
|
||||
pub const EPROTOTYPE: ::c_int = 91;
|
||||
pub const ENOPROTOOPT: ::c_int = 92;
|
||||
pub const EPROTONOSUPPORT: ::c_int = 93;
|
||||
pub const ESOCKTNOSUPPORT: ::c_int = 94;
|
||||
pub const EOPNOTSUPP: ::c_int = 95;
|
||||
pub const ENOTSUP: ::c_int = EOPNOTSUPP;
|
||||
pub const EPFNOSUPPORT: ::c_int = 96;
|
||||
pub const EAFNOSUPPORT: ::c_int = 97;
|
||||
pub const EADDRINUSE: ::c_int = 98;
|
||||
pub const EADDRNOTAVAIL: ::c_int = 99;
|
||||
pub const ENETDOWN: ::c_int = 100;
|
||||
pub const ENETUNREACH: ::c_int = 101;
|
||||
pub const ENETRESET: ::c_int = 102;
|
||||
pub const ECONNABORTED: ::c_int = 103;
|
||||
pub const ECONNRESET: ::c_int = 104;
|
||||
pub const ENOBUFS: ::c_int = 105;
|
||||
pub const EISCONN: ::c_int = 106;
|
||||
pub const ENOTCONN: ::c_int = 107;
|
||||
pub const ESHUTDOWN: ::c_int = 108;
|
||||
pub const ETOOMANYREFS: ::c_int = 109;
|
||||
pub const ETIMEDOUT: ::c_int = 110;
|
||||
pub const ECONNREFUSED: ::c_int = 111;
|
||||
pub const EHOSTDOWN: ::c_int = 112;
|
||||
pub const EHOSTUNREACH: ::c_int = 113;
|
||||
pub const EALREADY: ::c_int = 114;
|
||||
pub const EINPROGRESS: ::c_int = 115;
|
||||
pub const ESTALE: ::c_int = 116;
|
||||
pub const EUCLEAN: ::c_int = 117;
|
||||
pub const ENOTNAM: ::c_int = 118;
|
||||
pub const ENAVAIL: ::c_int = 119;
|
||||
pub const EISNAM: ::c_int = 120;
|
||||
pub const EREMOTEIO: ::c_int = 121;
|
||||
pub const EDQUOT: ::c_int = 122;
|
||||
pub const ENOMEDIUM: ::c_int = 123;
|
||||
pub const EMEDIUMTYPE: ::c_int = 124;
|
||||
pub const ECANCELED: ::c_int = 125;
|
||||
pub const ENOKEY: ::c_int = 126;
|
||||
pub const EKEYEXPIRED: ::c_int = 127;
|
||||
pub const EKEYREVOKED: ::c_int = 128;
|
||||
pub const EKEYREJECTED: ::c_int = 129;
|
||||
pub const EOWNERDEAD: ::c_int = 130;
|
||||
pub const ENOTRECOVERABLE: ::c_int = 131;
|
||||
pub const EHWPOISON: ::c_int = 133;
|
||||
pub const ERFKILL: ::c_int = 132;
|
||||
|
||||
pub const SA_ONSTACK: ::c_int = 0x08000000;
|
||||
pub const SA_SIGINFO: ::c_int = 0x00000004;
|
||||
pub const SA_NOCLDWAIT: ::c_int = 0x00000002;
|
||||
|
||||
pub const SIGCHLD: ::c_int = 17;
|
||||
pub const SIGBUS: ::c_int = 7;
|
||||
pub const SIGTTIN: ::c_int = 21;
|
||||
pub const SIGTTOU: ::c_int = 22;
|
||||
pub const SIGXCPU: ::c_int = 24;
|
||||
pub const SIGXFSZ: ::c_int = 25;
|
||||
pub const SIGVTALRM: ::c_int = 26;
|
||||
pub const SIGPROF: ::c_int = 27;
|
||||
pub const SIGWINCH: ::c_int = 28;
|
||||
pub const SIGUSR1: ::c_int = 10;
|
||||
pub const SIGUSR2: ::c_int = 12;
|
||||
pub const SIGCONT: ::c_int = 18;
|
||||
pub const SIGSTOP: ::c_int = 19;
|
||||
pub const SIGTSTP: ::c_int = 20;
|
||||
pub const SIGURG: ::c_int = 23;
|
||||
pub const SIGIO: ::c_int = 29;
|
||||
pub const SIGSYS: ::c_int = 31;
|
||||
pub const SIGSTKFLT: ::c_int = 16;
|
||||
pub const SIGPOLL: ::c_int = 29;
|
||||
pub const SIGPWR: ::c_int = 30;
|
||||
pub const SIG_SETMASK: ::c_int = 2;
|
||||
pub const SIG_BLOCK: ::c_int = 0;
|
||||
pub const SIG_UNBLOCK: ::c_int = 1;
|
||||
|
||||
pub const F_GETLK: ::c_int = 5;
|
||||
pub const F_GETOWN: ::c_int = 9;
|
||||
pub const F_SETLK: ::c_int = 6;
|
||||
pub const F_SETLKW: ::c_int = 7;
|
||||
pub const F_SETOWN: ::c_int = 8;
|
||||
|
||||
pub const VEOF: usize = 4;
|
||||
|
||||
pub const POLLWRNORM: ::c_short = 0x100;
|
||||
pub const POLLWRBAND: ::c_short = 0x200;
|
||||
|
||||
pub const SOCK_STREAM: ::c_int = 1;
|
||||
pub const SOCK_DGRAM: ::c_int = 2;
|
||||
|
||||
pub const MAP_ANON: ::c_int = 0x0020;
|
||||
pub const MAP_GROWSDOWN: ::c_int = 0x0100;
|
||||
pub const MAP_DENYWRITE: ::c_int = 0x0800;
|
||||
pub const MAP_EXECUTABLE: ::c_int = 0x01000;
|
||||
pub const MAP_LOCKED: ::c_int = 0x02000;
|
||||
pub const MAP_NORESERVE: ::c_int = 0x04000;
|
||||
pub const MAP_POPULATE: ::c_int = 0x08000;
|
||||
pub const MAP_NONBLOCK: ::c_int = 0x010000;
|
||||
pub const MAP_STACK: ::c_int = 0x020000;
|
||||
pub const MAP_HUGETLB: ::c_int = 0x040000;
|
||||
pub const MAP_SYNC: ::c_int = 0x080000;
|
||||
|
||||
pub const MCL_CURRENT: ::c_int = 0x0001;
|
||||
pub const MCL_FUTURE: ::c_int = 0x0002;
|
||||
pub const MCL_ONFAULT: ::c_int = 0x0004;
|
||||
pub const CBAUD: ::tcflag_t = 0o0010017;
|
||||
pub const TAB1: ::c_int = 0x00000800;
|
||||
pub const TAB2: ::c_int = 0x00001000;
|
||||
pub const TAB3: ::c_int = 0x00001800;
|
||||
pub const CR1: ::c_int = 0x00000200;
|
||||
pub const CR2: ::c_int = 0x00000400;
|
||||
pub const CR3: ::c_int = 0x00000600;
|
||||
pub const FF1: ::c_int = 0x00008000;
|
||||
pub const BS1: ::c_int = 0x00002000;
|
||||
pub const VT1: ::c_int = 0x00004000;
|
||||
pub const VWERASE: usize = 14;
|
||||
pub const VREPRINT: usize = 12;
|
||||
pub const VSUSP: usize = 10;
|
||||
pub const VSTART: usize = 8;
|
||||
pub const VSTOP: usize = 9;
|
||||
pub const VDISCARD: usize = 13;
|
||||
pub const VTIME: usize = 5;
|
||||
pub const IXON: ::tcflag_t = 0x00000400;
|
||||
pub const IXOFF: ::tcflag_t = 0x00001000;
|
||||
pub const ONLCR: ::tcflag_t = 0x4;
|
||||
pub const CSIZE: ::tcflag_t = 0x00000030;
|
||||
pub const CS6: ::tcflag_t = 0x00000010;
|
||||
pub const CS7: ::tcflag_t = 0x00000020;
|
||||
pub const CS8: ::tcflag_t = 0x00000030;
|
||||
pub const CSTOPB: ::tcflag_t = 0x00000040;
|
||||
pub const CREAD: ::tcflag_t = 0x00000080;
|
||||
pub const PARENB: ::tcflag_t = 0x00000100;
|
||||
pub const PARODD: ::tcflag_t = 0x00000200;
|
||||
pub const HUPCL: ::tcflag_t = 0x00000400;
|
||||
pub const CLOCAL: ::tcflag_t = 0x00000800;
|
||||
pub const ECHOKE: ::tcflag_t = 0x00000800;
|
||||
pub const ECHOE: ::tcflag_t = 0x00000010;
|
||||
pub const ECHOK: ::tcflag_t = 0x00000020;
|
||||
pub const ECHONL: ::tcflag_t = 0x00000040;
|
||||
pub const ECHOPRT: ::tcflag_t = 0x00000400;
|
||||
pub const ECHOCTL: ::tcflag_t = 0x00000200;
|
||||
pub const ISIG: ::tcflag_t = 0x00000001;
|
||||
pub const ICANON: ::tcflag_t = 0x00000002;
|
||||
pub const PENDIN: ::tcflag_t = 0x00004000;
|
||||
pub const NOFLSH: ::tcflag_t = 0x00000080;
|
||||
pub const CIBAUD: ::tcflag_t = 0o02003600000;
|
||||
pub const CBAUDEX: ::tcflag_t = 0o010000;
|
||||
pub const VSWTC: usize = 7;
|
||||
pub const OLCUC: ::tcflag_t = 0o000002;
|
||||
pub const NLDLY: ::tcflag_t = 0o000400;
|
||||
pub const CRDLY: ::tcflag_t = 0o003000;
|
||||
pub const TABDLY: ::tcflag_t = 0o014000;
|
||||
pub const BSDLY: ::tcflag_t = 0o020000;
|
||||
pub const FFDLY: ::tcflag_t = 0o100000;
|
||||
pub const VTDLY: ::tcflag_t = 0o040000;
|
||||
pub const XTABS: ::tcflag_t = 0o014000;
|
||||
pub const B57600: ::speed_t = 0o010001;
|
||||
pub const B115200: ::speed_t = 0o010002;
|
||||
pub const B230400: ::speed_t = 0o010003;
|
||||
pub const B460800: ::speed_t = 0o010004;
|
||||
pub const B500000: ::speed_t = 0o010005;
|
||||
pub const B576000: ::speed_t = 0o010006;
|
||||
pub const B921600: ::speed_t = 0o010007;
|
||||
pub const B1000000: ::speed_t = 0o010010;
|
||||
pub const B1152000: ::speed_t = 0o010011;
|
||||
pub const B1500000: ::speed_t = 0o010012;
|
||||
pub const B2000000: ::speed_t = 0o010013;
|
||||
pub const B2500000: ::speed_t = 0o010014;
|
||||
pub const B3000000: ::speed_t = 0o010015;
|
||||
pub const B3500000: ::speed_t = 0o010016;
|
||||
pub const B4000000: ::speed_t = 0o010017;
|
||||
|
||||
pub const EDEADLK: ::c_int = 35;
|
||||
pub const EDEADLOCK: ::c_int = EDEADLK;
|
||||
pub const EXTPROC: ::tcflag_t = 0x00010000;
|
||||
pub const VEOL: usize = 11;
|
||||
pub const VEOL2: usize = 16;
|
||||
pub const VMIN: usize = 6;
|
||||
pub const IEXTEN: ::tcflag_t = 0x00008000;
|
||||
pub const TOSTOP: ::tcflag_t = 0x00000100;
|
||||
pub const FLUSHO: ::tcflag_t = 0x00001000;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(libc_align)] {
|
||||
mod align;
|
||||
pub use self::align::*;
|
||||
}
|
||||
}
|
|
@ -157,6 +157,9 @@ cfg_if! {
|
|||
} else if #[cfg(any(target_arch = "riscv64"))] {
|
||||
mod riscv64;
|
||||
pub use self::riscv64::*;
|
||||
} else if #[cfg(any(target_arch = "loongarch64"))] {
|
||||
mod loongarch64;
|
||||
pub use self::loongarch64::*;
|
||||
} else {
|
||||
// Unknown target_arch
|
||||
}
|
||||
|
|
|
@ -42,3 +42,20 @@ s_no_extra_traits! {
|
|||
pub __glibc_reserved: [::c_uint; 3],
|
||||
}
|
||||
}
|
||||
|
||||
s! {
|
||||
#[repr(align(8))]
|
||||
pub struct clone_args {
|
||||
pub flags: ::c_ulonglong,
|
||||
pub pidfd: ::c_ulonglong,
|
||||
pub child_tid: ::c_ulonglong,
|
||||
pub parent_tid: ::c_ulonglong,
|
||||
pub exit_signal: ::c_ulonglong,
|
||||
pub stack: ::c_ulonglong,
|
||||
pub stack_size: ::c_ulonglong,
|
||||
pub tls: ::c_ulonglong,
|
||||
pub set_tid: ::c_ulonglong,
|
||||
pub set_tid_size: ::c_ulonglong,
|
||||
pub cgroup: ::c_ulonglong,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -671,6 +671,12 @@ pub const PTRACE_PEEKSIGINFO: ::c_int = 0x4209;
|
|||
pub const PTRACE_GETSIGMASK: ::c_uint = 0x420a;
|
||||
pub const PTRACE_SETSIGMASK: ::c_uint = 0x420b;
|
||||
|
||||
pub const RWF_HIPRI: ::c_int = 0x00000001;
|
||||
pub const RWF_DSYNC: ::c_int = 0x00000002;
|
||||
pub const RWF_SYNC: ::c_int = 0x00000004;
|
||||
pub const RWF_NOWAIT: ::c_int = 0x00000008;
|
||||
pub const RWF_APPEND: ::c_int = 0x00000010;
|
||||
|
||||
pub const AF_IB: ::c_int = 27;
|
||||
pub const AF_MPLS: ::c_int = 28;
|
||||
pub const AF_NFC: ::c_int = 39;
|
||||
|
@ -862,6 +868,20 @@ extern "C" {
|
|||
dirfd: ::c_int,
|
||||
path: *const ::c_char,
|
||||
) -> ::c_int;
|
||||
pub fn preadv2(
|
||||
fd: ::c_int,
|
||||
iov: *const ::iovec,
|
||||
iovcnt: ::c_int,
|
||||
offset: ::off_t,
|
||||
flags: ::c_int,
|
||||
) -> ::ssize_t;
|
||||
pub fn pwritev2(
|
||||
fd: ::c_int,
|
||||
iov: *const ::iovec,
|
||||
iovcnt: ::c_int,
|
||||
offset: ::off_t,
|
||||
flags: ::c_int,
|
||||
) -> ::ssize_t;
|
||||
pub fn getauxval(type_: ::c_ulong) -> ::c_ulong;
|
||||
|
||||
// Added in `musl` 1.1.20
|
||||
|
@ -883,21 +903,6 @@ extern "C" {
|
|||
|
||||
pub fn asctime_r(tm: *const ::tm, buf: *mut ::c_char) -> *mut ::c_char;
|
||||
|
||||
pub fn strftime(
|
||||
s: *mut ::c_char,
|
||||
max: ::size_t,
|
||||
format: *const ::c_char,
|
||||
tm: *const ::tm,
|
||||
) -> ::size_t;
|
||||
pub fn strftime_l(
|
||||
s: *mut ::c_char,
|
||||
max: ::size_t,
|
||||
format: *const ::c_char,
|
||||
tm: *const ::tm,
|
||||
locale: ::locale_t,
|
||||
) -> ::size_t;
|
||||
pub fn strptime(s: *const ::c_char, format: *const ::c_char, tm: *mut ::tm) -> *mut ::c_char;
|
||||
|
||||
pub fn dirname(path: *mut ::c_char) -> *mut ::c_char;
|
||||
pub fn basename(path: *mut ::c_char) -> *mut ::c_char;
|
||||
}
|
||||
|
@ -912,7 +917,8 @@ cfg_if! {
|
|||
target_arch = "mips64",
|
||||
target_arch = "powerpc64",
|
||||
target_arch = "s390x",
|
||||
target_arch = "riscv64"))] {
|
||||
target_arch = "riscv64",
|
||||
target_arch = "loongarch64"))] {
|
||||
mod b64;
|
||||
pub use self::b64::*;
|
||||
} else if #[cfg(any(target_arch = "x86",
|
||||
|
|
|
@ -107,6 +107,64 @@ impl siginfo_t {
|
|||
}
|
||||
}
|
||||
|
||||
// Internal, for casts to access union fields
|
||||
#[repr(C)]
|
||||
struct sifields_sigchld {
|
||||
si_pid: ::pid_t,
|
||||
si_uid: ::uid_t,
|
||||
si_status: ::c_int,
|
||||
si_utime: ::c_long,
|
||||
si_stime: ::c_long,
|
||||
}
|
||||
impl ::Copy for sifields_sigchld {}
|
||||
impl ::Clone for sifields_sigchld {
|
||||
fn clone(&self) -> sifields_sigchld {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
// Internal, for casts to access union fields
|
||||
#[repr(C)]
|
||||
union sifields {
|
||||
_align_pointer: *mut ::c_void,
|
||||
sigchld: sifields_sigchld,
|
||||
}
|
||||
|
||||
// Internal, for casts to access union fields. Note that some variants
|
||||
// of sifields start with a pointer, which makes the alignment of
|
||||
// sifields vary on 32-bit and 64-bit architectures.
|
||||
#[repr(C)]
|
||||
struct siginfo_f {
|
||||
_siginfo_base: [::c_int; 3],
|
||||
sifields: sifields,
|
||||
}
|
||||
|
||||
impl siginfo_t {
|
||||
unsafe fn sifields(&self) -> &sifields {
|
||||
&(*(self as *const siginfo_t as *const siginfo_f)).sifields
|
||||
}
|
||||
|
||||
pub unsafe fn si_pid(&self) -> ::pid_t {
|
||||
self.sifields().sigchld.si_pid
|
||||
}
|
||||
|
||||
pub unsafe fn si_uid(&self) -> ::uid_t {
|
||||
self.sifields().sigchld.si_uid
|
||||
}
|
||||
|
||||
pub unsafe fn si_status(&self) -> ::c_int {
|
||||
self.sifields().sigchld.si_status
|
||||
}
|
||||
|
||||
pub unsafe fn si_utime(&self) -> ::c_long {
|
||||
self.sifields().sigchld.si_utime
|
||||
}
|
||||
|
||||
pub unsafe fn si_stime(&self) -> ::c_long {
|
||||
self.sifields().sigchld.si_stime
|
||||
}
|
||||
}
|
||||
|
||||
pub const MCL_CURRENT: ::c_int = 0x0001;
|
||||
pub const MCL_FUTURE: ::c_int = 0x0002;
|
||||
pub const MCL_ONFAULT: ::c_int = 0x0004;
|
||||
|
@ -245,7 +303,7 @@ pub const BUFSIZ: ::c_int = 4096;
|
|||
pub const EDEADLOCK: ::c_int = EDEADLK;
|
||||
pub const EXTA: ::c_uint = B19200;
|
||||
pub const EXTB: ::c_uint = B38400;
|
||||
pub const EXTPROC: ::tcflag_t = 0200000;
|
||||
pub const EXTPROC: ::tcflag_t = 0o200000;
|
||||
pub const FOPEN_MAX: ::c_int = 16;
|
||||
pub const F_GETOWN: ::c_int = 9;
|
||||
pub const F_OFD_GETLK: ::c_int = 36;
|
||||
|
@ -272,7 +330,7 @@ pub const MAP_HUGE_1GB: ::c_int = 30 << MAP_HUGE_SHIFT;
|
|||
pub const MAP_HUGE_2GB: ::c_int = 31 << MAP_HUGE_SHIFT;
|
||||
pub const MAP_HUGE_16GB: ::c_int = 34 << MAP_HUGE_SHIFT;
|
||||
pub const MINSIGSTKSZ: ::c_int = 2048;
|
||||
pub const MSG_COPY: ::c_int = 040000;
|
||||
pub const MSG_COPY: ::c_int = 0o40000;
|
||||
pub const NI_MAXHOST: ::socklen_t = 1025;
|
||||
pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY;
|
||||
pub const PACKET_MR_UNICAST: ::c_int = 3;
|
||||
|
@ -285,7 +343,7 @@ pub const PTRACE_PEEKSIGINFO: ::c_int = 0x4209;
|
|||
pub const PTRACE_SETSIGMASK: ::c_uint = 0x420b;
|
||||
pub const RTLD_NOLOAD: ::c_int = 0x00004;
|
||||
pub const RUSAGE_THREAD: ::c_int = 1;
|
||||
pub const SHM_EXEC: ::c_int = 0100000;
|
||||
pub const SHM_EXEC: ::c_int = 0o100000;
|
||||
pub const SIGPOLL: ::c_int = SIGIO;
|
||||
pub const SOCK_DCCP: ::c_int = 6;
|
||||
pub const SOCK_PACKET: ::c_int = 10;
|
||||
|
@ -374,6 +432,7 @@ extern "C" {
|
|||
pub fn setrlimit(resource: ::__rlimit_resource_t, rlim: *const ::rlimit) -> ::c_int;
|
||||
pub fn getpriority(which: ::__priority_which_t, who: ::id_t) -> ::c_int;
|
||||
pub fn setpriority(which: ::__priority_which_t, who: ::id_t, prio: ::c_int) -> ::c_int;
|
||||
pub fn getauxval(type_: ::c_ulong) -> ::c_ulong;
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
|
|
|
@ -311,15 +311,15 @@ pub const EHOSTUNREACH: ::c_int = 113; // No route to host
|
|||
pub const EDQUOT: ::c_int = 122; // Quota exceeded
|
||||
pub const EOPNOTSUPP: ::c_int = 0x5f;
|
||||
pub const ENODATA: ::c_int = 0x3d;
|
||||
pub const O_APPEND: ::c_int = 02000;
|
||||
pub const O_ACCMODE: ::c_int = 0003;
|
||||
pub const O_APPEND: ::c_int = 0o2000;
|
||||
pub const O_ACCMODE: ::c_int = 0o003;
|
||||
pub const O_CLOEXEC: ::c_int = 0x80000;
|
||||
pub const O_CREAT: ::c_int = 0100;
|
||||
pub const O_DIRECTORY: ::c_int = 0200000;
|
||||
pub const O_EXCL: ::c_int = 0200;
|
||||
pub const O_DIRECTORY: ::c_int = 0o200000;
|
||||
pub const O_EXCL: ::c_int = 0o200;
|
||||
pub const O_NOFOLLOW: ::c_int = 0x20000;
|
||||
pub const O_NONBLOCK: ::c_int = 04000;
|
||||
pub const O_TRUNC: ::c_int = 01000;
|
||||
pub const O_NONBLOCK: ::c_int = 0o4000;
|
||||
pub const O_TRUNC: ::c_int = 0o1000;
|
||||
pub const NCCS: usize = 32;
|
||||
pub const SIG_SETMASK: ::c_int = 2; // Set the set of blocked signals
|
||||
pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
|
||||
|
@ -332,7 +332,7 @@ pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56;
|
|||
pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8;
|
||||
pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32;
|
||||
pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4;
|
||||
pub const PIDFD_NONBLOCK: ::c_int = 04000;
|
||||
pub const PIDFD_NONBLOCK: ::c_int = 0o4000;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "l4re")] {
|
||||
|
|
|
@ -1775,6 +1775,21 @@ extern "C" {
|
|||
pub fn uname(buf: *mut ::utsname) -> ::c_int;
|
||||
|
||||
pub fn strchrnul(s: *const ::c_char, c: ::c_int) -> *mut ::c_char;
|
||||
|
||||
pub fn strftime(
|
||||
s: *mut ::c_char,
|
||||
max: ::size_t,
|
||||
format: *const ::c_char,
|
||||
tm: *const ::tm,
|
||||
) -> ::size_t;
|
||||
pub fn strftime_l(
|
||||
s: *mut ::c_char,
|
||||
max: ::size_t,
|
||||
format: *const ::c_char,
|
||||
tm: *const ::tm,
|
||||
locale: ::locale_t,
|
||||
) -> ::size_t;
|
||||
pub fn strptime(s: *const ::c_char, format: *const ::c_char, tm: *mut ::tm) -> *mut ::c_char;
|
||||
}
|
||||
|
||||
// LFS64 extensions
|
||||
|
|
|
@ -369,6 +369,7 @@ cfg_if! {
|
|||
target_os = "ios",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos",
|
||||
target_os = "visionos",
|
||||
target_os = "android",
|
||||
target_os = "openbsd",
|
||||
target_os = "nto",
|
||||
|
@ -395,7 +396,7 @@ cfg_if! {
|
|||
#[cfg_attr(feature = "rustc-dep-of-std",
|
||||
link(name = "c", cfg(not(target_feature = "crt-static"))))]
|
||||
extern {}
|
||||
} else if #[cfg(target_env = "aix")] {
|
||||
} else if #[cfg(target_os = "aix")] {
|
||||
#[link(name = "c")]
|
||||
#[link(name = "m")]
|
||||
#[link(name = "bsd")]
|
||||
|
@ -594,7 +595,10 @@ extern "C" {
|
|||
target_vendor = "nintendo"
|
||||
)))]
|
||||
#[cfg_attr(target_os = "netbsd", link_name = "__socket30")]
|
||||
#[cfg_attr(target_os = "illumos", link_name = "__xnet_socket")]
|
||||
#[cfg_attr(
|
||||
any(target_os = "illumos", target_os = "solaris"),
|
||||
link_name = "__xnet_socket"
|
||||
)]
|
||||
#[cfg_attr(target_os = "espidf", link_name = "lwip_socket")]
|
||||
pub fn socket(domain: ::c_int, ty: ::c_int, protocol: ::c_int) -> ::c_int;
|
||||
#[cfg(not(all(
|
||||
|
@ -606,7 +610,10 @@ extern "C" {
|
|||
all(target_os = "macos", target_arch = "x86"),
|
||||
link_name = "connect$UNIX2003"
|
||||
)]
|
||||
#[cfg_attr(target_os = "illumos", link_name = "__xnet_connect")]
|
||||
#[cfg_attr(
|
||||
any(target_os = "illumos", target_os = "solaris"),
|
||||
link_name = "__xnet_connect"
|
||||
)]
|
||||
#[cfg_attr(target_os = "espidf", link_name = "lwip_connect")]
|
||||
pub fn connect(socket: ::c_int, address: *const sockaddr, len: socklen_t) -> ::c_int;
|
||||
#[cfg_attr(
|
||||
|
@ -668,7 +675,10 @@ extern "C" {
|
|||
all(target_os = "macos", target_arch = "x86"),
|
||||
link_name = "socketpair$UNIX2003"
|
||||
)]
|
||||
#[cfg_attr(target_os = "illumos", link_name = "__xnet_socketpair")]
|
||||
#[cfg_attr(
|
||||
any(target_os = "illumos", target_os = "solaris"),
|
||||
link_name = "__xnet_socketpair"
|
||||
)]
|
||||
pub fn socketpair(
|
||||
domain: ::c_int,
|
||||
type_: ::c_int,
|
||||
|
@ -684,7 +694,10 @@ extern "C" {
|
|||
all(target_os = "macos", target_arch = "x86"),
|
||||
link_name = "sendto$UNIX2003"
|
||||
)]
|
||||
#[cfg_attr(target_os = "illumos", link_name = "__xnet_sendto")]
|
||||
#[cfg_attr(
|
||||
any(target_os = "illumos", target_os = "solaris"),
|
||||
link_name = "__xnet_sendto"
|
||||
)]
|
||||
#[cfg_attr(target_os = "espidf", link_name = "lwip_sendto")]
|
||||
pub fn sendto(
|
||||
socket: ::c_int,
|
||||
|
@ -1042,7 +1055,8 @@ extern "C" {
|
|||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos"
|
||||
target_os = "watchos",
|
||||
target_os = "visionos"
|
||||
),
|
||||
link_name = "realpath$DARWIN_EXTSN"
|
||||
)]
|
||||
|
@ -1054,6 +1068,7 @@ extern "C" {
|
|||
pub fn times(buf: *mut ::tms) -> ::clock_t;
|
||||
|
||||
pub fn pthread_self() -> ::pthread_t;
|
||||
pub fn pthread_equal(t1: ::pthread_t, t2: ::pthread_t) -> ::c_int;
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86"),
|
||||
link_name = "pthread_join$UNIX2003"
|
||||
|
@ -1161,7 +1176,10 @@ extern "C" {
|
|||
pub fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> ::c_int;
|
||||
pub fn pthread_rwlockattr_destroy(attr: *mut pthread_rwlockattr_t) -> ::c_int;
|
||||
|
||||
#[cfg_attr(target_os = "illumos", link_name = "__xnet_getsockopt")]
|
||||
#[cfg_attr(
|
||||
any(target_os = "illumos", target_os = "solaris"),
|
||||
link_name = "__xnet_getsockopt"
|
||||
)]
|
||||
#[cfg_attr(target_os = "espidf", link_name = "lwip_getsockopt")]
|
||||
pub fn getsockopt(
|
||||
sockfd: ::c_int,
|
||||
|
@ -1184,7 +1202,10 @@ extern "C" {
|
|||
target_arch = "powerpc",
|
||||
target_vendor = "nintendo"
|
||||
)))]
|
||||
#[cfg_attr(target_os = "illumos", link_name = "__xnet_getaddrinfo")]
|
||||
#[cfg_attr(
|
||||
any(target_os = "illumos", target_os = "solaris"),
|
||||
link_name = "__xnet_getaddrinfo"
|
||||
)]
|
||||
#[cfg_attr(target_os = "espidf", link_name = "lwip_getaddrinfo")]
|
||||
pub fn getaddrinfo(
|
||||
node: *const c_char,
|
||||
|
@ -1218,7 +1239,8 @@ extern "C" {
|
|||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos"
|
||||
target_os = "watchos",
|
||||
target_os = "visionos"
|
||||
),
|
||||
link_name = "res_9_init"
|
||||
)]
|
||||
|
@ -1406,6 +1428,15 @@ cfg_if! {
|
|||
target_os = "nto")))] {
|
||||
extern "C" {
|
||||
pub fn adjtime(delta: *const timeval, olddelta: *mut timeval) -> ::c_int;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(not(any(target_os = "emscripten",
|
||||
target_os = "android",
|
||||
target_os = "nto")))] {
|
||||
extern "C" {
|
||||
pub fn stpncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char;
|
||||
}
|
||||
}
|
||||
|
@ -1555,6 +1586,7 @@ cfg_if! {
|
|||
target_os = "ios",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos",
|
||||
target_os = "visionos",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "openbsd",
|
||||
|
|
|
@ -89,6 +89,16 @@ pub const MSG_EOR: ::c_int = 0x08;
|
|||
|
||||
pub const PTHREAD_STACK_MIN: ::size_t = 768;
|
||||
|
||||
pub const SIGABRT: ::size_t = 1;
|
||||
pub const SIGFPE: ::size_t = 1;
|
||||
pub const SIGILL: ::size_t = 1;
|
||||
pub const SIGINT: ::size_t = 1;
|
||||
pub const SIGSEGV: ::size_t = 1;
|
||||
pub const SIGTERM: ::size_t = 1;
|
||||
pub const SIGHUP: ::size_t = 1;
|
||||
pub const SIGQUIT: ::size_t = 1;
|
||||
pub const NSIG: ::size_t = 2;
|
||||
|
||||
extern "C" {
|
||||
pub fn pthread_create(
|
||||
native: *mut ::pthread_t,
|
||||
|
|
|
@ -2672,6 +2672,7 @@ pub const VRIGHT: usize = 29;
|
|||
pub const VUP: usize = 30;
|
||||
pub const XCASE: tcflag_t = 0x00000004;
|
||||
|
||||
pub const PTHREAD_BARRIER_SERIAL_THREAD: ::c_int = -1;
|
||||
pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0x00;
|
||||
pub const PTHREAD_CREATE_DETACHED: ::c_int = 0x01;
|
||||
|
||||
|
@ -2864,9 +2865,9 @@ safe_f! {
|
|||
|
||||
// Network related functions are provided by libsocket and regex
|
||||
// functions are provided by libregex.
|
||||
// In QNX <=7.0, libregex functions were included in libc itself.
|
||||
#[link(name = "socket")]
|
||||
#[link(name = "regex")]
|
||||
|
||||
#[cfg_attr(not(target_env = "nto70"), link(name = "regex"))]
|
||||
extern "C" {
|
||||
pub fn sem_destroy(sem: *mut sem_t) -> ::c_int;
|
||||
pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int;
|
||||
|
@ -3339,7 +3340,10 @@ extern "C" {
|
|||
pub fn dl_iterate_phdr(
|
||||
callback: ::Option<
|
||||
unsafe extern "C" fn(
|
||||
info: *const dl_phdr_info,
|
||||
// The original .h file declares this as *const, but for consistency with other platforms,
|
||||
// changing this to *mut to make it easier to use.
|
||||
// Maybe in v0.3 all platforms should use this as a *const.
|
||||
info: *mut dl_phdr_info,
|
||||
size: ::size_t,
|
||||
data: *mut ::c_void,
|
||||
) -> ::c_int,
|
||||
|
|
|
@ -677,22 +677,22 @@ pub const EPOLL_CLOEXEC: ::c_int = 0x0100_0000;
|
|||
pub const EPOLL_CTL_ADD: ::c_int = 1;
|
||||
pub const EPOLL_CTL_DEL: ::c_int = 2;
|
||||
pub const EPOLL_CTL_MOD: ::c_int = 3;
|
||||
pub const EPOLLIN: ::c_int = 1;
|
||||
pub const EPOLLPRI: ::c_int = 0;
|
||||
pub const EPOLLOUT: ::c_int = 2;
|
||||
pub const EPOLLRDNORM: ::c_int = 0;
|
||||
pub const EPOLLNVAL: ::c_int = 0;
|
||||
pub const EPOLLRDBAND: ::c_int = 0;
|
||||
pub const EPOLLWRNORM: ::c_int = 0;
|
||||
pub const EPOLLWRBAND: ::c_int = 0;
|
||||
pub const EPOLLMSG: ::c_int = 0;
|
||||
pub const EPOLLERR: ::c_int = 0;
|
||||
pub const EPOLLHUP: ::c_int = 0;
|
||||
pub const EPOLLRDHUP: ::c_int = 0;
|
||||
pub const EPOLLEXCLUSIVE: ::c_int = 0;
|
||||
pub const EPOLLWAKEUP: ::c_int = 0;
|
||||
pub const EPOLLONESHOT: ::c_int = 0;
|
||||
pub const EPOLLET: ::c_int = 0;
|
||||
pub const EPOLLIN: ::c_int = 0x001;
|
||||
pub const EPOLLPRI: ::c_int = 0x002;
|
||||
pub const EPOLLOUT: ::c_int = 0x004;
|
||||
pub const EPOLLERR: ::c_int = 0x008;
|
||||
pub const EPOLLHUP: ::c_int = 0x010;
|
||||
pub const EPOLLNVAL: ::c_int = 0x020;
|
||||
pub const EPOLLRDNORM: ::c_int = 0x040;
|
||||
pub const EPOLLRDBAND: ::c_int = 0x080;
|
||||
pub const EPOLLWRNORM: ::c_int = 0x100;
|
||||
pub const EPOLLWRBAND: ::c_int = 0x200;
|
||||
pub const EPOLLMSG: ::c_int = 0x400;
|
||||
pub const EPOLLRDHUP: ::c_int = 0x2000;
|
||||
pub const EPOLLEXCLUSIVE: ::c_int = 1 << 28;
|
||||
pub const EPOLLWAKEUP: ::c_int = 1 << 29;
|
||||
pub const EPOLLONESHOT: ::c_int = 1 << 30;
|
||||
pub const EPOLLET: ::c_int = 1 << 31;
|
||||
|
||||
// sys/stat.h
|
||||
pub const S_IFMT: ::c_int = 0o0_170_000;
|
||||
|
|
|
@ -81,6 +81,21 @@ extern "C" {
|
|||
) -> ::c_int;
|
||||
pub fn pset_getloadavg(pset: ::psetid_t, load: *mut ::c_double, num: ::c_int) -> ::c_int;
|
||||
|
||||
pub fn pthread_attr_get_np(thread: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int;
|
||||
pub fn pthread_attr_getstackaddr(
|
||||
attr: *const ::pthread_attr_t,
|
||||
stackaddr: *mut *mut ::c_void,
|
||||
) -> ::c_int;
|
||||
pub fn pthread_attr_setstack(
|
||||
attr: *mut ::pthread_attr_t,
|
||||
stackaddr: *mut ::c_void,
|
||||
stacksize: ::size_t,
|
||||
) -> ::c_int;
|
||||
pub fn pthread_attr_setstackaddr(
|
||||
attr: *mut ::pthread_attr_t,
|
||||
stackaddr: *mut ::c_void,
|
||||
) -> ::c_int;
|
||||
|
||||
pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t;
|
||||
pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t)
|
||||
-> ::ssize_t;
|
||||
|
|
|
@ -120,6 +120,17 @@ s! {
|
|||
pub __sin6_src_id: u32
|
||||
}
|
||||
|
||||
pub struct in_pktinfo {
|
||||
pub ipi_ifindex: ::c_uint,
|
||||
pub ipi_spec_dst: ::in_addr,
|
||||
pub ipi_addr: ::in_addr,
|
||||
}
|
||||
|
||||
pub struct in6_pktinfo {
|
||||
pub ipi6_addr: ::in6_addr,
|
||||
pub ipi6_ifindex: ::c_uint,
|
||||
}
|
||||
|
||||
pub struct passwd {
|
||||
pub pw_name: *mut ::c_char,
|
||||
pub pw_passwd: *mut ::c_char,
|
||||
|
@ -135,7 +146,7 @@ s! {
|
|||
pub struct ifaddrs {
|
||||
pub ifa_next: *mut ifaddrs,
|
||||
pub ifa_name: *mut ::c_char,
|
||||
pub ifa_flags: ::c_ulong,
|
||||
pub ifa_flags: u64,
|
||||
pub ifa_addr: *mut ::sockaddr,
|
||||
pub ifa_netmask: *mut ::sockaddr,
|
||||
pub ifa_dstaddr: *mut ::sockaddr,
|
||||
|
@ -1238,14 +1249,20 @@ pub const CLD_STOPPED: ::c_int = 5;
|
|||
pub const CLD_CONTINUED: ::c_int = 6;
|
||||
|
||||
pub const IP_RECVDSTADDR: ::c_int = 0x7;
|
||||
pub const IP_PKTINFO: ::c_int = 0x1a;
|
||||
pub const IP_DONTFRAG: ::c_int = 0x1b;
|
||||
pub const IP_SEC_OPT: ::c_int = 0x22;
|
||||
|
||||
pub const IPV6_UNICAST_HOPS: ::c_int = 0x5;
|
||||
pub const IPV6_MULTICAST_IF: ::c_int = 0x6;
|
||||
pub const IPV6_MULTICAST_HOPS: ::c_int = 0x7;
|
||||
pub const IPV6_MULTICAST_LOOP: ::c_int = 0x8;
|
||||
pub const IPV6_PKTINFO: ::c_int = 0xb;
|
||||
pub const IPV6_RECVPKTINFO: ::c_int = 0x12;
|
||||
pub const IPV6_RECVTCLASS: ::c_int = 0x19;
|
||||
pub const IPV6_DONTFRAG: ::c_int = 0x21;
|
||||
pub const IPV6_SEC_OPT: ::c_int = 0x22;
|
||||
pub const IPV6_TCLASS: ::c_int = 0x26;
|
||||
pub const IPV6_V6ONLY: ::c_int = 0x27;
|
||||
|
||||
cfg_if! {
|
||||
|
@ -1279,6 +1296,7 @@ pub const FOPEN_MAX: ::c_uint = 20;
|
|||
pub const FILENAME_MAX: ::c_uint = 1024;
|
||||
pub const L_tmpnam: ::c_uint = 25;
|
||||
pub const TMP_MAX: ::c_uint = 17576;
|
||||
pub const PIPE_BUF: ::c_int = 5120;
|
||||
|
||||
pub const GRND_NONBLOCK: ::c_uint = 0x0001;
|
||||
pub const GRND_RANDOM: ::c_uint = 0x0002;
|
||||
|
@ -1774,8 +1792,9 @@ pub const SOCK_SEQPACKET: ::c_int = 6;
|
|||
pub const IP_MULTICAST_IF: ::c_int = 16;
|
||||
pub const IP_MULTICAST_TTL: ::c_int = 17;
|
||||
pub const IP_MULTICAST_LOOP: ::c_int = 18;
|
||||
pub const IP_TTL: ::c_int = 4;
|
||||
pub const IP_HDRINCL: ::c_int = 2;
|
||||
pub const IP_TOS: ::c_int = 3;
|
||||
pub const IP_TTL: ::c_int = 4;
|
||||
pub const IP_ADD_MEMBERSHIP: ::c_int = 19;
|
||||
pub const IP_DROP_MEMBERSHIP: ::c_int = 20;
|
||||
pub const IPV6_JOIN_GROUP: ::c_int = 9;
|
||||
|
@ -1829,6 +1848,7 @@ pub const SO_TYPE: ::c_int = 0x1008;
|
|||
pub const SO_PROTOTYPE: ::c_int = 0x1009;
|
||||
pub const SO_DOMAIN: ::c_int = 0x100c;
|
||||
pub const SO_TIMESTAMP: ::c_int = 0x1013;
|
||||
pub const SO_EXCLBIND: ::c_int = 0x1015;
|
||||
|
||||
pub const SCM_RIGHTS: ::c_int = 0x1010;
|
||||
pub const SCM_UCRED: ::c_int = 0x1012;
|
||||
|
@ -2867,15 +2887,15 @@ extern "C" {
|
|||
) -> ::c_int;
|
||||
pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char;
|
||||
|
||||
#[cfg_attr(target_os = "illumos", link_name = "__xnet_bind")]
|
||||
#[link_name = "__xnet_bind"]
|
||||
pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int;
|
||||
|
||||
pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t;
|
||||
pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t;
|
||||
|
||||
#[cfg_attr(target_os = "illumos", link_name = "__xnet_sendmsg")]
|
||||
#[link_name = "__xnet_sendmsg"]
|
||||
pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t;
|
||||
#[cfg_attr(target_os = "illumos", link_name = "__xnet_recvmsg")]
|
||||
#[link_name = "__xnet_recvmsg"]
|
||||
pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t;
|
||||
pub fn accept4(
|
||||
fd: ::c_int,
|
||||
|
|
|
@ -91,6 +91,7 @@ pub type SEM_ID_KERNEL = ::OBJ_HANDLE;
|
|||
pub type RTP_ID = ::OBJ_HANDLE;
|
||||
pub type SD_ID = ::OBJ_HANDLE;
|
||||
pub type CONDVAR_ID = ::OBJ_HANDLE;
|
||||
pub type STATUS = ::OBJ_HANDLE;
|
||||
|
||||
// From vxTypes.h
|
||||
pub type _Vx_usr_arg_t = isize;
|
||||
|
@ -613,6 +614,7 @@ pub const PTHREAD_STACK_MIN: usize = 4096;
|
|||
pub const _PTHREAD_SHARED_SEM_NAME_MAX: usize = 30;
|
||||
|
||||
// ERRNO STUFF
|
||||
pub const ERROR: ::c_int = -1;
|
||||
pub const OK: ::c_int = 0;
|
||||
pub const EPERM: ::c_int = 1; /* Not owner */
|
||||
pub const ENOENT: ::c_int = 2; /* No such file or directory */
|
||||
|
@ -720,6 +722,33 @@ pub const S_nfsLib_NFSERR_SERVERFAULT: ::c_int = EIO;
|
|||
pub const S_nfsLib_NFSERR_BADTYPE: ::c_int = M_nfsStat | nfsstat::NFSERR_BADTYPE as ::c_int;
|
||||
pub const S_nfsLib_NFSERR_JUKEBOX: ::c_int = M_nfsStat | nfsstat::NFSERR_JUKEBOX as ::c_int;
|
||||
|
||||
// internal offset values for below constants
|
||||
const taskErrorBase: ::c_int = 0x00030000;
|
||||
const semErrorBase: ::c_int = 0x00160000;
|
||||
const objErrorBase: ::c_int = 0x003d0000;
|
||||
|
||||
// taskLibCommon.h
|
||||
pub const S_taskLib_NAME_NOT_FOUND: ::c_int = taskErrorBase + 0x0065;
|
||||
pub const S_taskLib_TASK_HOOK_TABLE_FULL: ::c_int = taskErrorBase + 0x0066;
|
||||
pub const S_taskLib_TASK_HOOK_NOT_FOUND: ::c_int = taskErrorBase + 0x0067;
|
||||
pub const S_taskLib_ILLEGAL_PRIORITY: ::c_int = taskErrorBase + 0x0068;
|
||||
|
||||
// FIXME: could also be useful for TASK_DESC type
|
||||
pub const VX_TASK_NAME_LENGTH: ::c_int = 31;
|
||||
|
||||
// semLibCommon.h
|
||||
pub const S_semLib_INVALID_STATE: ::c_int = semErrorBase + 0x0065;
|
||||
pub const S_semLib_INVALID_OPTION: ::c_int = semErrorBase + 0x0066;
|
||||
pub const S_semLib_INVALID_QUEUE_TYPE: ::c_int = semErrorBase + 0x0067;
|
||||
pub const S_semLib_INVALID_OPERATION: ::c_int = semErrorBase + 0x0068;
|
||||
|
||||
// objLibCommon.h
|
||||
pub const S_objLib_OBJ_ID_ERROR: ::c_int = objErrorBase + 0x0001;
|
||||
pub const S_objLib_OBJ_UNAVAILABLE: ::c_int = objErrorBase + 0x0002;
|
||||
pub const S_objLib_OBJ_DELETED: ::c_int = objErrorBase + 0x0003;
|
||||
pub const S_objLib_OBJ_TIMEOUT: ::c_int = objErrorBase + 0x0004;
|
||||
pub const S_objLib_OBJ_NO_METHOD: ::c_int = objErrorBase + 0x0005;
|
||||
|
||||
// in.h
|
||||
pub const IPPROTO_IP: ::c_int = 0;
|
||||
pub const IPPROTO_IPV6: ::c_int = 41;
|
||||
|
@ -768,6 +797,7 @@ pub const S_IRWXO: ::c_int = 0x0007;
|
|||
|
||||
// socket.h
|
||||
pub const SOL_SOCKET: ::c_int = 0xffff;
|
||||
pub const SOMAXCONN: ::c_int = 128;
|
||||
|
||||
pub const SO_DEBUG: ::c_int = 0x0001;
|
||||
pub const SO_REUSEADDR: ::c_int = 0x0004;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::{Send, Sync};
|
||||
use core::iter::Iterator;
|
||||
|
||||
pub use ffi::c_void;
|
||||
|
||||
|
@ -175,6 +176,11 @@ s! {
|
|||
pub st_ctim: timespec,
|
||||
__reserved: [c_longlong; 3],
|
||||
}
|
||||
|
||||
pub struct fd_set {
|
||||
__nfds: usize,
|
||||
__fds: [c_int; FD_SETSIZE as usize],
|
||||
}
|
||||
}
|
||||
|
||||
// Declare dirent outside of s! so that it doesn't implement Copy, Eq, Hash,
|
||||
|
@ -366,10 +372,14 @@ pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE;
|
|||
pub const _SC_IOV_MAX: c_int = 60;
|
||||
pub const _SC_SYMLOOP_MAX: c_int = 173;
|
||||
|
||||
#[allow(unused_unsafe)] // `addr_of!(EXTERN_STATIC)` is now safe; remove `unsafe` when MSRV >= 1.82
|
||||
pub static CLOCK_MONOTONIC: clockid_t = unsafe { clockid_t(ptr_addr_of!(_CLOCK_MONOTONIC)) };
|
||||
#[allow(unused_unsafe)]
|
||||
pub static CLOCK_PROCESS_CPUTIME_ID: clockid_t =
|
||||
unsafe { clockid_t(ptr_addr_of!(_CLOCK_PROCESS_CPUTIME_ID)) };
|
||||
#[allow(unused_unsafe)]
|
||||
pub static CLOCK_REALTIME: clockid_t = unsafe { clockid_t(ptr_addr_of!(_CLOCK_REALTIME)) };
|
||||
#[allow(unused_unsafe)]
|
||||
pub static CLOCK_THREAD_CPUTIME_ID: clockid_t =
|
||||
unsafe { clockid_t(ptr_addr_of!(_CLOCK_THREAD_CPUTIME_ID)) };
|
||||
|
||||
|
@ -438,6 +448,28 @@ pub const NOEXPR: ::nl_item = 0x50001;
|
|||
pub const YESSTR: ::nl_item = 0x50002;
|
||||
pub const NOSTR: ::nl_item = 0x50003;
|
||||
|
||||
f! {
|
||||
pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool {
|
||||
let set = &*set;
|
||||
let n = set.__nfds;
|
||||
return set.__fds[..n].iter().any(|p| *p == fd)
|
||||
}
|
||||
|
||||
pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () {
|
||||
let set = &mut *set;
|
||||
let n = set.__nfds;
|
||||
if !set.__fds[..n].iter().any(|p| *p == fd) {
|
||||
set.__nfds = n + 1;
|
||||
set.__fds[n] = fd;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn FD_ZERO(set: *mut fd_set) -> () {
|
||||
(*set).__nfds = 0;
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "rustc-dep-of-std",
|
||||
link(
|
||||
|
@ -733,6 +765,14 @@ extern "C" {
|
|||
pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char;
|
||||
pub fn nl_langinfo_l(item: ::nl_item, loc: ::locale_t) -> *mut ::c_char;
|
||||
|
||||
pub fn select(
|
||||
nfds: c_int,
|
||||
readfds: *mut fd_set,
|
||||
writefds: *mut fd_set,
|
||||
errorfds: *mut fd_set,
|
||||
timeout: *const timeval,
|
||||
) -> c_int;
|
||||
|
||||
pub fn __wasilibc_register_preopened_fd(fd: c_int, path: *const c_char) -> c_int;
|
||||
pub fn __wasilibc_fd_renumber(fd: c_int, newfd: c_int) -> c_int;
|
||||
pub fn __wasilibc_unlinkat(fd: c_int, path: *const c_char) -> c_int;
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"32470c1f1471a46161eb9fda47e6e7d50e2615bfb0722bcd9355fbb90174319e","LICENSE":"06de63df29199a394442b57a28e886059ddc940973e10646877a0793fd53e2c9","README.md":"4c2a1448aab9177fd5f033faaf704af7bb222bf0804079fd3cff90fa1df4b812","src/errors/linux.rs":"df743ac9478e39f8a577f4f10f2d1317babad7b7c0d26cdbba2ea6b5426f4126","src/errors/macos.rs":"4516aaeb7abf6209f5cd94e86a1e55a9675ef77262f52e3b2d5596fd4b858458","src/errors/mod.rs":"f224af66124fd31a040c8da11bbab7b7795b48e4edea76e01c1f4dee537ea38a","src/errors/windows.rs":"0567af7bfac3ae2a8dff418e10873d8a5bf15a8b8ac6892c5ffdab08ec3ac901","src/format.rs":"4d9baaa3b3b52b4311efaadb12921088141becba8890ae977f0a2807eaa7f820","src/lib.rs":"0900c00594b3c386b86127055889006f0d7d0004b08455fadb0e60d55a469cab","src/traits.rs":"93127ad69a849325ed66a0626e0bdae05868488f81c539d35c71a7bfbb9e51ac","src/utils.rs":"17e8777b05998a8149fc5168af3bca1e0f9aeffe28cb3d6dbfb89c546f75e5ed"},"package":"1bb6eaf88cc770fa58e6ae721cf2e40c2ca6a4c942ae8c7aa324d680bd3c6717"}
|
||||
{"files":{"Cargo.toml":"3fe59b28a1e995925fd0d0a750787be30686e0ee5f93c0ff23ec5cdf9ef1ab87","LICENSE":"06de63df29199a394442b57a28e886059ddc940973e10646877a0793fd53e2c9","README.md":"4c2a1448aab9177fd5f033faaf704af7bb222bf0804079fd3cff90fa1df4b812","src/errors/linux.rs":"df743ac9478e39f8a577f4f10f2d1317babad7b7c0d26cdbba2ea6b5426f4126","src/errors/macos.rs":"4516aaeb7abf6209f5cd94e86a1e55a9675ef77262f52e3b2d5596fd4b858458","src/errors/mod.rs":"f224af66124fd31a040c8da11bbab7b7795b48e4edea76e01c1f4dee537ea38a","src/errors/windows.rs":"0567af7bfac3ae2a8dff418e10873d8a5bf15a8b8ac6892c5ffdab08ec3ac901","src/format.rs":"17daa7037ba9b4e8aa30a880975e883f618b3ff3ebb0b88a81313a895700fc6c","src/lib.rs":"0900c00594b3c386b86127055889006f0d7d0004b08455fadb0e60d55a469cab","src/traits.rs":"93127ad69a849325ed66a0626e0bdae05868488f81c539d35c71a7bfbb9e51ac","src/utils.rs":"6ab64a2fc39187903de0813d27db370cbeb57ba4984c6a993034829176bed4d7"},"package":"0cd8a9fb054833d2f402e82e256aeef544e595e45fe8fca2de6d03ed605f6647"}
|
|
@ -12,8 +12,13 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "minidump-common"
|
||||
version = "0.21.1"
|
||||
version = "0.22.1"
|
||||
authors = ["Ted Mielczarek <ted@mielczarek.org>"]
|
||||
build = false
|
||||
autobins = false
|
||||
autoexamples = false
|
||||
autotests = false
|
||||
autobenches = false
|
||||
description = "Some common types for working with minidump files."
|
||||
homepage = "https://github.com/rust-minidump/rust-minidump"
|
||||
readme = "README.md"
|
||||
|
@ -21,6 +26,10 @@ license = "MIT"
|
|||
repository = "https://github.com/rust-minidump/rust-minidump"
|
||||
resolver = "2"
|
||||
|
||||
[lib]
|
||||
name = "minidump_common"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies.arbitrary]
|
||||
version = "1"
|
||||
features = ["derive"]
|
||||
|
|
|
@ -1673,24 +1673,24 @@ multi_structs! {
|
|||
/// grafted onto Microsoft's own formats. Here's what's important to know:
|
||||
///
|
||||
/// * The "Cpu Context" and the "XSAVE context" are in fact the same regions
|
||||
/// of memory.
|
||||
/// of memory.
|
||||
///
|
||||
/// * Whether XSTATE is present or not, the classic layouts of CONTEXT_X86
|
||||
/// and [`CONTEXT_AMD64`] both apply -- xstate will only add stuff after *or*
|
||||
/// refine your understanding of memory in the existing layout. So you can
|
||||
/// safely ignore the existence of XSTATE, but you might be missing new info.
|
||||
/// and [`CONTEXT_AMD64`] both apply -- xstate will only add stuff after *or*
|
||||
/// refine your understanding of memory in the existing layout. So you can
|
||||
/// safely ignore the existence of XSTATE, but you might be missing new info.
|
||||
///
|
||||
/// * AMD64 doesn't have a standard way to save general purpose registers,
|
||||
/// so the first 256 bytes of [`CONTEXT_AMD64`] are just however microsoft
|
||||
/// decided to save the registers, and will not be referred to by the XSTATE.
|
||||
/// so the first 256 bytes of [`CONTEXT_AMD64`] are just however microsoft
|
||||
/// decided to save the registers, and will not be referred to by the XSTATE.
|
||||
///
|
||||
/// **!!! THIS PART IS IMPORTANT !!!**
|
||||
///
|
||||
/// * As a consequence, all [`XSTATE_FEATURE::offset`] values must have 256
|
||||
/// added to them to get the correct offset for that feature! For example, the
|
||||
/// LEGACY_FLOATING_POINT feature should always have an offset of 0, but it
|
||||
/// is actually at offset 256 in [`CONTEXT_AMD64`] (it corresponds to
|
||||
/// [`CONTEXT_AMD64::float_save`]).
|
||||
/// added to them to get the correct offset for that feature! For example, the
|
||||
/// LEGACY_FLOATING_POINT feature should always have an offset of 0, but it
|
||||
/// is actually at offset 256 in [`CONTEXT_AMD64`] (it corresponds to
|
||||
/// [`CONTEXT_AMD64::float_save`]).
|
||||
///
|
||||
/// * The following features are already contained inside of [`CONTEXT_AMD64`]:
|
||||
/// * LEGACY_FLOATING_POINT
|
||||
|
@ -1698,12 +1698,12 @@ multi_structs! {
|
|||
/// * GSSE_AND_AVX
|
||||
///
|
||||
/// * If there are XSTATE entries that *actually* map outside of the context's
|
||||
/// normal memory range, then the context's [`context_flags`](`CONTEXT_AMD64::context_flags`)
|
||||
/// will have bit 0x40 set ([`CONTEXT_HAS_XSTATE`]).
|
||||
/// normal memory range, then the context's [`context_flags`](`CONTEXT_AMD64::context_flags`)
|
||||
/// will have bit 0x40 set ([`CONTEXT_HAS_XSTATE`]).
|
||||
///
|
||||
/// * [`ContextFlagsCpu::from_flags`] will mask out the [`CONTEXT_HAS_XSTATE`] bit.
|
||||
/// If you want to check for that bit, check the raw value of
|
||||
/// [`context_flags`](`CONTEXT_AMD64::context_flags`).
|
||||
/// If you want to check for that bit, check the raw value of
|
||||
/// [`context_flags`](`CONTEXT_AMD64::context_flags`).
|
||||
|
||||
#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
|
||||
pub struct XSTATE_CONFIG_FEATURE_MSC_INFO {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Utility functions, only pathname handling at the moment.
|
||||
|
||||
pub fn basename(f: &str) -> &str {
|
||||
match f.rfind(|c| c == '/' || c == '\\') {
|
||||
match f.rfind(['/', '\\']) {
|
||||
None => f,
|
||||
Some(index) => &f[(index + 1)..],
|
||||
}
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -8,6 +8,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
<!-- next-header -->
|
||||
## [Unreleased] - ReleaseDate
|
||||
## [0.10.1] - 2024-09-20
|
||||
### Fixed
|
||||
- [PR#129](https://github.com/rust-minidump/minidump-writer/pull/129) added checking of additions to ensure invalid memory offsets are gracefully handled.
|
||||
- [PR#135](https://github.com/rust-minidump/minidump-writer/pull/135) resolved [#134](https://github.com/rust-minidump/minidump-writer/issues/134) by attempting to read the executables build id from the mapped file if it could not be retrieved from process memory.
|
||||
- [PR#136](https://github.com/rust-minidump/minidump-writer/pull/136) changed to an older type to avoid requiring a semi-recent rust version.
|
||||
|
||||
## [0.10.0] - 2024-08-20
|
||||
### Changed
|
||||
- [PR#118](https://github.com/rust-minidump/minidump-writer/pull/118) resolved [#72](https://github.com/rust-minidump/minidump-writer/issues/72) by adding support for reading process memory via `process_vm_readv` and `/proc/{pid}/mem`, in addition to the original `PTRACE_PEEKDATA`. This gives significant performance benefits as memory can now be read in blocks of arbitrary size instead of word-by-word with ptrace.
|
||||
- [PR#128](https://github.com/rust-minidump/minidump-writer/pull/128) and [PR#133](https://github.com/rust-minidump/minidump-writer/pull/133) updated the lockfile.
|
||||
|
||||
### Fixed
|
||||
- [PR#127](https://github.com/rust-minidump/minidump-writer/pull/127) resolved [#27](https://github.com/rust-minidump/minidump-writer/issues/27) by allowing programs to pass the needed auxv information, still falling back to reading `/proc/{pid}/auxv` to fill missing information, and being more permissive by still writing a dump if some or all of the auxv information could not be retrieved successfully rather than completely failing to write the minidump.
|
||||
- [PR#131](https://github.com/rust-minidump/minidump-writer/pull/131) resolved [#124](https://github.com/rust-minidump/minidump-writer/issues/124) by reinjecting non-`SIGSTOP` signals after `ptrace::attach` so that the thread would be in the correct state after `ptrace::detach`.
|
||||
|
||||
## [0.9.0] - 2024-07-20
|
||||
### Fixed
|
||||
- [PR#117](https://github.com/rust-minidump/minidump-writer/pull/117) resolved [#79](https://github.com/rust-minidump/minidump-writer/issues/79) by enabling reading of a module's build id and soname directly from the mapped process rather than relying on file reading, though that is still used as a fallback.
|
||||
|
||||
### Changed
|
||||
- [PR#126](https://github.com/rust-minidump/minidump-writer/pull/126) updated `minidump-common` -> 0.22.
|
||||
|
||||
## [0.8.9] - 2024-04-01
|
||||
### Fixed
|
||||
- [PR#110](https://github.com/rust-minidump/minidump-writer/pull/110) changed it so that `SIGCONT` is sent regardless if the process was not able to be `SIGSTOP`ed quickly enough.
|
||||
|
@ -135,7 +157,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Initial release, including basic support for `x86_64-unknown-linux-gnu/musl` and `x86_64-pc-windows-msvc`
|
||||
|
||||
<!-- next-url -->
|
||||
[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/0.8.9...HEAD
|
||||
[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/0.10.1...HEAD
|
||||
[0.10.1]: https://github.com/rust-minidump/minidump-writer/compare/0.10.0...0.10.1
|
||||
[0.10.0]: https://github.com/rust-minidump/minidump-writer/compare/0.9.0...0.10.0
|
||||
[0.9.0]: https://github.com/rust-minidump/minidump-writer/compare/0.8.9...0.9.0
|
||||
[0.8.9]: https://github.com/rust-minidump/minidump-writer/compare/0.8.8...0.8.9
|
||||
[0.8.8]: https://github.com/rust-minidump/minidump-writer/compare/0.8.7...0.8.8
|
||||
[0.8.7]: https://github.com/rust-minidump/minidump-writer/compare/0.8.6...0.8.7
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -12,14 +12,51 @@
|
|||
[package]
|
||||
edition = "2021"
|
||||
name = "minidump-writer"
|
||||
version = "0.8.9"
|
||||
version = "0.10.1"
|
||||
authors = ["Martin Sirringhaus"]
|
||||
build = "build.rs"
|
||||
autobins = false
|
||||
autoexamples = false
|
||||
autotests = false
|
||||
autobenches = false
|
||||
description = "Rust rewrite of Breakpad's minidump_writer"
|
||||
homepage = "https://github.com/rust-minidump/minidump-writer"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/rust-minidump/minidump-writer"
|
||||
|
||||
[lib]
|
||||
name = "minidump_writer"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "test"
|
||||
path = "src/bin/test.rs"
|
||||
|
||||
[[example]]
|
||||
name = "synthetic"
|
||||
path = "examples/synthetic.rs"
|
||||
|
||||
[[test]]
|
||||
name = "linux_minidump_writer"
|
||||
path = "tests/linux_minidump_writer.rs"
|
||||
|
||||
[[test]]
|
||||
name = "mac_minidump_writer"
|
||||
path = "tests/mac_minidump_writer.rs"
|
||||
|
||||
[[test]]
|
||||
name = "ptrace_dumper"
|
||||
path = "tests/ptrace_dumper.rs"
|
||||
|
||||
[[test]]
|
||||
name = "task_dumper"
|
||||
path = "tests/task_dumper.rs"
|
||||
|
||||
[[test]]
|
||||
name = "windows_minidump_writer"
|
||||
path = "tests/windows_minidump_writer.rs"
|
||||
|
||||
[dependencies.bitflags]
|
||||
version = "2.4"
|
||||
|
||||
|
@ -39,7 +76,7 @@ version = "0.4"
|
|||
version = "0.9"
|
||||
|
||||
[dependencies.minidump-common]
|
||||
version = "0.21"
|
||||
version = "0.22"
|
||||
|
||||
[dependencies.scroll]
|
||||
version = "0.12"
|
||||
|
@ -61,49 +98,50 @@ features = ["executor"]
|
|||
version = "0.9"
|
||||
|
||||
[dev-dependencies.minidump]
|
||||
version = "0.21"
|
||||
version = "0.22"
|
||||
|
||||
[target."cfg(any(target_os = \"linux\", target_os = \"android\"))".dependencies.nix]
|
||||
version = "0.28"
|
||||
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies.nix]
|
||||
version = "0.29"
|
||||
features = [
|
||||
"mman",
|
||||
"process",
|
||||
"ptrace",
|
||||
"signal",
|
||||
"uio",
|
||||
"user",
|
||||
]
|
||||
default-features = false
|
||||
|
||||
[target."cfg(any(target_os = \"linux\", target_os = \"android\"))".dependencies.procfs-core]
|
||||
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies.procfs-core]
|
||||
version = "0.16"
|
||||
default-features = false
|
||||
|
||||
[target."cfg(target_os = \"macos\")".dependencies.mach2]
|
||||
[target.'cfg(target_os = "macos")'.dependencies.mach2]
|
||||
version = "0.4"
|
||||
|
||||
[target."cfg(target_os = \"macos\")".dev-dependencies.dump_syms]
|
||||
[target.'cfg(target_os = "macos")'.dev-dependencies.dump_syms]
|
||||
version = "2.2"
|
||||
default-features = false
|
||||
|
||||
[target."cfg(target_os = \"macos\")".dev-dependencies.minidump-processor]
|
||||
version = "0.21"
|
||||
[target.'cfg(target_os = "macos")'.dev-dependencies.minidump-processor]
|
||||
version = "0.22"
|
||||
default-features = false
|
||||
|
||||
[target."cfg(target_os = \"macos\")".dev-dependencies.minidump-unwind]
|
||||
version = "0.21"
|
||||
[target.'cfg(target_os = "macos")'.dev-dependencies.minidump-unwind]
|
||||
version = "0.22"
|
||||
features = ["debuginfo"]
|
||||
|
||||
[target."cfg(target_os = \"macos\")".dev-dependencies.similar-asserts]
|
||||
[target.'cfg(target_os = "macos")'.dev-dependencies.similar-asserts]
|
||||
version = "1.5"
|
||||
|
||||
[target."cfg(target_os = \"macos\")".dev-dependencies.uuid]
|
||||
[target.'cfg(target_os = "macos")'.dev-dependencies.uuid]
|
||||
version = "1.4"
|
||||
|
||||
[target."cfg(target_os = \"windows\")".dependencies.bitflags]
|
||||
[target.'cfg(target_os = "windows")'.dependencies.bitflags]
|
||||
version = "2.4"
|
||||
|
||||
[target."cfg(unix)".dependencies.goblin]
|
||||
version = "0.8"
|
||||
version = "0.8.2"
|
||||
|
||||
[target."cfg(unix)".dependencies.libc]
|
||||
version = "0.2"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
[graph]
|
||||
targets = [
|
||||
{ triple = "x86_64-unknown-linux-gnu" },
|
||||
{ triple = "x86_64-unknown-linux-musl" },
|
||||
|
@ -14,7 +15,7 @@ ignore = []
|
|||
[bans]
|
||||
multiple-versions = "deny"
|
||||
deny = [
|
||||
#{ crate = "chrono", use-instead = "time", reason = "unneccessary dependency" },
|
||||
{ crate = "chrono", use-instead = "time", reason = "unneccessary dependency" },
|
||||
]
|
||||
skip-tree = []
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@ pub type Result<T> = std::result::Result<T, Error>;
|
|||
mod linux {
|
||||
use super::*;
|
||||
use minidump_writer::{
|
||||
minidump_writer::STOP_TIMEOUT,
|
||||
ptrace_dumper::{PtraceDumper, AT_SYSINFO_EHDR},
|
||||
minidump_writer::STOP_TIMEOUT, module_reader, ptrace_dumper::PtraceDumper,
|
||||
LINUX_GATE_LIBRARY_NAME,
|
||||
};
|
||||
use nix::{
|
||||
|
@ -19,24 +18,22 @@ mod linux {
|
|||
|
||||
macro_rules! test {
|
||||
($x:expr, $errmsg:expr) => {
|
||||
if $x {
|
||||
Ok(())
|
||||
} else {
|
||||
Err($errmsg)
|
||||
if !$x {
|
||||
return Err($errmsg.into());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn test_setup() -> Result<()> {
|
||||
let ppid = getppid();
|
||||
PtraceDumper::new(ppid.as_raw(), STOP_TIMEOUT)?;
|
||||
PtraceDumper::new(ppid.as_raw(), STOP_TIMEOUT, Default::default())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_thread_list() -> Result<()> {
|
||||
let ppid = getppid();
|
||||
let dumper = PtraceDumper::new(ppid.as_raw(), STOP_TIMEOUT)?;
|
||||
test!(!dumper.threads.is_empty(), "No threads")?;
|
||||
let dumper = PtraceDumper::new(ppid.as_raw(), STOP_TIMEOUT, Default::default())?;
|
||||
test!(!dumper.threads.is_empty(), "No threads");
|
||||
test!(
|
||||
dumper
|
||||
.threads
|
||||
|
@ -45,35 +42,84 @@ mod linux {
|
|||
.count()
|
||||
== 1,
|
||||
"Thread found multiple times"
|
||||
)?;
|
||||
);
|
||||
|
||||
test!(
|
||||
dumper
|
||||
.threads
|
||||
.iter()
|
||||
.any(|thread| thread.name.as_deref() == Some("sighup-thread")),
|
||||
"Failed to locate and/or stop sighup-thread"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_copy_from_process(stack_var: usize, heap_var: usize) -> Result<()> {
|
||||
use minidump_writer::mem_reader::MemReader;
|
||||
|
||||
let ppid = getppid().as_raw();
|
||||
let mut dumper = PtraceDumper::new(ppid, STOP_TIMEOUT)?;
|
||||
let mut dumper = PtraceDumper::new(ppid, STOP_TIMEOUT, Default::default())?;
|
||||
dumper.suspend_threads()?;
|
||||
let stack_res = PtraceDumper::copy_from_process(ppid, stack_var as *mut libc::c_void, 1)?;
|
||||
|
||||
let expected_stack: libc::c_long = 0x11223344;
|
||||
test!(
|
||||
stack_res == expected_stack.to_ne_bytes(),
|
||||
"stack var not correct"
|
||||
)?;
|
||||
// We support 3 different methods of reading memory from another
|
||||
// process, ensure they all function and give the same results
|
||||
|
||||
let expected_stack = 0x11223344usize.to_ne_bytes();
|
||||
let expected_heap = 0x55667788usize.to_ne_bytes();
|
||||
|
||||
let validate = |reader: &mut MemReader| -> Result<()> {
|
||||
let mut val = [0u8; std::mem::size_of::<usize>()];
|
||||
let read = reader.read(stack_var, &mut val)?;
|
||||
assert_eq!(read, val.len());
|
||||
test!(val == expected_stack, "stack var not correct");
|
||||
|
||||
let read = reader.read(heap_var, &mut val)?;
|
||||
assert_eq!(read, val.len());
|
||||
test!(val == expected_heap, "heap var not correct");
|
||||
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// virtual mem
|
||||
{
|
||||
let mut mr = MemReader::for_virtual_mem(ppid);
|
||||
validate(&mut mr)
|
||||
.map_err(|err| format!("failed to validate memory for {mr:?}: {err}"))?;
|
||||
}
|
||||
|
||||
// file
|
||||
{
|
||||
let mut mr = MemReader::for_file(ppid)
|
||||
.map_err(|err| format!("failed to open `/proc/{ppid}/mem`: {err}"))?;
|
||||
validate(&mut mr)
|
||||
.map_err(|err| format!("failed to validate memory for {mr:?}: {err}"))?;
|
||||
}
|
||||
|
||||
// ptrace
|
||||
{
|
||||
let mut mr = MemReader::for_ptrace(ppid);
|
||||
validate(&mut mr)
|
||||
.map_err(|err| format!("failed to validate memory for {mr:?}: {err}"))?;
|
||||
}
|
||||
|
||||
let stack_res =
|
||||
PtraceDumper::copy_from_process(ppid, stack_var, std::mem::size_of::<usize>())?;
|
||||
|
||||
test!(stack_res == expected_stack, "stack var not correct");
|
||||
|
||||
let heap_res =
|
||||
PtraceDumper::copy_from_process(ppid, heap_var, std::mem::size_of::<usize>())?;
|
||||
|
||||
test!(heap_res == expected_heap, "heap var not correct");
|
||||
|
||||
let heap_res = PtraceDumper::copy_from_process(ppid, heap_var as *mut libc::c_void, 1)?;
|
||||
let expected_heap: libc::c_long = 0x55667788;
|
||||
test!(
|
||||
heap_res == expected_heap.to_ne_bytes(),
|
||||
"heap var not correct"
|
||||
)?;
|
||||
dumper.resume_threads()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_find_mappings(addr1: usize, addr2: usize) -> Result<()> {
|
||||
let ppid = getppid();
|
||||
let dumper = PtraceDumper::new(ppid.as_raw(), STOP_TIMEOUT)?;
|
||||
let dumper = PtraceDumper::new(ppid.as_raw(), STOP_TIMEOUT, Default::default())?;
|
||||
dumper
|
||||
.find_mapping(addr1)
|
||||
.ok_or("No mapping for addr1 found")?;
|
||||
|
@ -82,15 +128,16 @@ mod linux {
|
|||
.find_mapping(addr2)
|
||||
.ok_or("No mapping for addr2 found")?;
|
||||
|
||||
test!(dumper.find_mapping(0).is_none(), "NULL found")?;
|
||||
test!(dumper.find_mapping(0).is_none(), "NULL found");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_file_id() -> Result<()> {
|
||||
let ppid = getppid().as_raw();
|
||||
let exe_link = format!("/proc/{}/exe", ppid);
|
||||
let exe_link = format!("/proc/{ppid}/exe");
|
||||
let exe_name = std::fs::read_link(exe_link)?.into_os_string();
|
||||
let mut dumper = PtraceDumper::new(getppid().as_raw(), STOP_TIMEOUT)?;
|
||||
let mut dumper = PtraceDumper::new(ppid, STOP_TIMEOUT, Default::default())?;
|
||||
dumper.suspend_threads()?;
|
||||
let mut found_exe = None;
|
||||
for (idx, mapping) in dumper.mappings.iter().enumerate() {
|
||||
if mapping.name.as_ref().map(|x| x.into()).as_ref() == Some(&exe_name) {
|
||||
|
@ -99,7 +146,8 @@ mod linux {
|
|||
}
|
||||
}
|
||||
let idx = found_exe.unwrap();
|
||||
let id = dumper.elf_identifier_for_mapping_index(idx)?;
|
||||
let module_reader::BuildId(id) = dumper.from_process_memory_for_index(idx)?;
|
||||
dumper.resume_threads()?;
|
||||
assert!(!id.is_empty());
|
||||
assert!(id.iter().any(|&x| x > 0));
|
||||
Ok(())
|
||||
|
@ -107,7 +155,7 @@ mod linux {
|
|||
|
||||
fn test_merged_mappings(path: String, mapped_mem: usize, mem_size: usize) -> Result<()> {
|
||||
// Now check that PtraceDumper interpreted the mappings properly.
|
||||
let dumper = PtraceDumper::new(getppid().as_raw(), STOP_TIMEOUT)?;
|
||||
let dumper = PtraceDumper::new(getppid().as_raw(), STOP_TIMEOUT, Default::default())?;
|
||||
let mut mapping_count = 0;
|
||||
for map in &dumper.mappings {
|
||||
if map
|
||||
|
@ -129,28 +177,29 @@ mod linux {
|
|||
|
||||
fn test_linux_gate_mapping_id() -> Result<()> {
|
||||
let ppid = getppid().as_raw();
|
||||
let mut dumper = PtraceDumper::new(ppid, STOP_TIMEOUT)?;
|
||||
let mut dumper = PtraceDumper::new(ppid, STOP_TIMEOUT, Default::default())?;
|
||||
let mut found_linux_gate = false;
|
||||
for mut mapping in dumper.mappings.clone() {
|
||||
for mapping in dumper.mappings.clone() {
|
||||
if mapping.name == Some(LINUX_GATE_LIBRARY_NAME.into()) {
|
||||
found_linux_gate = true;
|
||||
dumper.suspend_threads()?;
|
||||
let id = PtraceDumper::elf_identifier_for_mapping(&mut mapping, ppid)?;
|
||||
test!(!id.is_empty(), "id-vec is empty")?;
|
||||
test!(id.iter().any(|&x| x > 0), "all id elements are 0")?;
|
||||
let module_reader::BuildId(id) =
|
||||
PtraceDumper::from_process_memory_for_mapping(&mapping, ppid)?;
|
||||
test!(!id.is_empty(), "id-vec is empty");
|
||||
test!(id.iter().any(|&x| x > 0), "all id elements are 0");
|
||||
dumper.resume_threads()?;
|
||||
break;
|
||||
}
|
||||
}
|
||||
test!(found_linux_gate, "found no linux_gate")?;
|
||||
test!(found_linux_gate, "found no linux_gate");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_mappings_include_linux_gate() -> Result<()> {
|
||||
let ppid = getppid().as_raw();
|
||||
let dumper = PtraceDumper::new(ppid, STOP_TIMEOUT)?;
|
||||
let linux_gate_loc = dumper.auxv[&AT_SYSINFO_EHDR];
|
||||
test!(linux_gate_loc != 0, "linux_gate_loc == 0")?;
|
||||
let dumper = PtraceDumper::new(ppid, STOP_TIMEOUT, Default::default())?;
|
||||
let linux_gate_loc = dumper.auxv.get_linux_gate_address().unwrap();
|
||||
test!(linux_gate_loc != 0, "linux_gate_loc == 0");
|
||||
let mut found_linux_gate = false;
|
||||
for mapping in &dumper.mappings {
|
||||
if mapping.name == Some(LINUX_GATE_LIBRARY_NAME.into()) {
|
||||
|
@ -158,7 +207,7 @@ mod linux {
|
|||
test!(
|
||||
linux_gate_loc == mapping.start_address.try_into()?,
|
||||
"linux_gate_loc != start_address"
|
||||
)?;
|
||||
);
|
||||
|
||||
// This doesn't work here, as we do not test via "fork()", so the addresses are different
|
||||
// let ll = mapping.start_address as *const u8;
|
||||
|
@ -172,7 +221,7 @@ mod linux {
|
|||
break;
|
||||
}
|
||||
}
|
||||
test!(found_linux_gate, "found no linux_gate")?;
|
||||
test!(found_linux_gate, "found no linux_gate");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -268,6 +317,7 @@ mod linux {
|
|||
pub(super) fn real_main(args: Vec<String>) -> Result<()> {
|
||||
match args.len() {
|
||||
1 => match args[0].as_ref() {
|
||||
"nop" => Ok(()),
|
||||
"file_id" => test_file_id(),
|
||||
"setup" => test_setup(),
|
||||
"thread_list" => test_thread_list(),
|
||||
|
|
|
@ -4,15 +4,18 @@
|
|||
#[cfg(target_os = "android")]
|
||||
mod android;
|
||||
pub mod app_memory;
|
||||
pub(crate) mod auxv_reader;
|
||||
pub(crate) mod auxv;
|
||||
pub mod crash_context;
|
||||
mod dso_debug;
|
||||
mod dumper_cpu_info;
|
||||
pub mod errors;
|
||||
pub mod maps_reader;
|
||||
pub mod mem_reader;
|
||||
pub mod minidump_writer;
|
||||
pub mod module_reader;
|
||||
pub mod ptrace_dumper;
|
||||
pub(crate) mod sections;
|
||||
pub mod thread_info;
|
||||
|
||||
pub use maps_reader::LINUX_GATE_LIBRARY_NAME;
|
||||
pub type Pid = i32;
|
||||
|
|
|
@ -1,38 +1,31 @@
|
|||
use crate::errors::AndroidError;
|
||||
use crate::maps_reader::MappingInfo;
|
||||
use crate::ptrace_dumper::PtraceDumper;
|
||||
use crate::thread_info::Pid;
|
||||
use crate::Pid;
|
||||
use goblin::elf;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
use goblin::elf::dynamic::dyn32::{Dyn, SIZEOF_DYN};
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
use goblin::elf::dynamic::dyn64::{Dyn, SIZEOF_DYN};
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
use goblin::elf::header::header32 as elf_header;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
use goblin::elf::header::header64 as elf_header;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
use goblin::elf::program_header::program_header32::ProgramHeader;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
use goblin::elf::program_header::program_header64::ProgramHeader;
|
||||
use std::ffi::c_void;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_pointer_width = "32")] {
|
||||
use elf::dynamic::dyn32::{Dyn, SIZEOF_DYN};
|
||||
use elf::header::header32 as elf_header;
|
||||
use elf::program_header::program_header32::ProgramHeader;
|
||||
|
||||
const DT_ANDROID_REL: u32 = (elf::dynamic::DT_LOOS + 2) as u32;
|
||||
const DT_ANDROID_RELA: u32 = (elf::dynamic::DT_LOOS + 4) as u32;
|
||||
} else if #[cfg(target_pointer_width = "64")] {
|
||||
use elf::dynamic::dyn64::{Dyn, SIZEOF_DYN};
|
||||
use elf::header::header64 as elf_header;
|
||||
use elf::program_header::program_header64::ProgramHeader;
|
||||
|
||||
const DT_ANDROID_REL: u64 = elf::dynamic::DT_LOOS + 2;
|
||||
const DT_ANDROID_RELA: u64 = elf::dynamic::DT_LOOS + 4;
|
||||
} else {
|
||||
compile_error!("invalid pointer width");
|
||||
}
|
||||
}
|
||||
|
||||
type Result<T> = std::result::Result<T, AndroidError>;
|
||||
|
||||
// From /usr/include/elf.h of the android SDK
|
||||
// #define DT_ANDROID_REL (DT_LOOS + 2)
|
||||
// #define DT_ANDROID_RELSZ (DT_LOOS + 3)
|
||||
// #define DT_ANDROID_RELA (DT_LOOS + 4)
|
||||
// #define DT_ANDROID_RELASZ (DT_LOOS + 5)
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const DT_ANDROID_REL: u64 = elf::dynamic::DT_LOOS + 2;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const DT_ANDROID_RELA: u64 = elf::dynamic::DT_LOOS + 4;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const DT_ANDROID_REL: u32 = (elf::dynamic::DT_LOOS + 2) as u32;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const DT_ANDROID_RELA: u32 = (elf::dynamic::DT_LOOS + 4) as u32;
|
||||
|
||||
struct DynVaddresses {
|
||||
min_vaddr: usize,
|
||||
dyn_vaddr: usize,
|
||||
|
@ -42,7 +35,7 @@ struct DynVaddresses {
|
|||
fn has_android_packed_relocations(pid: Pid, load_bias: usize, vaddrs: DynVaddresses) -> Result<()> {
|
||||
let dyn_addr = load_bias + vaddrs.dyn_vaddr;
|
||||
for idx in 0..vaddrs.dyn_count {
|
||||
let addr = (dyn_addr + SIZEOF_DYN * idx) as *mut c_void;
|
||||
let addr = dyn_addr + SIZEOF_DYN * idx;
|
||||
let dyn_data = PtraceDumper::copy_from_process(pid, addr, SIZEOF_DYN)?;
|
||||
// TODO: Couldn't find a nice way to use goblin for that, to avoid the unsafe-block
|
||||
let dyn_obj: Dyn;
|
||||
|
@ -85,7 +78,7 @@ fn parse_loaded_elf_program_headers(
|
|||
|
||||
let phdr_opt = PtraceDumper::copy_from_process(
|
||||
pid,
|
||||
phdr_addr as *mut c_void,
|
||||
phdr_addr,
|
||||
elf_header::SIZEOF_EHDR * ehdr.e_phnum as usize,
|
||||
);
|
||||
if let Ok(ph_data) = phdr_opt {
|
||||
|
@ -120,13 +113,10 @@ pub fn late_process_mappings(pid: Pid, mappings: &mut [MappingInfo]) -> Result<(
|
|||
.iter_mut()
|
||||
.filter(|m| m.is_executable() && m.name_is_path())
|
||||
{
|
||||
let ehdr_opt = PtraceDumper::copy_from_process(
|
||||
pid,
|
||||
map.start_address as *mut c_void,
|
||||
elf_header::SIZEOF_EHDR,
|
||||
)
|
||||
.ok()
|
||||
.and_then(|x| elf_header::Header::parse(&x).ok());
|
||||
let ehdr_opt =
|
||||
PtraceDumper::copy_from_process(pid, map.start_address, elf_header::SIZEOF_EHDR)
|
||||
.ok()
|
||||
.and_then(|x| elf_header::Header::parse(&x).ok());
|
||||
|
||||
if let Some(ehdr) = ehdr_opt {
|
||||
if ehdr.e_type == elf_header::ET_DYN {
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
pub use reader::ProcfsAuxvIter;
|
||||
use {
|
||||
crate::Pid,
|
||||
std::{fs::File, io::BufReader},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
mod reader;
|
||||
|
||||
/// The type used in auxv keys and values.
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub type AuxvType = u32;
|
||||
/// The type used in auxv keys and values.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub type AuxvType = u64;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
mod consts {
|
||||
use super::AuxvType;
|
||||
pub const AT_PHDR: AuxvType = 3;
|
||||
pub const AT_PHNUM: AuxvType = 5;
|
||||
pub const AT_ENTRY: AuxvType = 9;
|
||||
pub const AT_SYSINFO_EHDR: AuxvType = 33;
|
||||
}
|
||||
#[cfg(not(target_os = "android"))]
|
||||
mod consts {
|
||||
use super::AuxvType;
|
||||
pub const AT_PHDR: AuxvType = libc::AT_PHDR;
|
||||
pub const AT_PHNUM: AuxvType = libc::AT_PHNUM;
|
||||
pub const AT_ENTRY: AuxvType = libc::AT_ENTRY;
|
||||
pub const AT_SYSINFO_EHDR: AuxvType = libc::AT_SYSINFO_EHDR;
|
||||
}
|
||||
|
||||
/// An auxv key-value pair.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct AuxvPair {
|
||||
pub key: AuxvType,
|
||||
pub value: AuxvType,
|
||||
}
|
||||
|
||||
/// Auxv info that can be passed from crashing process
|
||||
///
|
||||
/// Since `/proc/{pid}/auxv` can sometimes be inaccessible, the calling process should prefer to transfer this
|
||||
/// information directly using the Linux `getauxval()` call (if possible).
|
||||
///
|
||||
/// Any field that is set to `0` will be considered unset. In that case, minidump-writer might try other techniques
|
||||
/// to obtain it (like reading `/proc/{pid}/auxv`).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct DirectAuxvDumpInfo {
|
||||
/// The value of `getauxval(AT_PHNUM)`
|
||||
pub program_header_count: AuxvType,
|
||||
/// The value of `getauxval(AT_PHDR)`
|
||||
pub program_header_address: AuxvType,
|
||||
/// The value of `getauxval(AT_SYSINFO_EHDR)`
|
||||
pub linux_gate_address: AuxvType,
|
||||
/// The value of `getauxval(AT_ENTRY)`
|
||||
pub entry_address: AuxvType,
|
||||
}
|
||||
|
||||
impl From<DirectAuxvDumpInfo> for AuxvDumpInfo {
|
||||
fn from(f: DirectAuxvDumpInfo) -> AuxvDumpInfo {
|
||||
AuxvDumpInfo {
|
||||
program_header_count: (f.program_header_count > 0).then_some(f.program_header_count),
|
||||
program_header_address: (f.program_header_address > 0)
|
||||
.then_some(f.program_header_address),
|
||||
linux_gate_address: (f.linux_gate_address > 0).then_some(f.linux_gate_address),
|
||||
entry_address: (f.entry_address > 0).then_some(f.entry_address),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct AuxvDumpInfo {
|
||||
program_header_count: Option<AuxvType>,
|
||||
program_header_address: Option<AuxvType>,
|
||||
linux_gate_address: Option<AuxvType>,
|
||||
entry_address: Option<AuxvType>,
|
||||
}
|
||||
|
||||
impl AuxvDumpInfo {
|
||||
pub fn try_filling_missing_info(&mut self, pid: Pid) -> Result<(), AuxvError> {
|
||||
if self.is_complete() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let auxv_path = format!("/proc/{pid}/auxv");
|
||||
let auxv_file = File::open(&auxv_path).map_err(|e| AuxvError::OpenError(auxv_path, e))?;
|
||||
|
||||
for AuxvPair { key, value } in
|
||||
ProcfsAuxvIter::new(BufReader::new(auxv_file)).filter_map(Result::ok)
|
||||
{
|
||||
let dest_field = match key {
|
||||
consts::AT_PHNUM => &mut self.program_header_count,
|
||||
consts::AT_PHDR => &mut self.program_header_address,
|
||||
consts::AT_SYSINFO_EHDR => &mut self.linux_gate_address,
|
||||
consts::AT_ENTRY => &mut self.entry_address,
|
||||
_ => continue,
|
||||
};
|
||||
if dest_field.is_none() {
|
||||
*dest_field = Some(value);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub fn get_program_header_count(&self) -> Option<AuxvType> {
|
||||
self.program_header_count
|
||||
}
|
||||
pub fn get_program_header_address(&self) -> Option<AuxvType> {
|
||||
self.program_header_address
|
||||
}
|
||||
pub fn get_linux_gate_address(&self) -> Option<AuxvType> {
|
||||
self.linux_gate_address
|
||||
}
|
||||
pub fn get_entry_address(&self) -> Option<AuxvType> {
|
||||
self.entry_address
|
||||
}
|
||||
pub fn is_complete(&self) -> bool {
|
||||
self.program_header_count.is_some()
|
||||
&& self.program_header_address.is_some()
|
||||
&& self.linux_gate_address.is_some()
|
||||
&& self.entry_address.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AuxvError {
|
||||
#[error("Failed to open file {0}")]
|
||||
OpenError(String, #[source] std::io::Error),
|
||||
#[error("No auxv entry found for PID {0}")]
|
||||
NoAuxvEntryFound(Pid),
|
||||
#[error("Invalid auxv format (should not hit EOF before AT_NULL)")]
|
||||
InvalidFormat,
|
||||
#[error("IO Error")]
|
||||
IOError(#[from] std::io::Error),
|
||||
}
|
|
@ -4,26 +4,15 @@
|
|||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
// The above copyright notice and this permission notice shall be in…substantial portions of the Software.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
use crate::errors::AuxvReaderError;
|
||||
use byteorder::{NativeEndian, ReadBytesExt};
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Read};
|
||||
|
||||
pub type Result<T> = std::result::Result<T, AuxvReaderError>;
|
||||
|
||||
/// The type used in auxv keys and values.
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub type AuxvType = u32;
|
||||
/// The type used in auxv keys and values.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub type AuxvType = u64;
|
||||
|
||||
/// An auxv key-value pair.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct AuxvPair {
|
||||
pub key: AuxvType,
|
||||
pub value: AuxvType,
|
||||
}
|
||||
use {
|
||||
super::{AuxvError, AuxvPair, AuxvType},
|
||||
byteorder::{NativeEndian, ReadBytesExt},
|
||||
std::{
|
||||
fs::File,
|
||||
io::{BufReader, Read},
|
||||
},
|
||||
};
|
||||
|
||||
/// An iterator across auxv pairs from procfs.
|
||||
pub struct ProcfsAuxvIter {
|
||||
|
@ -48,7 +37,7 @@ impl ProcfsAuxvIter {
|
|||
}
|
||||
|
||||
impl Iterator for ProcfsAuxvIter {
|
||||
type Item = Result<AuxvPair>;
|
||||
type Item = Result<AuxvPair, AuxvError>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if !self.keep_going {
|
||||
return None;
|
||||
|
@ -65,7 +54,7 @@ impl Iterator for ProcfsAuxvIter {
|
|||
Ok(n) => {
|
||||
if n == 0 {
|
||||
// should not hit EOF before AT_NULL
|
||||
return Some(Err(AuxvReaderError::InvalidFormat));
|
||||
return Some(Err(AuxvError::InvalidFormat));
|
||||
}
|
||||
|
||||
read_bytes += n;
|
|
@ -1,9 +1,8 @@
|
|||
use crate::{
|
||||
linux::{auxv_reader::AuxvType, errors::SectionDsoDebugError, ptrace_dumper::PtraceDumper},
|
||||
linux::{auxv::AuxvDumpInfo, errors::SectionDsoDebugError, ptrace_dumper::PtraceDumper},
|
||||
mem_writer::{write_string_to_location, Buffer, MemoryArrayWriter, MemoryWriter},
|
||||
minidump_format::*,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
type Result<T> = std::result::Result<T, SectionDsoDebugError>;
|
||||
|
||||
|
@ -77,33 +76,16 @@ pub struct RDebug {
|
|||
pub fn write_dso_debug_stream(
|
||||
buffer: &mut Buffer,
|
||||
blamed_thread: i32,
|
||||
auxv: &HashMap<AuxvType, AuxvType>,
|
||||
auxv: &AuxvDumpInfo,
|
||||
) -> Result<MDRawDirectory> {
|
||||
let at_phnum;
|
||||
let at_phdr;
|
||||
#[cfg(any(target_arch = "arm", all(target_os = "android", target_arch = "x86")))]
|
||||
{
|
||||
at_phdr = 3;
|
||||
at_phnum = 5;
|
||||
}
|
||||
#[cfg(not(any(target_arch = "arm", all(target_os = "android", target_arch = "x86"))))]
|
||||
{
|
||||
at_phdr = libc::AT_PHDR;
|
||||
at_phnum = libc::AT_PHNUM;
|
||||
}
|
||||
let phnum_max = *auxv
|
||||
.get(&at_phnum)
|
||||
.ok_or(SectionDsoDebugError::CouldNotFind("AT_PHNUM in auxv"))?
|
||||
as usize;
|
||||
let phdr = *auxv
|
||||
.get(&at_phdr)
|
||||
let phnum_max =
|
||||
auxv.get_program_header_count()
|
||||
.ok_or(SectionDsoDebugError::CouldNotFind("AT_PHNUM in auxv"))? as usize;
|
||||
let phdr = auxv
|
||||
.get_program_header_address()
|
||||
.ok_or(SectionDsoDebugError::CouldNotFind("AT_PHDR in auxv"))? as usize;
|
||||
|
||||
let ph = PtraceDumper::copy_from_process(
|
||||
blamed_thread,
|
||||
phdr as *mut libc::c_void,
|
||||
SIZEOF_PHDR * phnum_max,
|
||||
)?;
|
||||
let ph = PtraceDumper::copy_from_process(blamed_thread, phdr, SIZEOF_PHDR * phnum_max)?;
|
||||
let program_headers;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
{
|
||||
|
@ -151,7 +133,7 @@ pub fn write_dso_debug_stream(
|
|||
loop {
|
||||
let dyn_data = PtraceDumper::copy_from_process(
|
||||
blamed_thread,
|
||||
(dyn_addr as usize + dynamic_length) as *mut libc::c_void,
|
||||
dyn_addr as usize + dynamic_length,
|
||||
dyn_size,
|
||||
)?;
|
||||
dynamic_length += dyn_size;
|
||||
|
@ -177,11 +159,8 @@ pub fn write_dso_debug_stream(
|
|||
// See <link.h> for a more detailed discussion of the how the dynamic
|
||||
// loader communicates with debuggers.
|
||||
|
||||
let debug_entry_data = PtraceDumper::copy_from_process(
|
||||
blamed_thread,
|
||||
r_debug as *mut libc::c_void,
|
||||
std::mem::size_of::<RDebug>(),
|
||||
)?;
|
||||
let debug_entry_data =
|
||||
PtraceDumper::copy_from_process(blamed_thread, r_debug, std::mem::size_of::<RDebug>())?;
|
||||
|
||||
// goblin::elf::Dyn doesn't have padding bytes
|
||||
let (head, body, _tail) = unsafe { debug_entry_data.align_to::<RDebug>() };
|
||||
|
@ -194,7 +173,7 @@ pub fn write_dso_debug_stream(
|
|||
while curr_map != 0 {
|
||||
let link_map_data = PtraceDumper::copy_from_process(
|
||||
blamed_thread,
|
||||
curr_map as *mut libc::c_void,
|
||||
curr_map,
|
||||
std::mem::size_of::<LinkMap>(),
|
||||
)?;
|
||||
|
||||
|
@ -218,11 +197,8 @@ pub fn write_dso_debug_stream(
|
|||
for (idx, map) in dso_vec.iter().enumerate() {
|
||||
let mut filename = String::new();
|
||||
if map.l_name > 0 {
|
||||
let filename_data = PtraceDumper::copy_from_process(
|
||||
blamed_thread,
|
||||
map.l_name as *mut libc::c_void,
|
||||
256,
|
||||
)?;
|
||||
let filename_data =
|
||||
PtraceDumper::copy_from_process(blamed_thread, map.l_name, 256)?;
|
||||
|
||||
// C - string is NULL-terminated
|
||||
if let Some(name) = filename_data.splitn(2, |x| *x == b'\0').next() {
|
||||
|
@ -257,11 +233,8 @@ pub fn write_dso_debug_stream(
|
|||
};
|
||||
|
||||
dirent.location.data_size += dynamic_length as u32;
|
||||
let dso_debug_data = PtraceDumper::copy_from_process(
|
||||
blamed_thread,
|
||||
dyn_addr as *mut libc::c_void,
|
||||
dynamic_length,
|
||||
)?;
|
||||
let dso_debug_data =
|
||||
PtraceDumper::copy_from_process(blamed_thread, dyn_addr as usize, dynamic_length)?;
|
||||
MemoryArrayWriter::write_bytes(buffer, &dso_debug_data);
|
||||
|
||||
Ok(dirent)
|
||||
|
|
|
@ -84,7 +84,7 @@ pub fn write_cpu_information(sys_info: &mut MDRawSystemInfo) -> Result<()> {
|
|||
|
||||
// special case for vendor_id
|
||||
if field == vendor_id_name && !value.is_empty() {
|
||||
vendor_id = value.to_owned();
|
||||
vendor_id = value.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::dir_section::FileWriterError;
|
||||
use crate::maps_reader::MappingInfo;
|
||||
use crate::mem_writer::MemoryWriterError;
|
||||
use crate::thread_info::Pid;
|
||||
use crate::{
|
||||
dir_section::FileWriterError, maps_reader::MappingInfo, mem_writer::MemoryWriterError, Pid,
|
||||
};
|
||||
use goblin;
|
||||
use nix::errno::Errno;
|
||||
use std::ffi::OsString;
|
||||
|
@ -9,20 +8,27 @@ use thiserror::Error;
|
|||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum InitError {
|
||||
#[error("failed to read auxv")]
|
||||
ReadAuxvFailed(crate::auxv::AuxvError),
|
||||
#[error("IO error for file {0}")]
|
||||
IOError(String, #[source] std::io::Error),
|
||||
#[error("No auxv entry found for PID {0}")]
|
||||
NoAuxvEntryFound(Pid),
|
||||
#[error("crash thread does not reference principal mapping")]
|
||||
PrincipalMappingNotReferenced,
|
||||
#[error("Failed Android specific late init")]
|
||||
AndroidLateInitError(#[from] AndroidError),
|
||||
#[error("Failed to read the page size")]
|
||||
PageSizeError(#[from] Errno),
|
||||
#[error("Ptrace does not function within the same process")]
|
||||
CannotPtraceSameProcess,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum MapsReaderError {
|
||||
#[error("Couldn't parse as ELF file")]
|
||||
ELFParsingFailed(#[from] goblin::error::Error),
|
||||
#[error("No soname found (filename: {})", .0.to_string_lossy())]
|
||||
NoSoName(OsString, #[source] ModuleReaderError),
|
||||
|
||||
// parse_from_line()
|
||||
#[error("Map entry malformed: No {0} found")]
|
||||
MapEntryMalformed(&'static str),
|
||||
|
@ -40,22 +46,6 @@ pub enum MapsReaderError {
|
|||
MmapSanityCheckFailed,
|
||||
#[error("Symlink does not match ({0} vs. {1})")]
|
||||
SymlinkError(std::path::PathBuf, std::path::PathBuf),
|
||||
|
||||
// fixup_deleted_file()
|
||||
#[error("Couldn't parse as ELF file")]
|
||||
ELFParsingFailed(#[from] goblin::error::Error),
|
||||
#[error("An anonymous mapping has no associated file")]
|
||||
AnonymousMapping,
|
||||
#[error("No soname found (filename: {})", .0.to_string_lossy())]
|
||||
NoSoName(OsString),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AuxvReaderError {
|
||||
#[error("Invalid auxv format (should not hit EOF before AT_NULL)")]
|
||||
InvalidFormat,
|
||||
#[error("IO Error")]
|
||||
IOError(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
@ -96,6 +86,16 @@ pub enum AndroidError {
|
|||
NoRelFound,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("Copy from process {child} failed (source {src}, offset: {offset}, length: {length})")]
|
||||
pub struct CopyFromProcessError {
|
||||
pub child: Pid,
|
||||
pub src: usize,
|
||||
pub offset: usize,
|
||||
pub length: usize,
|
||||
pub source: nix::Error,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DumperError {
|
||||
#[error("Failed to get PAGE_SIZE from system")]
|
||||
|
@ -106,8 +106,8 @@ pub enum DumperError {
|
|||
PtraceAttachError(Pid, #[source] nix::Error),
|
||||
#[error("nix::ptrace::detach(Pid={0}) failed")]
|
||||
PtraceDetachError(Pid, #[source] nix::Error),
|
||||
#[error("Copy from process {0} failed (source {1}, offset: {2}, length: {3})")]
|
||||
CopyFromProcessError(Pid, usize, usize, usize, #[source] nix::Error),
|
||||
#[error(transparent)]
|
||||
CopyFromProcessError(#[from] CopyFromProcessError),
|
||||
#[error("Skipped thread {0} due to it being part of the seccomp sandbox's trusted code")]
|
||||
DetachSkippedThread(Pid),
|
||||
#[error("No threads left to suspend out of {0}")]
|
||||
|
@ -118,8 +118,8 @@ pub enum DumperError {
|
|||
TryFromSliceError(#[from] std::array::TryFromSliceError),
|
||||
#[error("Couldn't parse as ELF file")]
|
||||
ELFParsingFailed(#[from] goblin::error::Error),
|
||||
#[error("No build-id found")]
|
||||
NoBuildIDFound,
|
||||
#[error("Could not read value from module")]
|
||||
ModuleReaderError(#[from] ModuleReaderError),
|
||||
#[error("Not safe to open mapping: {}", .0.to_string_lossy())]
|
||||
NotSafeToOpenMapping(OsString),
|
||||
#[error("Failed integer conversion")]
|
||||
|
@ -251,3 +251,63 @@ pub enum WriterError {
|
|||
#[error("Failed to get current timestamp when writing header of minidump")]
|
||||
SystemTimeError(#[from] std::time::SystemTimeError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ModuleReaderError {
|
||||
#[error("failed to read module file ({path}): {error}")]
|
||||
MapFile {
|
||||
path: std::path::PathBuf,
|
||||
#[source]
|
||||
error: std::io::Error,
|
||||
},
|
||||
#[error("failed to read module memory: {length} bytes at {offset}{}: {error}", .start_address.map(|addr| format!(" (start address: {addr})")).unwrap_or_default())]
|
||||
ReadModuleMemory {
|
||||
offset: u64,
|
||||
length: u64,
|
||||
start_address: Option<u64>,
|
||||
#[source]
|
||||
error: nix::Error,
|
||||
},
|
||||
#[error("failed to parse ELF memory: {0}")]
|
||||
Parsing(#[from] goblin::error::Error),
|
||||
#[error("no build id notes in program headers")]
|
||||
NoProgramHeaderNote,
|
||||
#[error("no string table available to locate note sections")]
|
||||
NoStrTab,
|
||||
#[error("no build id note sections")]
|
||||
NoSectionNote,
|
||||
#[error("the ELF data contains no program headers")]
|
||||
NoProgramHeaders,
|
||||
#[error("the ELF data contains no sections")]
|
||||
NoSections,
|
||||
#[error("the ELF data does not have a .text section from which to generate a build id")]
|
||||
NoTextSection,
|
||||
#[error(
|
||||
"failed to calculate build id\n\
|
||||
... from program headers: {program_headers}\n\
|
||||
... from sections: {section}\n\
|
||||
... from the text section: {section}"
|
||||
)]
|
||||
NoBuildId {
|
||||
program_headers: Box<Self>,
|
||||
section: Box<Self>,
|
||||
generated: Box<Self>,
|
||||
},
|
||||
#[error("no dynamic string table section")]
|
||||
NoDynStrSection,
|
||||
#[error("a string in the strtab did not have a terminating nul byte")]
|
||||
StrTabNoNulByte,
|
||||
#[error("no SONAME found in dynamic linking information")]
|
||||
NoSoNameEntry,
|
||||
#[error("no dynamic linking information section")]
|
||||
NoDynamicSection,
|
||||
#[error(
|
||||
"failed to retrieve soname\n\
|
||||
... from program headers: {program_headers}\n\
|
||||
... from sections: {section}"
|
||||
)]
|
||||
NoSoName {
|
||||
program_headers: Box<Self>,
|
||||
section: Box<Self>,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use crate::auxv_reader::AuxvType;
|
||||
use crate::auxv::AuxvType;
|
||||
use crate::errors::MapsReaderError;
|
||||
use crate::thread_info::Pid;
|
||||
use byteorder::{NativeEndian, ReadBytesExt};
|
||||
use goblin::elf;
|
||||
use memmap2::{Mmap, MmapOptions};
|
||||
use procfs_core::process::{MMPermissions, MMapPath, MemoryMaps};
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::os::unix::ffi::{OsStrExt, OsStringExt};
|
||||
use std::{fs::File, mem::size_of, path::PathBuf};
|
||||
|
||||
pub const LINUX_GATE_LIBRARY_NAME: &str = "linux-gate.so";
|
||||
|
@ -64,6 +63,17 @@ fn is_mapping_a_path(pathname: Option<&OsStr>) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sanitize mapped paths.
|
||||
///
|
||||
/// This removes a ` (deleted)` suffix, if present.
|
||||
fn sanitize_path(pathname: OsString) -> OsString {
|
||||
if let Some(bytes) = pathname.as_bytes().strip_suffix(DELETED_SUFFIX) {
|
||||
OsString::from_vec(bytes.to_owned())
|
||||
} else {
|
||||
pathname
|
||||
}
|
||||
}
|
||||
|
||||
impl MappingInfo {
|
||||
/// Return whether the `name` field is a path (contains a `/`).
|
||||
pub fn name_is_path(&self) -> bool {
|
||||
|
@ -87,7 +97,7 @@ impl MappingInfo {
|
|||
let mut offset: usize = mm.offset.try_into()?;
|
||||
|
||||
let mut pathname: Option<OsString> = match mm.pathname {
|
||||
MMapPath::Path(p) => Some(p.into()),
|
||||
MMapPath::Path(p) => Some(sanitize_path(p.into())),
|
||||
MMapPath::Heap => Some("[heap]".into()),
|
||||
MMapPath::Stack => Some("[stack]".into()),
|
||||
MMapPath::TStack(i) => Some(format!("[stack:{i}]").into()),
|
||||
|
@ -197,52 +207,6 @@ impl MappingInfo {
|
|||
Ok(mapped_file)
|
||||
}
|
||||
|
||||
/// Check whether the mapping refers to a deleted file, and if so try to find the file
|
||||
/// elsewhere and return that path.
|
||||
///
|
||||
/// Currently this only supports fixing a deleted file that was the main exe of the given
|
||||
/// `pid`.
|
||||
///
|
||||
/// Returns a tuple, where the first element is the file path (which is possibly different than
|
||||
/// `self.name`), and the second element is the original file path if a different path was
|
||||
/// used. If no mapping name exists, returns an error.
|
||||
pub fn fixup_deleted_file(&self, pid: Pid) -> Result<(OsString, Option<&OsStr>)> {
|
||||
// Check for ' (deleted)' in |path|.
|
||||
// |path| has to be at least as long as "/x (deleted)".
|
||||
let Some(path) = &self.name else {
|
||||
return Err(MapsReaderError::AnonymousMapping);
|
||||
};
|
||||
|
||||
let Some(old_path) = path.as_bytes().strip_suffix(DELETED_SUFFIX) else {
|
||||
return Ok((path.clone(), None));
|
||||
};
|
||||
|
||||
// Check |path| against the /proc/pid/exe 'symlink'.
|
||||
let exe_link = format!("/proc/{}/exe", pid);
|
||||
let link_path = std::fs::read_link(&exe_link)?;
|
||||
|
||||
// This is a no-op for now (until we want to support root_prefix for chroot-envs)
|
||||
// if (!GetMappingAbsolutePath(new_mapping, new_path))
|
||||
// return false;
|
||||
|
||||
if &link_path != path {
|
||||
return Err(MapsReaderError::SymlinkError(
|
||||
PathBuf::from(path),
|
||||
link_path,
|
||||
));
|
||||
}
|
||||
|
||||
// Check to see if someone actually named their executable 'foo (deleted)'.
|
||||
|
||||
// This makes currently no sense, as exe_link == new_path
|
||||
// if let (Some(exe_stat), Some(new_path_stat)) = (nix::stat::stat(exe_link), nix::stat::stat(new_path)) {
|
||||
// if exe_stat.st_dev == new_path_stat.st_dev && exe_stat.st_ino == new_path_stat.st_ino {
|
||||
// return Err("".into());
|
||||
// }
|
||||
// }
|
||||
Ok((exe_link.into(), Some(OsStr::from_bytes(old_path))))
|
||||
}
|
||||
|
||||
pub fn stack_has_pointer_to_mapping(&self, stack_copy: &[u8], sp_offset: usize) -> bool {
|
||||
// Loop over all stack words that would have been on the stack in
|
||||
// the target process (i.e. are word aligned, and at addresses >=
|
||||
|
@ -292,14 +256,13 @@ impl MappingInfo {
|
|||
/// Find the shared object name (SONAME) by examining the ELF information
|
||||
/// for the mapping.
|
||||
fn so_name(&self) -> Result<String> {
|
||||
use super::module_reader::{ReadFromModule, SoName};
|
||||
|
||||
let mapped_file = MappingInfo::get_mmap(&self.name, self.offset)?;
|
||||
|
||||
let elf_obj = elf::Elf::parse(&mapped_file)?;
|
||||
|
||||
let soname = elf_obj.soname.ok_or_else(|| {
|
||||
MapsReaderError::NoSoName(self.name.clone().unwrap_or_else(|| "None".into()))
|
||||
})?;
|
||||
Ok(soname.to_string())
|
||||
Ok(SoName::read_from_module((&*mapped_file).into())
|
||||
.map_err(|e| MapsReaderError::NoSoName(self.name.clone().unwrap_or_default(), e))?
|
||||
.0
|
||||
.to_string())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -309,6 +272,7 @@ impl MappingInfo {
|
|||
|
||||
pub fn get_mapping_effective_path_name_and_version(
|
||||
&self,
|
||||
soname: Option<String>,
|
||||
) -> Result<(PathBuf, String, Option<SoVersion>)> {
|
||||
let mut file_path = PathBuf::from(self.name.clone().unwrap_or_default());
|
||||
|
||||
|
@ -318,7 +282,7 @@ impl MappingInfo {
|
|||
// filesystem name of the module.
|
||||
|
||||
// Just use the filesystem name if no SONAME is present.
|
||||
let Ok(file_name) = self.so_name() else {
|
||||
let Some(file_name) = soname.or_else(|| self.so_name().ok()) else {
|
||||
// file_path := /path/to/libname.so
|
||||
// file_name := libname.so
|
||||
let file_name = file_path
|
||||
|
@ -725,7 +689,7 @@ a4840000-a4873000 rw-p 09021000 08:12 393449 /data/app/org.mozilla.firefox-1
|
|||
assert_eq!(mappings.len(), 1);
|
||||
|
||||
let (file_path, file_name, _version) = mappings[0]
|
||||
.get_mapping_effective_path_name_and_version()
|
||||
.get_mapping_effective_path_name_and_version(None)
|
||||
.expect("Couldn't get effective name for mapping");
|
||||
assert_eq!(file_name, "libmozgtk.so");
|
||||
assert_eq!(file_path, PathBuf::from("/home/martin/Documents/mozilla/devel/mozilla-central/obj/widget/gtk/mozgtk/gtk3/libmozgtk.so"));
|
||||
|
@ -763,19 +727,17 @@ a4840000-a4873000 rw-p 09021000 08:12 393449 /data/app/org.mozilla.firefox-1
|
|||
let mappings = get_mappings_for(
|
||||
"\
|
||||
10000000-20000000 r--p 00000000 00:3e 27136458 libmoz gtk.so
|
||||
20000000-30000000 r--p 00000000 00:3e 27136458 libmozgtk.so (deleted)
|
||||
30000000-40000000 r--p 00000000 00:3e 27136458 \"libmoz gtk.so (deleted)\"
|
||||
30000000-40000000 r--p 00000000 00:3e 27136458 ",
|
||||
0x7ffe091bf000,
|
||||
);
|
||||
|
||||
assert_eq!(mappings.len(), 4);
|
||||
assert_eq!(mappings.len(), 3);
|
||||
assert_eq!(mappings[0].name, Some("libmoz gtk.so".into()));
|
||||
assert_eq!(mappings[1].name, Some("libmozgtk.so (deleted)".into()));
|
||||
assert_eq!(
|
||||
mappings[2].name,
|
||||
mappings[1].name,
|
||||
Some("\"libmoz gtk.so (deleted)\"".into())
|
||||
);
|
||||
assert_eq!(mappings[3].name, None);
|
||||
assert_eq!(mappings[2].name, None);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,277 @@
|
|||
//! Functionality for reading a remote process's memory
|
||||
|
||||
use crate::{errors::CopyFromProcessError, ptrace_dumper::PtraceDumper, Pid};
|
||||
|
||||
enum Style {
|
||||
/// Uses [`process_vm_readv`](https://linux.die.net/man/2/process_vm_readv)
|
||||
/// to read the memory.
|
||||
///
|
||||
/// This is not available on old <3.2 (really, ancient) kernels, and requires
|
||||
/// the same permissions as ptrace
|
||||
VirtualMem,
|
||||
/// Reads the memory from `/proc/<pid>/mem`
|
||||
///
|
||||
/// Available on basically all versions of Linux, but could fail if the process
|
||||
/// has insufficient privileges, ie ptrace
|
||||
File(std::fs::File),
|
||||
/// Reads the memory with [ptrace (`PTRACE_PEEKDATA`)](https://man7.org/linux/man-pages/man2/ptrace.2.html)
|
||||
///
|
||||
/// Reads data one word at a time, so slow, but fairly reliable, as long as
|
||||
/// the process can be ptraced
|
||||
Ptrace,
|
||||
/// No methods succeeded, generally there isn't a case where failing a syscall
|
||||
/// will work if called again
|
||||
Unavailable {
|
||||
vmem: nix::Error,
|
||||
file: nix::Error,
|
||||
ptrace: nix::Error,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct MemReader {
|
||||
/// The pid of the child to read
|
||||
pid: nix::unistd::Pid,
|
||||
style: Option<Style>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for MemReader {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let s = match &self.style {
|
||||
Some(Style::VirtualMem) => "process_vm_readv",
|
||||
Some(Style::File(_)) => "/proc/<pid>/mem",
|
||||
Some(Style::Ptrace) => "PTRACE_PEEKDATA",
|
||||
Some(Style::Unavailable { vmem, file, ptrace }) => {
|
||||
return write!(
|
||||
f,
|
||||
"process_vm_readv: {vmem}, /proc/<pid>/mem: {file}, PTRACE_PEEKDATA: {ptrace}"
|
||||
);
|
||||
}
|
||||
None => "unknown",
|
||||
};
|
||||
|
||||
f.write_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl MemReader {
|
||||
/// Creates a [`Self`] for the specified process id, the method used will
|
||||
/// be probed for on the first access
|
||||
#[inline]
|
||||
pub fn new(pid: i32) -> Self {
|
||||
Self {
|
||||
pid: nix::unistd::Pid::from_raw(pid),
|
||||
style: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
pub fn for_virtual_mem(pid: i32) -> Self {
|
||||
Self {
|
||||
pid: nix::unistd::Pid::from_raw(pid),
|
||||
style: Some(Style::VirtualMem),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
pub fn for_file(pid: i32) -> std::io::Result<Self> {
|
||||
let file = std::fs::File::open(format!("/proc/{pid}/mem"))?;
|
||||
|
||||
Ok(Self {
|
||||
pid: nix::unistd::Pid::from_raw(pid),
|
||||
style: Some(Style::File(file)),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
pub fn for_ptrace(pid: i32) -> Self {
|
||||
Self {
|
||||
pid: nix::unistd::Pid::from_raw(pid),
|
||||
style: Some(Style::Ptrace),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_to_vec(
|
||||
&mut self,
|
||||
src: usize,
|
||||
length: std::num::NonZeroUsize,
|
||||
) -> Result<Vec<u8>, CopyFromProcessError> {
|
||||
let length = length.into();
|
||||
let layout =
|
||||
std::alloc::Layout::array::<u8>(length).map_err(|_err| CopyFromProcessError {
|
||||
child: self.pid.as_raw(),
|
||||
src,
|
||||
offset: 0,
|
||||
length,
|
||||
source: nix::errno::Errno::EINVAL,
|
||||
})?;
|
||||
|
||||
// SAFETY: we've guaranteed the layout we're allocating is valid at this point
|
||||
let output = unsafe {
|
||||
let ptr = std::alloc::alloc(layout);
|
||||
if ptr.is_null() {
|
||||
return Err(CopyFromProcessError {
|
||||
child: self.pid.as_raw(),
|
||||
src,
|
||||
offset: 0,
|
||||
length,
|
||||
source: nix::errno::Errno::ENOMEM,
|
||||
});
|
||||
}
|
||||
std::slice::from_raw_parts_mut(ptr, length)
|
||||
};
|
||||
|
||||
match self.read(src, output) {
|
||||
Ok(read) => {
|
||||
// SAFETY: we've filled initialized read bytes of our allocation block
|
||||
unsafe { Ok(Vec::from_raw_parts(output.as_mut_ptr(), read, length)) }
|
||||
}
|
||||
Err(err) => {
|
||||
// SAFETY: the pointer and layout are the same we just allocated
|
||||
unsafe {
|
||||
std::alloc::dealloc(output.as_mut_ptr(), layout);
|
||||
}
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&mut self, src: usize, dst: &mut [u8]) -> Result<usize, CopyFromProcessError> {
|
||||
if let Some(rs) = &mut self.style {
|
||||
let res = match rs {
|
||||
Style::VirtualMem => Self::vmem(self.pid, src, dst).map_err(|s| (s, 0)),
|
||||
Style::File(file) => Self::file(file, src, dst).map_err(|s| (s, 0)),
|
||||
Style::Ptrace => Self::ptrace(self.pid, src, dst),
|
||||
Style::Unavailable { ptrace, .. } => Err((*ptrace, 0)),
|
||||
};
|
||||
|
||||
return res.map_err(|(source, offset)| CopyFromProcessError {
|
||||
child: self.pid.as_raw(),
|
||||
src,
|
||||
offset,
|
||||
length: dst.len(),
|
||||
source,
|
||||
});
|
||||
}
|
||||
|
||||
// Attempt to read in order of speed
|
||||
let vmem = match Self::vmem(self.pid, src, dst) {
|
||||
Ok(len) => {
|
||||
self.style = Some(Style::VirtualMem);
|
||||
return Ok(len);
|
||||
}
|
||||
Err(err) => err,
|
||||
};
|
||||
|
||||
let file = match std::fs::File::open(format!("/proc/{}/mem", self.pid)) {
|
||||
Ok(mut file) => match Self::file(&mut file, src, dst) {
|
||||
Ok(len) => {
|
||||
self.style = Some(Style::File(file));
|
||||
return Ok(len);
|
||||
}
|
||||
Err(err) => err,
|
||||
},
|
||||
Err(err) => nix::Error::from_raw(err.raw_os_error().expect(
|
||||
"failed to open /proc/<pid>/mem and the I/O error doesn't have an OS code",
|
||||
)),
|
||||
};
|
||||
|
||||
let ptrace = match Self::ptrace(self.pid, src, dst) {
|
||||
Ok(len) => {
|
||||
self.style = Some(Style::Ptrace);
|
||||
return Ok(len);
|
||||
}
|
||||
Err((err, _)) => err,
|
||||
};
|
||||
|
||||
self.style = Some(Style::Unavailable { vmem, file, ptrace });
|
||||
Err(CopyFromProcessError {
|
||||
child: self.pid.as_raw(),
|
||||
src,
|
||||
offset: 0,
|
||||
length: dst.len(),
|
||||
source: ptrace,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn vmem(pid: nix::unistd::Pid, src: usize, dst: &mut [u8]) -> Result<usize, nix::Error> {
|
||||
let remote = &[nix::sys::uio::RemoteIoVec {
|
||||
base: src,
|
||||
len: dst.len(),
|
||||
}];
|
||||
nix::sys::uio::process_vm_readv(pid, &mut [std::io::IoSliceMut::new(dst)], remote)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn file(file: &mut std::fs::File, src: usize, dst: &mut [u8]) -> Result<usize, nix::Error> {
|
||||
use std::os::unix::fs::FileExt;
|
||||
|
||||
file.read_exact_at(dst, src as u64).map_err(|err| {
|
||||
if let Some(os) = err.raw_os_error() {
|
||||
nix::Error::from_raw(os)
|
||||
} else {
|
||||
nix::Error::E2BIG /* EOF */
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(dst.len())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn ptrace(
|
||||
pid: nix::unistd::Pid,
|
||||
src: usize,
|
||||
dst: &mut [u8],
|
||||
) -> Result<usize, (nix::Error, usize)> {
|
||||
let mut offset = 0;
|
||||
let mut chunks = dst.chunks_exact_mut(std::mem::size_of::<usize>());
|
||||
|
||||
for chunk in chunks.by_ref() {
|
||||
let word = nix::sys::ptrace::read(pid, (src + offset) as *mut std::ffi::c_void)
|
||||
.map_err(|err| (err, offset))?;
|
||||
chunk.copy_from_slice(&word.to_ne_bytes());
|
||||
offset += std::mem::size_of::<usize>();
|
||||
}
|
||||
|
||||
// I don't think there would ever be a case where we would not read on word boundaries, but just in case...
|
||||
let last = chunks.into_remainder();
|
||||
if !last.is_empty() {
|
||||
let word = nix::sys::ptrace::read(pid, (src + offset) as *mut std::ffi::c_void)
|
||||
.map_err(|err| (err, offset))?;
|
||||
last.copy_from_slice(&word.to_ne_bytes()[..last.len()]);
|
||||
}
|
||||
|
||||
Ok(dst.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl PtraceDumper {
|
||||
/// Copies a block of bytes from the target process, returning the heap
|
||||
/// allocated copy
|
||||
#[inline]
|
||||
pub fn copy_from_process(
|
||||
pid: Pid,
|
||||
src: usize,
|
||||
length: usize,
|
||||
) -> Result<Vec<u8>, crate::errors::DumperError> {
|
||||
let length = std::num::NonZeroUsize::new(length).ok_or_else(|| {
|
||||
crate::errors::DumperError::CopyFromProcessError(CopyFromProcessError {
|
||||
src,
|
||||
child: pid,
|
||||
offset: 0,
|
||||
length,
|
||||
// TODO: We should make copy_from_process also take a NonZero,
|
||||
// as EINVAL could also come from the syscalls that actually read
|
||||
// memory as well which could be confusing
|
||||
source: nix::errno::Errno::EINVAL,
|
||||
})
|
||||
})?;
|
||||
|
||||
let mut mem = MemReader::new(pid);
|
||||
Ok(mem.read_to_vec(src, length)?)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
pub use crate::linux::auxv::{AuxvType, DirectAuxvDumpInfo};
|
||||
use crate::{
|
||||
auxv::AuxvDumpInfo,
|
||||
dir_section::{DirSection, DumpBuf},
|
||||
linux::{
|
||||
app_memory::AppMemoryList,
|
||||
|
@ -8,10 +10,10 @@ use crate::{
|
|||
maps_reader::{MappingInfo, MappingList},
|
||||
ptrace_dumper::PtraceDumper,
|
||||
sections::*,
|
||||
thread_info::Pid,
|
||||
},
|
||||
mem_writer::{Buffer, MemoryArrayWriter, MemoryWriter, MemoryWriterError},
|
||||
minidump_format::*,
|
||||
Pid,
|
||||
};
|
||||
use std::{
|
||||
io::{Seek, Write},
|
||||
|
@ -42,6 +44,7 @@ pub struct MinidumpWriter {
|
|||
pub crash_context: Option<CrashContext>,
|
||||
pub crashing_thread_context: CrashingThreadContext,
|
||||
pub stop_timeout: Duration,
|
||||
pub direct_auxv_dump_info: Option<DirectAuxvDumpInfo>,
|
||||
}
|
||||
|
||||
// This doesn't work yet:
|
||||
|
@ -71,6 +74,7 @@ impl MinidumpWriter {
|
|||
crash_context: None,
|
||||
crashing_thread_context: CrashingThreadContext::None,
|
||||
stop_timeout: STOP_TIMEOUT,
|
||||
direct_auxv_dump_info: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,10 +121,30 @@ impl MinidumpWriter {
|
|||
self
|
||||
}
|
||||
|
||||
/// Directly set important Auxv info determined by the crashing process
|
||||
///
|
||||
/// Since `/proc/{pid}/auxv` can sometimes be inaccessible, the calling process should prefer to transfer this
|
||||
/// information directly using the Linux `getauxval()` call (if possible).
|
||||
///
|
||||
/// Any field that is set to `0` will be considered unset. In that case, minidump-writer might try other techniques
|
||||
/// to obtain it (like reading `/proc/{pid}/auxv`).
|
||||
pub fn set_direct_auxv_dump_info(
|
||||
&mut self,
|
||||
direct_auxv_dump_info: DirectAuxvDumpInfo,
|
||||
) -> &mut Self {
|
||||
self.direct_auxv_dump_info = Some(direct_auxv_dump_info);
|
||||
self
|
||||
}
|
||||
|
||||
/// Generates a minidump and writes to the destination provided. Returns the in-memory
|
||||
/// version of the minidump as well.
|
||||
pub fn dump(&mut self, destination: &mut (impl Write + Seek)) -> Result<Vec<u8>> {
|
||||
let mut dumper = PtraceDumper::new(self.process_id, self.stop_timeout)?;
|
||||
let auxv = self
|
||||
.direct_auxv_dump_info
|
||||
.clone()
|
||||
.map(AuxvDumpInfo::from)
|
||||
.unwrap_or_default();
|
||||
let mut dumper = PtraceDumper::new(self.process_id, self.stop_timeout, auxv)?;
|
||||
dumper.suspend_threads()?;
|
||||
dumper.late_init()?;
|
||||
|
||||
|
@ -182,7 +206,7 @@ impl MinidumpWriter {
|
|||
|
||||
let stack_copy = match PtraceDumper::copy_from_process(
|
||||
self.blamed_thread,
|
||||
valid_stack_pointer as *mut libc::c_void,
|
||||
valid_stack_pointer,
|
||||
stack_len,
|
||||
) {
|
||||
Ok(x) => x,
|
||||
|
|
|
@ -0,0 +1,622 @@
|
|||
use crate::errors::ModuleReaderError as Error;
|
||||
use crate::mem_reader::MemReader;
|
||||
use crate::minidump_format::GUID;
|
||||
use goblin::{
|
||||
container::{Container, Ctx, Endian},
|
||||
elf,
|
||||
};
|
||||
use std::{borrow::Cow, ffi::CStr};
|
||||
|
||||
type Buf<'buf> = Cow<'buf, [u8]>;
|
||||
|
||||
const NOTE_SECTION_NAME: &[u8] = b".note.gnu.build-id\0";
|
||||
|
||||
pub struct ProcessReader {
|
||||
inner: MemReader,
|
||||
start_address: u64,
|
||||
}
|
||||
|
||||
impl ProcessReader {
|
||||
pub fn new(pid: i32, start_address: usize) -> Self {
|
||||
Self {
|
||||
inner: MemReader::new(pid),
|
||||
start_address: start_address as u64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ProcessMemory<'buf> {
|
||||
Slice(&'buf [u8]),
|
||||
Process(ProcessReader),
|
||||
}
|
||||
|
||||
impl<'buf> From<&'buf [u8]> for ProcessMemory<'buf> {
|
||||
fn from(value: &'buf [u8]) -> Self {
|
||||
Self::Slice(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'buf> From<ProcessReader> for ProcessMemory<'buf> {
|
||||
fn from(value: ProcessReader) -> Self {
|
||||
Self::Process(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'buf> ProcessMemory<'buf> {
|
||||
#[inline]
|
||||
fn read(&mut self, offset: u64, length: u64) -> Result<Buf<'buf>, Error> {
|
||||
let error = move |start_address, error| Error::ReadModuleMemory {
|
||||
start_address,
|
||||
offset,
|
||||
length,
|
||||
error,
|
||||
};
|
||||
|
||||
match self {
|
||||
Self::Process(pr) => {
|
||||
let error = |e| error(Some(pr.start_address), e);
|
||||
let len = std::num::NonZeroUsize::new(length as usize)
|
||||
.ok_or_else(|| error(nix::Error::EINVAL))?;
|
||||
let proc_offset = pr
|
||||
.start_address
|
||||
.checked_add(offset)
|
||||
.ok_or_else(|| error(nix::Error::EOVERFLOW))?;
|
||||
pr.inner
|
||||
.read_to_vec(proc_offset as _, len)
|
||||
.map(Cow::Owned)
|
||||
.map_err(|err| error(err.source))
|
||||
}
|
||||
Self::Slice(s) => {
|
||||
let error = |e| error(None, e);
|
||||
let end = offset
|
||||
.checked_add(length)
|
||||
.ok_or_else(|| error(nix::Error::EOVERFLOW))?;
|
||||
s.get(offset as usize..end as usize)
|
||||
.map(Cow::Borrowed)
|
||||
.ok_or_else(|| error(nix::Error::EACCES))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the absolute address of the specified relative address
|
||||
#[inline]
|
||||
fn absolute(&self, addr: u64) -> u64 {
|
||||
let Self::Process(pr) = self else {
|
||||
return addr;
|
||||
};
|
||||
addr.checked_sub(pr.start_address).unwrap_or(addr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_process_memory(&self) -> bool {
|
||||
matches!(self, Self::Process(_))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_executable_section(header: &elf::SectionHeader) -> bool {
|
||||
header.sh_type == elf::section_header::SHT_PROGBITS
|
||||
&& header.sh_flags & u64::from(elf::section_header::SHF_ALLOC) != 0
|
||||
&& header.sh_flags & u64::from(elf::section_header::SHF_EXECINSTR) != 0
|
||||
}
|
||||
|
||||
/// Return bytes to use as a build id, computed by hashing the given data.
|
||||
///
|
||||
/// This provides `size_of::<GUID>` bytes to keep identifiers produced by this function compatible
|
||||
/// with other build ids.
|
||||
fn build_id_from_bytes(data: &[u8]) -> Vec<u8> {
|
||||
// Only provide mem::size_of(MDGUID) bytes to keep identifiers produced by this
|
||||
// function backwards-compatible.
|
||||
data.chunks(std::mem::size_of::<GUID>()).fold(
|
||||
vec![0u8; std::mem::size_of::<GUID>()],
|
||||
|mut bytes, chunk| {
|
||||
bytes
|
||||
.iter_mut()
|
||||
.zip(chunk.iter())
|
||||
.for_each(|(b, c)| *b ^= *c);
|
||||
bytes
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// `name` should be null-terminated
|
||||
fn section_header_with_name<'sc>(
|
||||
section_headers: &'sc elf::SectionHeaders,
|
||||
strtab_index: usize,
|
||||
name: &[u8],
|
||||
module_memory: &mut ProcessMemory<'_>,
|
||||
) -> Result<Option<&'sc elf::SectionHeader>, Error> {
|
||||
let strtab_section_header = section_headers
|
||||
.get(strtab_index)
|
||||
.and_then(|hdr| (hdr.sh_type == elf::section_header::SHT_STRTAB).then_some(hdr))
|
||||
.ok_or(Error::NoStrTab)?;
|
||||
|
||||
for header in section_headers {
|
||||
let sh_name = header.sh_name as u64;
|
||||
if sh_name >= strtab_section_header.sh_size {
|
||||
log::warn!("invalid sh_name offset for {:?}", name);
|
||||
continue;
|
||||
}
|
||||
if sh_name + name.len() as u64 >= strtab_section_header.sh_size {
|
||||
// This can't be a match.
|
||||
continue;
|
||||
}
|
||||
let n = module_memory.read(strtab_section_header.sh_offset + sh_name, name.len() as u64)?;
|
||||
if name == &*n {
|
||||
return Ok(Some(header));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Types which can be read from ProcessMemory.
|
||||
pub trait ReadFromModule: Sized {
|
||||
fn read_from_module(module_memory: ProcessMemory<'_>) -> Result<Self, Error>;
|
||||
|
||||
fn read_from_file(path: &std::path::Path) -> Result<Self, Error> {
|
||||
let map = std::fs::File::open(path)
|
||||
// Safety: the file is an executable binary (very likely read-only), and won't be changed.
|
||||
.and_then(|file| unsafe { memmap2::Mmap::map(&file) })
|
||||
.map_err(|error| Error::MapFile {
|
||||
path: path.to_owned(),
|
||||
error,
|
||||
})?;
|
||||
Self::read_from_module(ProcessMemory::Slice(&map))
|
||||
}
|
||||
}
|
||||
|
||||
/// The module build id.
|
||||
pub struct BuildId(pub Vec<u8>);
|
||||
|
||||
impl ReadFromModule for BuildId {
|
||||
fn read_from_module(module_memory: ProcessMemory<'_>) -> Result<Self, Error> {
|
||||
let mut reader = ModuleReader::new(module_memory)?;
|
||||
let program_headers = match reader.build_id_from_program_headers() {
|
||||
Ok(v) => return Ok(BuildId(v)),
|
||||
Err(e) => Box::new(e),
|
||||
};
|
||||
let section = match reader.build_id_from_section() {
|
||||
Ok(v) => return Ok(BuildId(v)),
|
||||
Err(e) => Box::new(e),
|
||||
};
|
||||
let generated = match reader.build_id_generate_from_text() {
|
||||
Ok(v) => return Ok(BuildId(v)),
|
||||
Err(e) => Box::new(e),
|
||||
};
|
||||
Err(Error::NoBuildId {
|
||||
program_headers,
|
||||
section,
|
||||
generated,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct DynIter<'a> {
|
||||
data: &'a [u8],
|
||||
offset: usize,
|
||||
ctx: Ctx,
|
||||
}
|
||||
|
||||
impl<'a> DynIter<'a> {
|
||||
pub fn new(data: &'a [u8], ctx: Ctx) -> Self {
|
||||
DynIter {
|
||||
data,
|
||||
offset: 0,
|
||||
ctx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for DynIter<'a> {
|
||||
type Item = Result<elf::dynamic::Dyn, Error>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
use scroll::Pread;
|
||||
let dyn_: elf::dynamic::Dyn = match self.data.gread_with(&mut self.offset, self.ctx) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return Some(Err(e.into())),
|
||||
};
|
||||
if dyn_.d_tag == elf::dynamic::DT_NULL {
|
||||
None
|
||||
} else {
|
||||
Some(Ok(dyn_))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The module SONAME.
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct SoName(pub String);
|
||||
|
||||
impl ReadFromModule for SoName {
|
||||
fn read_from_module(module_memory: ProcessMemory<'_>) -> Result<Self, Error> {
|
||||
let mut reader = ModuleReader::new(module_memory)?;
|
||||
let program_headers = match reader.soname_from_program_headers() {
|
||||
Ok(v) => return Ok(SoName(v)),
|
||||
Err(e) => Box::new(e),
|
||||
};
|
||||
let section = match reader.soname_from_sections() {
|
||||
Ok(v) => return Ok(SoName(v)),
|
||||
Err(e) => Box::new(e),
|
||||
};
|
||||
Err(Error::NoSoName {
|
||||
program_headers,
|
||||
section,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ModuleReader<'buf> {
|
||||
module_memory: ProcessMemory<'buf>,
|
||||
header: elf::Header,
|
||||
context: Ctx,
|
||||
}
|
||||
|
||||
impl<'buf> ModuleReader<'buf> {
|
||||
pub fn new(mut module_memory: ProcessMemory<'buf>) -> Result<Self, Error> {
|
||||
// We could use `Ctx::default()` (which defaults to the native system), however to be extra
|
||||
// permissive we'll just use a 64-bit ("Big") context which would result in the largest
|
||||
// possible header size.
|
||||
let header_size = elf::Header::size(Ctx::new(Container::Big, Endian::default()));
|
||||
let header_data = module_memory.read(0, header_size as u64)?;
|
||||
let header = elf::Elf::parse_header(&header_data)?;
|
||||
let context = Ctx::new(header.container()?, header.endianness()?);
|
||||
|
||||
Ok(Self {
|
||||
module_memory,
|
||||
header,
|
||||
context,
|
||||
})
|
||||
}
|
||||
|
||||
/// Read the SONAME using program headers to locate dynamic library information.
|
||||
pub fn soname_from_program_headers(&mut self) -> Result<String, Error> {
|
||||
let program_headers = self.read_program_headers()?;
|
||||
|
||||
let dynamic_segment_header = program_headers
|
||||
.iter()
|
||||
.find(|h| h.p_type == elf::program_header::PT_DYNAMIC)
|
||||
.ok_or(Error::NoDynamicSection)?;
|
||||
|
||||
let dynamic_section = self.read_segment(dynamic_segment_header)?;
|
||||
|
||||
let mut soname_strtab_offset = None;
|
||||
let mut strtab_addr = None;
|
||||
let mut strtab_size = None;
|
||||
for dyn_ in DynIter::new(&dynamic_section, self.context) {
|
||||
let dyn_ = dyn_?;
|
||||
match dyn_.d_tag {
|
||||
elf::dynamic::DT_SONAME => soname_strtab_offset = Some(dyn_.d_val),
|
||||
elf::dynamic::DT_STRTAB => strtab_addr = Some(dyn_.d_val),
|
||||
elf::dynamic::DT_STRSZ => strtab_size = Some(dyn_.d_val),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
match (strtab_addr, strtab_size, soname_strtab_offset) {
|
||||
(None, _, _) | (_, None, _) => Err(Error::NoDynStrSection),
|
||||
(_, _, None) => Err(Error::NoSoNameEntry),
|
||||
(Some(addr), Some(size), Some(offset)) => {
|
||||
// If loaded in memory, the address will be altered to be absolute.
|
||||
if offset < size {
|
||||
self.read_name_from_strtab(self.module_memory.absolute(addr), size, offset)
|
||||
} else {
|
||||
log::warn!("soname strtab offset ({offset}) exceeds strtab size ({size})");
|
||||
Err(Error::NoSoNameEntry)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read the SONAME using section headers to locate dynamic library information.
|
||||
pub fn soname_from_sections(&mut self) -> Result<String, Error> {
|
||||
let section_headers = self.read_section_headers()?;
|
||||
|
||||
let dynamic_section_header = section_headers
|
||||
.iter()
|
||||
.find(|h| h.sh_type == elf::section_header::SHT_DYNAMIC)
|
||||
.ok_or(Error::NoDynamicSection)?;
|
||||
|
||||
let dynstr_section_header =
|
||||
match section_headers.get(dynamic_section_header.sh_link as usize) {
|
||||
Some(header) if header.sh_type == elf::section_header::SHT_STRTAB => header,
|
||||
_ => section_header_with_name(
|
||||
§ion_headers,
|
||||
self.header.e_shstrndx as usize,
|
||||
b".dynstr\0",
|
||||
&mut self.module_memory,
|
||||
)?
|
||||
.ok_or(Error::NoDynStrSection)?,
|
||||
};
|
||||
|
||||
let dynamic_section = self.module_memory.read(
|
||||
self.section_offset(dynamic_section_header),
|
||||
dynamic_section_header.sh_size,
|
||||
)?;
|
||||
|
||||
for dyn_ in DynIter::new(&dynamic_section, self.context) {
|
||||
let dyn_ = dyn_?;
|
||||
if dyn_.d_tag == elf::dynamic::DT_SONAME {
|
||||
let name_offset = dyn_.d_val;
|
||||
if name_offset < dynstr_section_header.sh_size {
|
||||
return self.read_name_from_strtab(
|
||||
self.section_offset(dynstr_section_header),
|
||||
dynstr_section_header.sh_size,
|
||||
name_offset,
|
||||
);
|
||||
} else {
|
||||
log::warn!(
|
||||
"soname offset ({name_offset}) exceeds dynstr section size ({})",
|
||||
dynstr_section_header.sh_size
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::NoSoNameEntry)
|
||||
}
|
||||
|
||||
/// Read the build id from a program header note.
|
||||
pub fn build_id_from_program_headers(&mut self) -> Result<Vec<u8>, Error> {
|
||||
let program_headers = self.read_program_headers()?;
|
||||
for header in program_headers {
|
||||
if header.p_type != elf::program_header::PT_NOTE {
|
||||
continue;
|
||||
}
|
||||
if let Ok(Some(result)) =
|
||||
self.find_build_id_note(header.p_offset, header.p_filesz, header.p_align)
|
||||
{
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
Err(Error::NoProgramHeaderNote)
|
||||
}
|
||||
|
||||
/// Read the build id from a notes section.
|
||||
pub fn build_id_from_section(&mut self) -> Result<Vec<u8>, Error> {
|
||||
let section_headers = self.read_section_headers()?;
|
||||
|
||||
let header = section_header_with_name(
|
||||
§ion_headers,
|
||||
self.header.e_shstrndx as usize,
|
||||
NOTE_SECTION_NAME,
|
||||
&mut self.module_memory,
|
||||
)?
|
||||
.ok_or(Error::NoSectionNote)?;
|
||||
|
||||
match self.find_build_id_note(header.sh_offset, header.sh_size, header.sh_addralign) {
|
||||
Ok(Some(v)) => Ok(v),
|
||||
Ok(None) => Err(Error::NoSectionNote),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a build id by hashing the first page of the text section.
|
||||
pub fn build_id_generate_from_text(&mut self) -> Result<Vec<u8>, Error> {
|
||||
let Some(text_header) = self
|
||||
.read_section_headers()?
|
||||
.into_iter()
|
||||
.find(is_executable_section)
|
||||
else {
|
||||
return Err(Error::NoTextSection);
|
||||
};
|
||||
|
||||
// Take at most one page of the text section (we assume page size is 4096 bytes).
|
||||
let len = std::cmp::min(4096, text_header.sh_size);
|
||||
let text_data = self.module_memory.read(text_header.sh_offset, len)?;
|
||||
Ok(build_id_from_bytes(&text_data))
|
||||
}
|
||||
|
||||
fn read_segment(&mut self, header: &elf::ProgramHeader) -> Result<Buf<'buf>, Error> {
|
||||
let (offset, size) = if self.module_memory.is_process_memory() {
|
||||
(header.p_vaddr, header.p_memsz)
|
||||
} else {
|
||||
(header.p_offset, header.p_filesz)
|
||||
};
|
||||
|
||||
self.module_memory.read(offset, size)
|
||||
}
|
||||
|
||||
fn read_name_from_strtab(
|
||||
&mut self,
|
||||
strtab_offset: u64,
|
||||
strtab_size: u64,
|
||||
name_offset: u64,
|
||||
) -> Result<String, Error> {
|
||||
assert!(name_offset < strtab_size);
|
||||
let name = self
|
||||
.module_memory
|
||||
.read(strtab_offset + name_offset, strtab_size - name_offset)?;
|
||||
return CStr::from_bytes_until_nul(&name)
|
||||
.map(|s| s.to_string_lossy().into_owned())
|
||||
.map_err(|_| Error::StrTabNoNulByte);
|
||||
}
|
||||
|
||||
fn section_offset(&self, header: &elf::SectionHeader) -> u64 {
|
||||
if self.module_memory.is_process_memory() {
|
||||
header.sh_addr
|
||||
} else {
|
||||
header.sh_offset
|
||||
}
|
||||
}
|
||||
|
||||
fn read_program_headers(&mut self) -> Result<elf::ProgramHeaders, Error> {
|
||||
if self.header.e_phoff == 0 {
|
||||
return Err(Error::NoProgramHeaders);
|
||||
}
|
||||
let program_headers_data = self.module_memory.read(
|
||||
self.header.e_phoff,
|
||||
self.header.e_phentsize as u64 * self.header.e_phnum as u64,
|
||||
)?;
|
||||
let program_headers = elf::ProgramHeader::parse(
|
||||
&program_headers_data,
|
||||
0,
|
||||
self.header.e_phnum as usize,
|
||||
self.context,
|
||||
)?;
|
||||
Ok(program_headers)
|
||||
}
|
||||
|
||||
fn read_section_headers(&mut self) -> Result<elf::SectionHeaders, Error> {
|
||||
if self.header.e_shoff == 0 {
|
||||
return Err(Error::NoSections);
|
||||
}
|
||||
|
||||
let section_headers_data = self.module_memory.read(
|
||||
self.header.e_shoff,
|
||||
self.header.e_shentsize as u64 * self.header.e_shnum as u64,
|
||||
)?;
|
||||
// Use `parse_from` rather than `parse`, which allows a 0 offset.
|
||||
let section_headers = elf::SectionHeader::parse_from(
|
||||
§ion_headers_data,
|
||||
0,
|
||||
self.header.e_shnum as usize,
|
||||
self.context,
|
||||
)?;
|
||||
Ok(section_headers)
|
||||
}
|
||||
|
||||
fn find_build_id_note(
|
||||
&mut self,
|
||||
offset: u64,
|
||||
size: u64,
|
||||
alignment: u64,
|
||||
) -> Result<Option<Vec<u8>>, Error> {
|
||||
let notes = self.module_memory.read(offset, size)?;
|
||||
for note in (elf::note::NoteDataIterator {
|
||||
data: ¬es,
|
||||
// Note that `NoteDataIterator::size` is poorly named, it is actually an end offset. In
|
||||
// this case since our start offset is 0 we still set it to the size.
|
||||
size: size as usize,
|
||||
offset: 0,
|
||||
ctx: (alignment as usize, self.context),
|
||||
}) {
|
||||
let Ok(note) = note else { break };
|
||||
if note.name == "GNU" && note.n_type == elf::note::NT_GNU_BUILD_ID {
|
||||
return Ok(Some(note.desc.to_owned()));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
/// This is a small (but valid) 64-bit little-endian elf executable with the following layout:
|
||||
/// * ELF header
|
||||
/// * program header: text segment
|
||||
/// * program header: note
|
||||
/// * program header: dynamic
|
||||
/// * section header: null
|
||||
/// * section header: .text
|
||||
/// * section header: .note.gnu.build-id
|
||||
/// * section header: .shstrtab
|
||||
/// * section header: .dynamic
|
||||
/// * section header: .dynstr
|
||||
/// * note header (build id note)
|
||||
/// * shstrtab
|
||||
/// * dynamic (SONAME/STRTAB/STRSZ)
|
||||
/// * dynstr (SONAME string = libfoo.so.1)
|
||||
/// * program (calls exit(0))
|
||||
const TINY_ELF: &[u8] = &[
|
||||
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x03, 0x40, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x03, 0x00, 0x40, 0x00,
|
||||
0x06, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0a, 0x03, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x03, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x68, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xbd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x02, 0x40,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x03, 0x40,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x68, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x02, 0x40, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xbd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x02,
|
||||
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x4e,
|
||||
0x55, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
|
||||
0x0e, 0x0f, 0x10, 0x00, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x00, 0x2e, 0x6e, 0x6f, 0x74, 0x65,
|
||||
0x2e, 0x67, 0x6e, 0x75, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x2d, 0x69, 0x64, 0x00, 0x2e,
|
||||
0x73, 0x68, 0x73, 0x74, 0x72, 0x74, 0x61, 0x62, 0x00, 0x2e, 0x64, 0x79, 0x6e, 0x61, 0x6d,
|
||||
0x69, 0x63, 0x00, 0x2e, 0x64, 0x79, 0x6e, 0x73, 0x74, 0x72, 0x00, 0x0e, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x6c, 0x69, 0x62, 0x66, 0x6f, 0x6f, 0x2e, 0x73, 0x6f, 0x2e, 0x31, 0x00, 0x6a, 0x3c,
|
||||
0x58, 0x31, 0xff, 0x0f, 0x05,
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn build_id_program_headers() {
|
||||
let mut reader = ModuleReader::new(TINY_ELF.into()).unwrap();
|
||||
let id = reader.build_id_from_program_headers().unwrap();
|
||||
assert_eq!(
|
||||
id,
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_id_section() {
|
||||
let mut reader = ModuleReader::new(TINY_ELF.into()).unwrap();
|
||||
let id = reader.build_id_from_section().unwrap();
|
||||
assert_eq!(
|
||||
id,
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_id_text_hash() {
|
||||
let mut reader = ModuleReader::new(TINY_ELF.into()).unwrap();
|
||||
let id = reader.build_id_generate_from_text().unwrap();
|
||||
assert_eq!(
|
||||
id,
|
||||
vec![0x6a, 0x3c, 0x58, 0x31, 0xff, 0x0f, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn soname_program_headers() {
|
||||
let mut reader = ModuleReader::new(TINY_ELF.into()).unwrap();
|
||||
let soname = reader.soname_from_program_headers().unwrap();
|
||||
assert_eq!(soname, "libfoo.so.1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn soname_section() {
|
||||
let mut reader = ModuleReader::new(TINY_ELF.into()).unwrap();
|
||||
let soname = reader.soname_from_sections().unwrap();
|
||||
assert_eq!(soname, "libfoo.so.1");
|
||||
}
|
||||
}
|
|
@ -1,18 +1,15 @@
|
|||
#[cfg(target_os = "android")]
|
||||
use crate::linux::android::late_process_mappings;
|
||||
use crate::linux::{
|
||||
auxv::AuxvDumpInfo,
|
||||
errors::{DumperError, InitError, ThreadInfoError},
|
||||
maps_reader::MappingInfo,
|
||||
module_reader,
|
||||
thread_info::ThreadInfo,
|
||||
Pid,
|
||||
};
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
use crate::thread_info;
|
||||
use crate::{
|
||||
linux::{
|
||||
auxv_reader::{AuxvType, ProcfsAuxvIter},
|
||||
errors::{DumperError, InitError, ThreadInfoError},
|
||||
maps_reader::MappingInfo,
|
||||
thread_info::{Pid, ThreadInfo},
|
||||
LINUX_GATE_LIBRARY_NAME,
|
||||
},
|
||||
minidump_format::GUID,
|
||||
};
|
||||
use goblin::elf;
|
||||
use nix::{
|
||||
errno::Errno,
|
||||
sys::{ptrace, signal, wait},
|
||||
|
@ -22,9 +19,6 @@ use procfs_core::{
|
|||
FromRead, ProcError,
|
||||
};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ffi::c_void,
|
||||
io::BufReader,
|
||||
path,
|
||||
result::Result,
|
||||
time::{Duration, Instant},
|
||||
|
@ -41,7 +35,7 @@ pub struct PtraceDumper {
|
|||
pub pid: Pid,
|
||||
threads_suspended: bool,
|
||||
pub threads: Vec<Thread>,
|
||||
pub auxv: HashMap<AuxvType, AuxvType>,
|
||||
pub auxv: AuxvDumpInfo,
|
||||
pub mappings: Vec<MappingInfo>,
|
||||
pub page_size: usize,
|
||||
}
|
||||
|
@ -93,14 +87,17 @@ fn ptrace_detach(child: Pid) -> Result<(), DumperError> {
|
|||
}
|
||||
|
||||
impl PtraceDumper {
|
||||
/// Constructs a dumper for extracting information of a given process
|
||||
/// with a process ID of |pid|.
|
||||
pub fn new(pid: Pid, stop_timeout: Duration) -> Result<Self, InitError> {
|
||||
let mut dumper = PtraceDumper {
|
||||
/// Constructs a dumper for extracting information from the specified process id
|
||||
pub fn new(pid: Pid, stop_timeout: Duration, auxv: AuxvDumpInfo) -> Result<Self, InitError> {
|
||||
if pid == std::process::id() as _ {
|
||||
return Err(InitError::CannotPtraceSameProcess);
|
||||
}
|
||||
|
||||
let mut dumper = Self {
|
||||
pid,
|
||||
threads_suspended: false,
|
||||
threads: Vec::new(),
|
||||
auxv: HashMap::new(),
|
||||
auxv,
|
||||
mappings: Vec::new(),
|
||||
page_size: 0,
|
||||
};
|
||||
|
@ -114,7 +111,11 @@ impl PtraceDumper {
|
|||
if let Err(e) = self.stop_process(stop_timeout) {
|
||||
log::warn!("failed to stop process {}: {e}", self.pid);
|
||||
}
|
||||
self.read_auxv()?;
|
||||
|
||||
if let Err(e) = self.auxv.try_filling_missing_info(self.pid) {
|
||||
log::warn!("failed trying to fill in missing auxv info: {e}");
|
||||
}
|
||||
|
||||
self.enumerate_threads()?;
|
||||
self.enumerate_mappings()?;
|
||||
self.page_size = nix::unistd::sysconf(nix::unistd::SysconfVar::PAGE_SIZE)?
|
||||
|
@ -133,27 +134,6 @@ impl PtraceDumper {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Copies content of |length| bytes from a given process |child|,
|
||||
/// starting from |src|, into |dest|. This method uses ptrace to extract
|
||||
/// the content from the target process. Always returns true.
|
||||
pub fn copy_from_process(
|
||||
child: Pid,
|
||||
src: *mut c_void,
|
||||
num_of_bytes: usize,
|
||||
) -> Result<Vec<u8>, DumperError> {
|
||||
use DumperError::CopyFromProcessError as CFPE;
|
||||
let pid = nix::unistd::Pid::from_raw(child);
|
||||
let mut res = Vec::new();
|
||||
let mut idx = 0usize;
|
||||
while idx < num_of_bytes {
|
||||
let word = ptrace::read(pid, (src as usize + idx) as *mut c_void)
|
||||
.map_err(|e| CFPE(child, src as usize, idx, num_of_bytes, e))?;
|
||||
res.append(&mut word.to_ne_bytes().to_vec());
|
||||
idx += std::mem::size_of::<libc::c_long>();
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Suspends a thread by attaching to it.
|
||||
pub fn suspend_thread(child: Pid) -> Result<(), DumperError> {
|
||||
use DumperError::PtraceAttachError as AttachErr;
|
||||
|
@ -163,8 +143,28 @@ impl PtraceDumper {
|
|||
ptrace::attach(pid).map_err(|e| AttachErr(child, e))?;
|
||||
loop {
|
||||
match wait::waitpid(pid, Some(wait::WaitPidFlag::__WALL)) {
|
||||
Ok(_) => break,
|
||||
Err(_e @ Errno::EINTR) => continue,
|
||||
Ok(status) => {
|
||||
let wait::WaitStatus::Stopped(_, status) = status else {
|
||||
return Err(DumperError::WaitPidError(
|
||||
child,
|
||||
nix::errno::Errno::UnknownErrno,
|
||||
));
|
||||
};
|
||||
|
||||
// Any signal will stop the thread, make sure it is SIGSTOP. Otherwise, this
|
||||
// signal will be delivered after PTRACE_DETACH, and the thread will enter
|
||||
// the "T (stopped)" state.
|
||||
if status == nix::sys::signal::SIGSTOP {
|
||||
break;
|
||||
}
|
||||
|
||||
// Signals other than SIGSTOP that are received need to be reinjected,
|
||||
// or they will otherwise get lost.
|
||||
if let Err(err) = ptrace::cont(pid, status) {
|
||||
return Err(DumperError::WaitPidError(child, err));
|
||||
}
|
||||
}
|
||||
Err(Errno::EINTR) => continue,
|
||||
Err(e) => {
|
||||
ptrace_detach(child)?;
|
||||
return Err(DumperError::WaitPidError(child, e));
|
||||
|
@ -300,25 +300,6 @@ impl PtraceDumper {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn read_auxv(&mut self) -> Result<(), InitError> {
|
||||
let filename = format!("/proc/{}/auxv", self.pid);
|
||||
let auxv_path = path::PathBuf::from(&filename);
|
||||
let auxv_file =
|
||||
std::fs::File::open(auxv_path).map_err(|e| InitError::IOError(filename, e))?;
|
||||
let input = BufReader::new(auxv_file);
|
||||
let reader = ProcfsAuxvIter::new(input);
|
||||
self.auxv = reader
|
||||
.filter_map(Result::ok)
|
||||
.map(|x| (x.key, x.value))
|
||||
.collect();
|
||||
|
||||
if self.auxv.is_empty() {
|
||||
Err(InitError::NoAuxvEntryFound(self.pid))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn enumerate_mappings(&mut self) -> Result<(), InitError> {
|
||||
// linux_gate_loc is the beginning of the kernel's mapping of
|
||||
// linux-gate.so in the process. It doesn't actually show up in the
|
||||
|
@ -327,21 +308,11 @@ impl PtraceDumper {
|
|||
// case its entry when creating the list of mappings.
|
||||
// See http://www.trilithium.com/johan/2005/08/linux-gate/ for more
|
||||
// information.
|
||||
let linux_gate_loc = *self.auxv.get(&AT_SYSINFO_EHDR).unwrap_or(&0);
|
||||
let linux_gate_loc = self.auxv.get_linux_gate_address().unwrap_or_default();
|
||||
// Although the initial executable is usually the first mapping, it's not
|
||||
// guaranteed (see http://crosbug.com/25355); therefore, try to use the
|
||||
// actual entry point to find the mapping.
|
||||
let at_entry;
|
||||
#[cfg(any(target_arch = "arm", all(target_os = "android", target_arch = "x86")))]
|
||||
{
|
||||
at_entry = 9;
|
||||
}
|
||||
#[cfg(not(any(target_arch = "arm", all(target_os = "android", target_arch = "x86"))))]
|
||||
{
|
||||
at_entry = libc::AT_ENTRY;
|
||||
}
|
||||
|
||||
let entry_point_loc = *self.auxv.get(&at_entry).unwrap_or(&0);
|
||||
let entry_point_loc = self.auxv.get_entry_address().unwrap_or_default();
|
||||
let filename = format!("/proc/{}/maps", self.pid);
|
||||
let errmap = |e| InitError::IOError(filename.clone(), e);
|
||||
let maps_path = path::PathBuf::from(&filename);
|
||||
|
@ -562,111 +533,21 @@ impl PtraceDumper {
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_build_id<'data>(
|
||||
elf_obj: &elf::Elf<'data>,
|
||||
mem_slice: &'data [u8],
|
||||
) -> Option<&'data [u8]> {
|
||||
if let Some(mut notes) = elf_obj.iter_note_headers(mem_slice) {
|
||||
while let Some(Ok(note)) = notes.next() {
|
||||
if (note.name == "GNU") && (note.n_type == elf::note::NT_GNU_BUILD_ID) {
|
||||
return Some(note.desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(mut notes) = elf_obj.iter_note_sections(mem_slice, Some(".note.gnu.build-id")) {
|
||||
while let Some(Ok(note)) = notes.next() {
|
||||
if (note.name == "GNU") && (note.n_type == elf::note::NT_GNU_BUILD_ID) {
|
||||
return Some(note.desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn elf_file_identifier_from_mapped_file(mem_slice: &[u8]) -> Result<Vec<u8>, DumperError> {
|
||||
let elf_obj = elf::Elf::parse(mem_slice)?;
|
||||
|
||||
if let Some(build_id) = Self::parse_build_id(&elf_obj, mem_slice) {
|
||||
// Look for a build id note first.
|
||||
Ok(build_id.to_vec())
|
||||
} else {
|
||||
// Fall back on hashing the first page of the text section.
|
||||
|
||||
// Attempt to locate the .text section of an ELF binary and generate
|
||||
// a simple hash by XORing the first page worth of bytes into |result|.
|
||||
for section in elf_obj.section_headers {
|
||||
if section.sh_type != elf::section_header::SHT_PROGBITS {
|
||||
continue;
|
||||
}
|
||||
if section.sh_flags & u64::from(elf::section_header::SHF_ALLOC) != 0
|
||||
&& section.sh_flags & u64::from(elf::section_header::SHF_EXECINSTR) != 0
|
||||
{
|
||||
let text_section =
|
||||
&mem_slice[section.sh_offset as usize..][..section.sh_size as usize];
|
||||
// Only provide mem::size_of(MDGUID) bytes to keep identifiers produced by this
|
||||
// function backwards-compatible.
|
||||
let max_len = std::cmp::min(text_section.len(), 4096);
|
||||
let mut result = vec![0u8; std::mem::size_of::<GUID>()];
|
||||
let mut offset = 0;
|
||||
while offset < max_len {
|
||||
for idx in 0..std::mem::size_of::<GUID>() {
|
||||
if offset + idx >= text_section.len() {
|
||||
break;
|
||||
}
|
||||
result[idx] ^= text_section[offset + idx];
|
||||
}
|
||||
offset += std::mem::size_of::<GUID>();
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
Err(DumperError::NoBuildIDFound)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn elf_identifier_for_mapping_index(&mut self, idx: usize) -> Result<Vec<u8>, DumperError> {
|
||||
pub fn from_process_memory_for_index<T: module_reader::ReadFromModule>(
|
||||
&mut self,
|
||||
idx: usize,
|
||||
) -> Result<T, DumperError> {
|
||||
assert!(idx < self.mappings.len());
|
||||
|
||||
Self::elf_identifier_for_mapping(&mut self.mappings[idx], self.pid)
|
||||
Self::from_process_memory_for_mapping(&self.mappings[idx], self.pid)
|
||||
}
|
||||
|
||||
pub fn elf_identifier_for_mapping(
|
||||
mapping: &mut MappingInfo,
|
||||
pub fn from_process_memory_for_mapping<T: module_reader::ReadFromModule>(
|
||||
mapping: &MappingInfo,
|
||||
pid: Pid,
|
||||
) -> Result<Vec<u8>, DumperError> {
|
||||
if !MappingInfo::is_mapped_file_safe_to_open(&mapping.name) {
|
||||
return Err(DumperError::NotSafeToOpenMapping(
|
||||
mapping.name.clone().unwrap_or_default(),
|
||||
));
|
||||
}
|
||||
|
||||
// Special-case linux-gate because it's not a real file.
|
||||
if mapping.name.as_deref() == Some(LINUX_GATE_LIBRARY_NAME.as_ref()) {
|
||||
if pid == std::process::id().try_into()? {
|
||||
let mem_slice = unsafe {
|
||||
std::slice::from_raw_parts(mapping.start_address as *const u8, mapping.size)
|
||||
};
|
||||
return Self::elf_file_identifier_from_mapped_file(mem_slice);
|
||||
} else {
|
||||
let mem_slice = Self::copy_from_process(
|
||||
pid,
|
||||
mapping.start_address as *mut libc::c_void,
|
||||
mapping.size,
|
||||
)?;
|
||||
return Self::elf_file_identifier_from_mapped_file(&mem_slice);
|
||||
}
|
||||
}
|
||||
|
||||
let (filename, old_name) = mapping.fixup_deleted_file(pid)?;
|
||||
|
||||
let mem_slice = MappingInfo::get_mmap(&Some(filename), mapping.offset)?;
|
||||
let build_id = Self::elf_file_identifier_from_mapped_file(&mem_slice)?;
|
||||
|
||||
// This means we switched from "/my/binary" to "/proc/1234/exe", change the mapping to
|
||||
// remove the " (deleted)" portion.
|
||||
if let Some(old_name) = old_name {
|
||||
mapping.name = Some(old_name.into());
|
||||
}
|
||||
Ok(build_id)
|
||||
) -> Result<T, DumperError> {
|
||||
Ok(T::read_from_module(
|
||||
module_reader::ProcessReader::new(pid, mapping.start_address).into(),
|
||||
)?)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ pub fn write(
|
|||
for app_memory in &config.app_memory {
|
||||
let data_copy = PtraceDumper::copy_from_process(
|
||||
config.blamed_thread,
|
||||
app_memory.ptr as *mut libc::c_void,
|
||||
app_memory.ptr,
|
||||
app_memory.length,
|
||||
)?;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use super::*;
|
||||
use crate::linux::maps_reader::MappingInfo;
|
||||
use crate::linux::module_reader::{BuildId, ReadFromModule, SoName};
|
||||
|
||||
/// Write information about the mappings in effect. Because we are using the
|
||||
/// minidump format, the information about the mappings is pretty limited.
|
||||
|
@ -23,24 +24,53 @@ pub fn write(
|
|||
{
|
||||
continue;
|
||||
}
|
||||
// Note: elf_identifier_for_mapping_index() can manipulate the |mapping.name|.
|
||||
let identifier = dumper
|
||||
.elf_identifier_for_mapping_index(map_idx)
|
||||
.unwrap_or_default();
|
||||
log::debug!("retrieving build id for {:?}", &dumper.mappings[map_idx]);
|
||||
let BuildId(identifier) = dumper
|
||||
.from_process_memory_for_index(map_idx)
|
||||
.or_else(|e| {
|
||||
// If the mapping has an associated name that is a file, try to read the build id
|
||||
// from the file. If there is no note segment with the build id in
|
||||
// the program headers, we can't get to the note section if the section header
|
||||
// table isn't loaded.
|
||||
if let Some(path) = &dumper.mappings[map_idx].name {
|
||||
let path = std::path::Path::new(&path);
|
||||
if path.exists() {
|
||||
log::debug!("failed to get build id from process memory ({e}), attempting to retrieve from {}", path.display());
|
||||
return BuildId::read_from_file(path)
|
||||
.map_err(errors::DumperError::ModuleReaderError);
|
||||
}
|
||||
log::debug!(
|
||||
"not attempting to get build id from {}: path does not exist",
|
||||
path.display()
|
||||
);
|
||||
}
|
||||
Err(e)
|
||||
})
|
||||
.unwrap_or_else(|e| {
|
||||
log::warn!("failed to get build id for mapping: {e}");
|
||||
BuildId(Vec::new())
|
||||
});
|
||||
|
||||
// If the identifier is all 0, its an uninteresting mapping (bmc#1676109)
|
||||
if identifier.is_empty() || identifier.iter().all(|&x| x == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let module = fill_raw_module(buffer, &dumper.mappings[map_idx], &identifier)?;
|
||||
// SONAME should always be accessible through program headers alone, so we don't really
|
||||
// need to fall back to trying to read from the mapping file.
|
||||
let soname = dumper
|
||||
.from_process_memory_for_index(map_idx)
|
||||
.ok()
|
||||
.map(|SoName(n)| n);
|
||||
|
||||
let module = fill_raw_module(buffer, &dumper.mappings[map_idx], &identifier, soname)?;
|
||||
modules.push(module);
|
||||
}
|
||||
|
||||
// Next write all the mappings provided by the caller
|
||||
for user in &config.user_mapping_list {
|
||||
// GUID was provided by caller.
|
||||
let module = fill_raw_module(buffer, &user.mapping, &user.identifier)?;
|
||||
let module = fill_raw_module(buffer, &user.mapping, &user.identifier, None)?;
|
||||
modules.push(module);
|
||||
}
|
||||
|
||||
|
@ -63,6 +93,7 @@ fn fill_raw_module(
|
|||
buffer: &mut DumpBuf,
|
||||
mapping: &MappingInfo,
|
||||
identifier: &[u8],
|
||||
soname: Option<String>,
|
||||
) -> Result<MDRawModule, errors::SectionMappingsError> {
|
||||
let cv_record = if identifier.is_empty() {
|
||||
// Just zeroes
|
||||
|
@ -84,7 +115,7 @@ fn fill_raw_module(
|
|||
};
|
||||
|
||||
let (file_path, _, so_version) = mapping
|
||||
.get_mapping_effective_path_name_and_version()
|
||||
.get_mapping_effective_path_name_and_version(soname)
|
||||
.map_err(|e| errors::SectionMappingsError::GetEffectivePathError(mapping.clone(), e))?;
|
||||
let name_header = write_string_to_location(buffer, file_path.to_string_lossy().as_ref())?;
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ pub fn write(
|
|||
|
||||
let memory_copy = PtraceDumper::copy_from_process(
|
||||
thread.thread_id as i32,
|
||||
ip_memory_d.start_of_memory_range as *mut libc::c_void,
|
||||
ip_memory_d.start_of_memory_range as _,
|
||||
ip_memory_d.memory.data_size as usize,
|
||||
)?;
|
||||
|
||||
|
@ -196,7 +196,7 @@ fn fill_thread_stack(
|
|||
|
||||
let mut stack_bytes = PtraceDumper::copy_from_process(
|
||||
thread.thread_id.try_into()?,
|
||||
valid_stack_ptr as *mut libc::c_void,
|
||||
valid_stack_ptr,
|
||||
stack_len,
|
||||
)?;
|
||||
let stack_pointer_offset = stack_ptr.saturating_sub(valid_stack_ptr);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::errors::ThreadInfoError;
|
||||
use crate::{errors::ThreadInfoError, Pid};
|
||||
use nix::{errno::Errno, sys::ptrace, unistd};
|
||||
use std::{
|
||||
io::{self, BufRead},
|
||||
|
@ -7,8 +7,6 @@ use std::{
|
|||
|
||||
type Result<T> = std::result::Result<T, ThreadInfoError>;
|
||||
|
||||
pub type Pid = i32;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
|
||||
mod x86;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use super::{CommonThreadInfo, NT_Elf, Pid};
|
||||
use super::{CommonThreadInfo, NT_Elf};
|
||||
use crate::{
|
||||
errors::ThreadInfoError,
|
||||
minidump_cpu::{RawContextCPU, FP_REG_COUNT, GP_REG_COUNT},
|
||||
Pid,
|
||||
};
|
||||
use nix::sys::ptrace;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::{CommonThreadInfo, NT_Elf, Pid};
|
||||
use crate::{errors::ThreadInfoError, minidump_cpu::RawContextCPU};
|
||||
use super::{CommonThreadInfo, NT_Elf};
|
||||
use crate::{errors::ThreadInfoError, minidump_cpu::RawContextCPU, Pid};
|
||||
use nix::sys::ptrace;
|
||||
|
||||
type Result<T> = std::result::Result<T, ThreadInfoError>;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use super::Pid;
|
||||
use crate::errors::ThreadInfoError;
|
||||
use crate::{errors::ThreadInfoError, Pid};
|
||||
use libc;
|
||||
|
||||
type Result<T> = std::result::Result<T, ThreadInfoError>;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::{CommonThreadInfo, NT_Elf, Pid};
|
||||
use crate::{errors::ThreadInfoError, minidump_cpu::RawContextCPU, minidump_format::format};
|
||||
use super::{CommonThreadInfo, NT_Elf};
|
||||
use crate::{errors::ThreadInfoError, minidump_cpu::RawContextCPU, minidump_format::format, Pid};
|
||||
use core::mem::size_of_val;
|
||||
#[cfg(all(not(target_os = "android"), target_arch = "x86"))]
|
||||
use libc::user_fpxregs_struct;
|
||||
|
|
|
@ -9,16 +9,21 @@ type Error = Box<dyn error::Error + std::marker::Send + std::marker::Sync>;
|
|||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
fn build_command() -> Command {
|
||||
let mut cmd = Command::new("cargo");
|
||||
let mut cmd;
|
||||
if let Some(binary) = std::env::var_os("TEST_HELPER") {
|
||||
cmd = Command::new(binary);
|
||||
} else {
|
||||
cmd = Command::new("cargo");
|
||||
cmd.args(["run", "-q", "--bin", "test"]);
|
||||
|
||||
cmd.env("RUST_BACKTRACE", "1")
|
||||
.args(["run", "-q", "--bin", "test"]);
|
||||
// In normal cases where the host and target are the same this won't matter,
|
||||
// but tests will fail if you are eg running in a cross container which will
|
||||
// likely be x86_64 but may be targetting aarch64 or i686, which will result
|
||||
// in tests failing, or at the least not testing what you think
|
||||
cmd.args(["--target", current_platform::CURRENT_PLATFORM, "--"]);
|
||||
}
|
||||
|
||||
// In normal cases where the host and target are the same this won't matter,
|
||||
// but tests will fail if you are eg running in a cross container which will
|
||||
// likely be x86_64 but may be targetting aarch64 or i686, which will result
|
||||
// in tests failing, or at the least not testing what you think
|
||||
cmd.args(["--target", current_platform::CURRENT_PLATFORM, "--"]);
|
||||
cmd.env("RUST_BACKTRACE", "1");
|
||||
|
||||
cmd
|
||||
}
|
||||
|
|
|
@ -9,8 +9,9 @@ use minidump_writer::{
|
|||
errors::*,
|
||||
maps_reader::{MappingEntry, MappingInfo, SystemMappingInfo},
|
||||
minidump_writer::MinidumpWriter,
|
||||
module_reader::{BuildId, ReadFromModule},
|
||||
ptrace_dumper::PtraceDumper,
|
||||
thread_info::Pid,
|
||||
Pid,
|
||||
};
|
||||
use nix::{errno::Errno, sys::signal::Signal};
|
||||
use procfs_core::process::MMPermissions;
|
||||
|
@ -517,18 +518,28 @@ contextual_test! {
|
|||
let dump = Minidump::read_path(tmpfile.path()).expect("Failed to read minidump");
|
||||
let fds: MinidumpHandleDataStream = dump.get_stream().expect("Couldn't find MinidumpHandleDataStream");
|
||||
// We check that we create num_of_files plus stdin, stdout and stderr
|
||||
for i in 0..2 {
|
||||
for i in 0..3 {
|
||||
let descriptor = fds.handles.get(i).expect("Descriptor should be present");
|
||||
let fd = *descriptor.raw.handle().expect("Handle should be populated");
|
||||
assert_eq!(fd, i as u64);
|
||||
}
|
||||
|
||||
for i in 3..num_of_files {
|
||||
let descriptor = fds.handles.get(i).expect("Descriptor should be present");
|
||||
let object_name = descriptor.object_name.as_ref().expect("The path should be populated");
|
||||
let file_name = object_name.split('/').last().expect("The filename should be present");
|
||||
assert!(file_name.starts_with("test_file"));
|
||||
assert!(file_name.ends_with(&(i - 3).to_string()));
|
||||
let non_std_files = &fds.handles[3..];
|
||||
|
||||
// We need to handle the android case where additional pipes might be opened and
|
||||
// interspersed with the test_files (emulator? adb?) so that CI doesn't sporadically fail
|
||||
for i in 0..num_of_files {
|
||||
if !non_std_files.iter().any(|descriptor| {
|
||||
let Some(name) = &descriptor.object_name else { return false; };
|
||||
let Some(file_name) = name.rsplit_once('/').map(|(_, fname)| fname) else { return false; };
|
||||
if !file_name.starts_with("test_file") {
|
||||
return false;
|
||||
}
|
||||
|
||||
file_name.ends_with(&i.to_string())
|
||||
}) {
|
||||
panic!("unable to locate expected file `test_file{i}` in file handle stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -684,7 +695,11 @@ fn with_deleted_binary() {
|
|||
.unwrap();
|
||||
let binary_copy = binary_copy_dir.as_ref().join("binary_copy");
|
||||
|
||||
let path: &'static str = std::env!("CARGO_BIN_EXE_test");
|
||||
let path: String = if let Ok(p) = std::env::var("TEST_HELPER") {
|
||||
p
|
||||
} else {
|
||||
std::env!("CARGO_BIN_EXE_test").into()
|
||||
};
|
||||
|
||||
std::fs::copy(path, &binary_copy).expect("Failed to copy binary");
|
||||
let mem_slice = std::fs::read(&binary_copy).expect("Failed to read binary");
|
||||
|
@ -692,7 +707,7 @@ fn with_deleted_binary() {
|
|||
let mut child = Command::new(&binary_copy)
|
||||
.env("RUST_BACKTRACE", "1")
|
||||
.arg("spawn_and_wait")
|
||||
.arg(format!("{}", num_of_threads))
|
||||
.arg(num_of_threads.to_string())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("failed to execute child");
|
||||
|
@ -700,8 +715,8 @@ fn with_deleted_binary() {
|
|||
|
||||
let pid = child.id() as i32;
|
||||
|
||||
let mut build_id = PtraceDumper::elf_file_identifier_from_mapped_file(&mem_slice)
|
||||
.expect("Failed to get build_id");
|
||||
let BuildId(mut build_id) =
|
||||
BuildId::read_from_module(mem_slice.as_slice().into()).expect("Failed to get build_id");
|
||||
|
||||
std::fs::remove_file(&binary_copy).expect("Failed to remove binary");
|
||||
|
||||
|
@ -733,7 +748,7 @@ fn with_deleted_binary() {
|
|||
let main_module = module_list
|
||||
.main_module()
|
||||
.expect("Could not get main module");
|
||||
assert_eq!(main_module.code_file(), binary_copy.to_string_lossy());
|
||||
//assert_eq!(main_module.code_file(), binary_copy.to_string_lossy());
|
||||
|
||||
let did = main_module
|
||||
.debug_identifier()
|
||||
|
|
|
@ -12,6 +12,17 @@ use std::os::unix::process::ExitStatusExt;
|
|||
mod common;
|
||||
use common::*;
|
||||
|
||||
/// These tests generally aren't consistent in resource-deprived environments like CI runners and
|
||||
/// android emulators.
|
||||
macro_rules! disabled_on_ci_and_android {
|
||||
() => {
|
||||
if std::env::var("CI").is_ok() || cfg!(target_os = "android") {
|
||||
println!("disabled on CI and android, but otherwise works locally");
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_setup() {
|
||||
spawn_child("setup", &[]);
|
||||
|
@ -20,6 +31,58 @@ fn test_setup() {
|
|||
#[test]
|
||||
fn test_thread_list_from_child() {
|
||||
// Child spawns and looks in the parent (== this process) for its own thread-ID
|
||||
|
||||
let (tx, rx) = std::sync::mpsc::sync_channel(1);
|
||||
|
||||
// // We also spawn another thread that we send a SIGHUP to to ensure that the
|
||||
// // ptracedumper correctly handles it
|
||||
let _thread = std::thread::Builder::new()
|
||||
.name("sighup-thread".into())
|
||||
.spawn(move || {
|
||||
tx.send(unsafe { libc::pthread_self() as usize }).unwrap();
|
||||
loop {
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let thread_id = rx.recv().unwrap();
|
||||
|
||||
// Unfortunately we need to set a signal handler to ignore the SIGHUP we send
|
||||
// to the thread, as otherwise the default test harness fails
|
||||
unsafe {
|
||||
let mut act: libc::sigaction = std::mem::zeroed();
|
||||
if libc::sigemptyset(&mut act.sa_mask) != 0 {
|
||||
eprintln!(
|
||||
"unable to clear action mask: {:?}",
|
||||
std::io::Error::last_os_error()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
unsafe extern "C" fn on_sig(
|
||||
_sig: libc::c_int,
|
||||
_info: *mut libc::siginfo_t,
|
||||
_uc: *mut libc::c_void,
|
||||
) {
|
||||
}
|
||||
|
||||
act.sa_flags = libc::SA_SIGINFO;
|
||||
act.sa_sigaction = on_sig as usize;
|
||||
|
||||
// Register the action with the signal handler
|
||||
if libc::sigaction(libc::SIGHUP, &act, std::ptr::null_mut()) != 0 {
|
||||
eprintln!(
|
||||
"unable to register signal handler: {:?}",
|
||||
std::io::Error::last_os_error()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
libc::pthread_kill(thread_id as _, libc::SIGHUP);
|
||||
}
|
||||
|
||||
spawn_child("thread_list", &[]);
|
||||
}
|
||||
|
||||
|
@ -28,8 +91,12 @@ fn test_thread_list_from_parent() {
|
|||
let num_of_threads = 5;
|
||||
let mut child = start_child_and_wait_for_threads(num_of_threads);
|
||||
let pid = child.id() as i32;
|
||||
let mut dumper = PtraceDumper::new(pid, minidump_writer::minidump_writer::STOP_TIMEOUT)
|
||||
.expect("Couldn't init dumper");
|
||||
let mut dumper = PtraceDumper::new(
|
||||
pid,
|
||||
minidump_writer::minidump_writer::STOP_TIMEOUT,
|
||||
Default::default(),
|
||||
)
|
||||
.expect("Couldn't init dumper");
|
||||
assert_eq!(dumper.threads.len(), num_of_threads);
|
||||
dumper.suspend_threads().expect("Could not suspend threads");
|
||||
|
||||
|
@ -104,11 +171,7 @@ fn test_mappings_include_linux_gate() {
|
|||
|
||||
#[test]
|
||||
fn test_linux_gate_mapping_id() {
|
||||
if std::env::var("CI").is_ok() {
|
||||
println!("disabled on CI, but works locally");
|
||||
return;
|
||||
}
|
||||
|
||||
disabled_on_ci_and_android!();
|
||||
spawn_child("linux_gate_mapping_id", &[]);
|
||||
}
|
||||
|
||||
|
@ -118,8 +181,12 @@ fn test_merged_mappings() {
|
|||
let page_size = std::num::NonZeroUsize::new(page_size.unwrap() as usize).unwrap();
|
||||
let map_size = std::num::NonZeroUsize::new(3 * page_size.get()).unwrap();
|
||||
|
||||
let path: &'static str = std::env!("CARGO_BIN_EXE_test");
|
||||
let file = std::fs::File::open(path).unwrap();
|
||||
let path: String = if let Ok(p) = std::env::var("TEST_HELPER") {
|
||||
p
|
||||
} else {
|
||||
std::env!("CARGO_BIN_EXE_test").into()
|
||||
};
|
||||
let file = std::fs::File::open(&path).unwrap();
|
||||
|
||||
// mmap two segments out of the helper binary, one
|
||||
// enclosed in the other, but with different protections.
|
||||
|
@ -153,13 +220,14 @@ fn test_merged_mappings() {
|
|||
|
||||
spawn_child(
|
||||
"merged_mappings",
|
||||
&[path, &format!("{mapped}"), &format!("{map_size}")],
|
||||
&[&path, &format!("{mapped}"), &format!("{map_size}")],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Ensure that the linux-gate VDSO is included in the mapping list.
|
||||
fn test_file_id() {
|
||||
disabled_on_ci_and_android!();
|
||||
spawn_child("file_id", &[]);
|
||||
}
|
||||
|
||||
|
@ -176,10 +244,7 @@ fn test_find_mapping() {
|
|||
|
||||
#[test]
|
||||
fn test_copy_from_process_self() {
|
||||
if std::env::var("CI").is_ok() {
|
||||
println!("disabled on CI, but works locally");
|
||||
return;
|
||||
}
|
||||
disabled_on_ci_and_android!();
|
||||
|
||||
let stack_var: libc::c_long = 0x11223344;
|
||||
let heap_var: Box<libc::c_long> = Box::new(0x55667788);
|
||||
|
@ -207,8 +272,12 @@ fn test_sanitize_stack_copy() {
|
|||
let heap_addr = usize::from_str_radix(output.next().unwrap().trim_start_matches("0x"), 16)
|
||||
.expect("unable to parse mmap_addr");
|
||||
|
||||
let mut dumper = PtraceDumper::new(pid, minidump_writer::minidump_writer::STOP_TIMEOUT)
|
||||
.expect("Couldn't init dumper");
|
||||
let mut dumper = PtraceDumper::new(
|
||||
pid,
|
||||
minidump_writer::minidump_writer::STOP_TIMEOUT,
|
||||
Default::default(),
|
||||
)
|
||||
.expect("Couldn't init dumper");
|
||||
assert_eq!(dumper.threads.len(), num_of_threads);
|
||||
dumper.suspend_threads().expect("Could not suspend threads");
|
||||
let thread_info = dumper
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче