diff --git a/.cargo/config.toml.in b/.cargo/config.toml.in index cf8fa20b7ae0..a398336e5bdb 100644 --- a/.cargo/config.toml.in +++ b/.cargo/config.toml.in @@ -124,9 +124,9 @@ replace-with = "vendored-sources" git = "https://github.com/mozilla/nss-rs" replace-with = "vendored-sources" -[source."git+https://github.com/rust-minidump/minidump-writer.git?rev=ee5b9d59d85bea1d4c6845f6b854e04fe204adf2"] +[source."git+https://github.com/rust-minidump/minidump-writer.git?rev=6744feee58804a78730d176cdcc31bb4f3021107"] git = "https://github.com/rust-minidump/minidump-writer.git" -rev = "ee5b9d59d85bea1d4c6845f6b854e04fe204adf2" +rev = "6744feee58804a78730d176cdcc31bb4f3021107" replace-with = "vendored-sources" [source."git+https://github.com/servo/rust-cssparser?rev=ddccc070a0261cb94195ed0f74095c67b86a8550"] diff --git a/Cargo.lock b/Cargo.lock index d15e7b9020c4..77eff10fd66e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -358,7 +358,7 @@ dependencies = [ "dbus", "libc", "log", - "mach2", + "mach2 0.4.999", "windows-sys", ] @@ -1314,13 +1314,12 @@ dependencies = [ [[package]] name = "crash-context" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b85cef661eeca0c6675116310936972c520ebb0a33ddef16fd7efc957f4c1288" +version = "0.8.0" +source = "git+https://github.com/rust-minidump/minidump-writer.git?rev=6744feee58804a78730d176cdcc31bb4f3021107#6744feee58804a78730d176cdcc31bb4f3021107" dependencies = [ "cfg-if", "libc", - "mach2", + "mach2 0.6.0", ] [[package]] @@ -1329,7 +1328,7 @@ version = "0.1.0" dependencies = [ "anyhow", "crash_helper_common", - "mach2", + "mach2 0.6.0", "minidump-writer", "nix", "num-derive", @@ -1346,7 +1345,7 @@ dependencies = [ "getrandom 0.3.3", "linked-hash-map", "log", - "mach2", + "mach2 0.6.0", "minidump-writer", "mozannotation_server", "mozbuild", @@ -1620,7 +1619,7 @@ dependencies = [ "cubeb-backend", "float-cmp", "libc", - "mach2", + "mach2 0.4.999", "num", "ringbuf", "triple_buffer", @@ -4537,13 +4536,17 @@ dependencies = [ [[package]] name = "mach2" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" +version = "0.4.999" dependencies = [ - "libc", + "mach2 0.6.0", ] +[[package]] +name = "mach2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" + [[package]] name = "macho-unwind-info" version = "0.5.0" @@ -4867,8 +4870,8 @@ dependencies = [ [[package]] name = "minidump-writer" -version = "0.12.0" -source = "git+https://github.com/rust-minidump/minidump-writer.git?rev=ee5b9d59d85bea1d4c6845f6b854e04fe204adf2#ee5b9d59d85bea1d4c6845f6b854e04fe204adf2" +version = "0.13.0" +source = "git+https://github.com/rust-minidump/minidump-writer.git?rev=6744feee58804a78730d176cdcc31bb4f3021107#6744feee58804a78730d176cdcc31bb4f3021107" dependencies = [ "bitflags 2.10.0", "byteorder", @@ -4879,9 +4882,10 @@ dependencies = [ "goblin 0.9.2", "libc", "log", - "mach2", + "mach2 0.6.0", "memmap2", "minidump-common", + "plain", "process-backend", "procfs-core 0.18.0", "scroll", @@ -6490,11 +6494,10 @@ dependencies = [ [[package]] name = "process-backend" -version = "0.0.0" -source = "git+https://github.com/rust-minidump/minidump-writer.git?rev=ee5b9d59d85bea1d4c6845f6b854e04fe204adf2#ee5b9d59d85bea1d4c6845f6b854e04fe204adf2" +version = "0.1.0" +source = "git+https://github.com/rust-minidump/minidump-writer.git?rev=6744feee58804a78730d176cdcc31bb4f3021107#6744feee58804a78730d176cdcc31bb4f3021107" dependencies = [ "libc", - "log", "process-reader", "serde", "thiserror 2.0.12", @@ -6502,8 +6505,8 @@ dependencies = [ [[package]] name = "process-reader" -version = "0.0.0" -source = "git+https://github.com/rust-minidump/minidump-writer.git?rev=ee5b9d59d85bea1d4c6845f6b854e04fe204adf2#ee5b9d59d85bea1d4c6845f6b854e04fe204adf2" +version = "0.1.0" +source = "git+https://github.com/rust-minidump/minidump-writer.git?rev=6744feee58804a78730d176cdcc31bb4f3021107#6744feee58804a78730d176cdcc31bb4f3021107" dependencies = [ "libc", "serde", @@ -6516,7 +6519,7 @@ dependencies = [ "goblin 0.9.2", "libc", "log", - "mach2", + "mach2 0.6.0", "memoffset 0.9.0", "mozilla-central-workspace-hack", "scroll", diff --git a/Cargo.toml b/Cargo.toml index c83ca441ff5a..257118136ca7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -439,3 +439,6 @@ jxl_simd = { path = "third_party/rust/jxl_simd" } gleam = { git = "https://github.com/jamienicol/gleam", rev = "68ca4e5cc31135b843af07ff213a94b9ddce64cf" } # gl_generator 0.14.0 + https://github.com/rust-windowing/gl-rs/pull/566 gl_generator = { git = "https://github.com/jamienicol/gl-rs", rev = "71c792dbfe0ec5caeb242fc90937e19098386342" } + +# Implement mach2 0.4 in terms of 0.6 +mach2 = { path = "build/rust/mach2" } diff --git a/build/rust/mach2/Cargo.toml b/build/rust/mach2/Cargo.toml new file mode 100644 index 000000000000..824686192de6 --- /dev/null +++ b/build/rust/mach2/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "mach2" +version = "0.4.999" +edition = "2024" +license = "Mozilla Public License 2.0" + +[lib] +path = "lib.rs" + +[dependencies] +mach2 = "0.6.0" diff --git a/build/rust/mach2/lib.rs b/build/rust/mach2/lib.rs new file mode 100644 index 000000000000..72c19fa1e1c7 --- /dev/null +++ b/build/rust/mach2/lib.rs @@ -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 https://mozilla.org/MPL/2.0/. + +pub use mach2::*; diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index 9a12c62a71a4..61a91a59f374 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -17,7 +17,7 @@ who = "John M. Schanck " criteria = "safe-to-deploy" user-id = 175410 # John Schanck (jschanck) start = "2022-11-15" -end = "2026-09-25" +end = "2027-09-01" notes = "Maintained by the CryptoEng team at Mozilla." [[wildcard-audits.bhttp]] @@ -33,7 +33,7 @@ who = "Alex Franchuk " criteria = "safe-to-deploy" user-id = 72814 # Gabriele Svelto (gabrielesvelto) start = "2022-11-30" -end = "2026-02-01" +end = "2027-09-01" notes = "This crate is written and maintained by mozilla employees." [[wildcard-audits.cachemap2]] @@ -366,7 +366,7 @@ who = "Alex Franchuk " criteria = "safe-to-deploy" user-id = 72814 # Gabriele Svelto (gabrielesvelto) start = "2022-11-30" -end = "2026-02-01" +end = "2027-09-01" notes = "This crate is written and maintained by mozilla employees." [[wildcard-audits.minidump-common]] @@ -374,7 +374,7 @@ who = "Alex Franchuk " criteria = "safe-to-deploy" user-id = 72814 # Gabriele Svelto (gabrielesvelto) start = "2022-11-30" -end = "2026-02-01" +end = "2027-09-01" notes = "This crate is written and maintained by mozilla employees." [[wildcard-audits.minidump-unwind]] @@ -382,7 +382,7 @@ who = "Alex Franchuk " criteria = "safe-to-deploy" user-id = 72814 # Gabriele Svelto (gabrielesvelto) start = "2023-05-17" -end = "2026-02-01" +end = "2027-09-01" notes = "This crate is written and maintained by mozilla employees." [[wildcard-audits.mozdevice]] @@ -1775,6 +1775,17 @@ who = "Gabriele Svelto " criteria = "safe-to-deploy" delta = "0.6.0 -> 0.6.1" +[[audits.crash-context]] +who = "Chris Martin " +criteria = "safe-to-deploy" +delta = "0.6.1 -> 0.8.0" + +[[audits.crash-context]] +who = "Chris Martin " +criteria = "safe-to-deploy" +delta = "0.8.0 -> 0.8.0@git:6744feee58804a78730d176cdcc31bb4f3021107" +importable = false + [[audits.crc32fast]] who = "Alex Franchuk " criteria = "safe-to-deploy" @@ -4751,8 +4762,15 @@ delta = "0.11.0 -> 0.12.0" [[audits.minidump-writer]] who = "Chris Martin " criteria = "safe-to-deploy" -delta = "0.12.0 -> 0.12.0@git:ee5b9d59d85bea1d4c6845f6b854e04fe204adf2" +delta = "0.12.0 -> 0.13.0" +notes = "This crate is mostly maintained by Mozilla staff" + +[[audits.minidump-writer]] +who = "Chris Martin " +criteria = "safe-to-deploy" +delta = "0.13.0 -> 0.13.0@git:6744feee58804a78730d176cdcc31bb4f3021107" importable = false +notes = "This crate is mostly maintained by Mozilla staff." [[audits.miniz_oxide]] who = "Mike Hommey " @@ -9093,6 +9111,12 @@ user-id = 2915 # Amanieu d'Antras (Amanieu) start = "2019-05-04" end = "2024-05-05" +[[trusted.mach2]] +criteria = "safe-to-deploy" +trusted-publisher = "github:JohnTitor/mach2" +start = "2025-11-16" +end = "2027-09-01" + [[trusted.memchr]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) diff --git a/supply-chain/config.toml b/supply-chain/config.toml index ae21c7e520f7..7f462175c790 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -43,6 +43,9 @@ notes = "This is the upstream code plus a fix for https://github.com/rust-lang/c audit-as-crates-io = true notes = "This is upstream plus a warning fix from bug 1823866." +[policy."crash-context:0.8.0@git:6744feee58804a78730d176cdcc31bb4f3021107"] +audit-as-crates-io = true + [policy.cssparser] audit-as-crates-io = true notes = "Upstream not yet published changes" @@ -251,7 +254,7 @@ audit-as-crates-io = false [policy.peek-poke-derive] audit-as-crates-io = false -[policy."process-backend:0.0.0@git:ee5b9d59d85bea1d4c6845f6b854e04fe204adf2"] +[policy."process-backend:0.1.0@git:6744feee58804a78730d176cdcc31bb4f3021107"] audit-as-crates-io = false notes = """ This was originally intended to be a minidump-writer internal crate (and thus @@ -259,6 +262,9 @@ audited as part of minidump-writer), however an author accidentally published it publicly (so it is on crates.io now). """ +[policy."process-reader:0.1.0@git:6744feee58804a78730d176cdcc31bb4f3021107"] +audit-as-crates-io = false + [policy.pulse] audit-as-crates-io = false notes = "This is a first-party crate which is entirely unrelated to the crates.io package of the same name." diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index 8bc745505aaa..a06e0b0bd818 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -409,6 +409,11 @@ user-id = 2915 user-login = "Amanieu" user-name = "Amanieu d'Antras" +[[publisher.mach2]] +version = "0.6.0" +when = "2025-11-16" +trusted-publisher = "github:JohnTitor/mach2" + [[publisher.macho-unwind-info]] version = "0.5.0" when = "2024-12-06" @@ -3813,63 +3818,6 @@ who = "Ameer Ghani " criteria = "safe-to-deploy" delta = "0.5.1 -> 0.5.2" -[[audits.mozilla.wildcard-audits.uniffi]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -user-id = 111105 # Mark Hammond (mhammond) -start = "2021-11-22" -end = "2027-01-08" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.wildcard-audits.uniffi_bindgen]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -user-id = 111105 # Mark Hammond (mhammond) -start = "2021-11-22" -end = "2027-01-08" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.wildcard-audits.uniffi_build]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -user-id = 111105 # Mark Hammond (mhammond) -start = "2021-11-22" -end = "2027-01-08" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.wildcard-audits.uniffi_core]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -user-id = 111105 # Mark Hammond (mhammond) -start = "2023-11-20" -end = "2027-01-08" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.wildcard-audits.uniffi_macros]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -user-id = 111105 # Mark Hammond (mhammond) -start = "2021-11-22" -end = "2027-01-08" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.wildcard-audits.uniffi_meta]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -user-id = 111105 # Mark Hammond (mhammond) -start = "2023-11-20" -end = "2027-01-08" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.wildcard-audits.uniffi_pipeline]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -user-id = 111105 # Mark Hammond (mhammond) -start = "2025-10-08" -end = "2027-01-14" -notes = "Maintained by the Glean and Application Services teams" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - [[audits.mozilla.wildcard-audits.uniffi_testing]] who = "Jan-Erik Rediger " criteria = "safe-to-deploy" @@ -3878,14 +3826,6 @@ start = "2023-11-20" end = "2027-01-08" aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" -[[audits.mozilla.wildcard-audits.uniffi_udl]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -user-id = 111105 # Mark Hammond (mhammond) -start = "2023-11-20" -end = "2027-01-08" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - [[audits.mozilla.wildcard-audits.weedle2]] who = "Jan-Erik Rediger " criteria = "safe-to-deploy" diff --git a/third_party/rust/crash-context/.cargo-checksum.json b/third_party/rust/crash-context/.cargo-checksum.json index 167ba40c717a..7e49c349b88e 100644 --- a/third_party/rust/crash-context/.cargo-checksum.json +++ b/third_party/rust/crash-context/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo_vcs_info.json":"6ed7b69d2ca6fd1aaf962ffee20012e30364afee54eb73015bae5053181dc62b","CHANGELOG.md":"843168dabb93f6bc42076d4924040cd8c8a268f03cb02856b55691b5e9a873e1","Cargo.toml":"94c36b790e888c511e093c2b20ade75157daa86fad994d508d071bd4c049223a","Cargo.toml.orig":"27429894b157ef179ff40f155a12c7e81ceec7eaf03c883e86a8d03d592ff7e9","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"090a294a492ab2f41388252312a65cf2f0e423330b721a68c6665ac64766753b","README.md":"f91ee04dfaa356214af7ac68e4cfa1d6c8674f7fea08d65275f3fafde28301df","release.toml":"287ba3b6c89e3b289eae59827d36d6eb6e27b88cc2ada2c0d9a663c8b487117e","src/lib.rs":"26957a6a2555ab82aa9b6d3d1f24efaf20753d6c5eb1510395789283890ac1d1","src/linux.rs":"cf05c1217709a60adeea08e8623438f68a18dea66758b194de0e07ff398b090d","src/linux/getcontext.rs":"4164236732556d71cbb9e04bf4f2b41fd6f51f9bb94dfb974158cc5f49c3c789","src/linux/getcontext/aarch64.rs":"1193e68f06f7f2f4d3e64d80a196804e6cdfd03643ac50332c7af10928a5eccb","src/linux/getcontext/arm.rs":"682f163f4a96c21930e37427a6d687efc68199cbd8a9125b34d99a81280dd31b","src/linux/getcontext/x86.rs":"7c585ec44835910f99801cbb3ac34153e8d687b5dcbc682f9b7768873655c4a0","src/linux/getcontext/x86_64.rs":"db63a1c05e2c7c5b998f3c57b399972fc4e756eb36bcd119a99419c94470444a","src/mac.rs":"13d25443466d387eabf28adae361708f4b6297949c7eeb5bf1b38cb0ca13a418","src/mac/guard.rs":"115d1e8d5ac7bd9ecc666b11a0c584ed1e997160aacb0a1cc0f215ff5a1e9803","src/mac/ipc.rs":"2fc139ee5b70964bd726a30853d7fe9f74f7a6e0f8cf3d150e72a2ac802c1fba","src/mac/resource.rs":"8289db9294a45d6148329d537530512913c456a182783059a832767e39c67295","src/windows.rs":"c6c043cf56cf0840cc1373edc4bd39cf829566d181e50589174745629ab2ad37","tests/capture_context.rs":"899e94c522cd015fd1f45230aff5c8970346ba20623da46cd34da892bbd07f7e"},"package":"b85cef661eeca0c6675116310936972c520ebb0a33ddef16fd7efc957f4c1288"} \ No newline at end of file +{"files":{"CHANGELOG.md":"43797a4e27141f566a1b921e88b329d34e0839eb1bb2bcccb8befa154aba4990","Cargo.toml":"5f7ddf844c6a78ccbe409fa378eae172dd9f5cd9e553ee896e90c89705b06d32","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"090a294a492ab2f41388252312a65cf2f0e423330b721a68c6665ac64766753b","README.md":"57796e5f6ef2e5ba3825648b9efc8be22a13eeedb2ec99d23578bb7caac6531b","release.toml":"4ad4d174316dd8e71c381358ed79651354da7117c5737641ca8a5d904b64cc98","src/lib.rs":"26957a6a2555ab82aa9b6d3d1f24efaf20753d6c5eb1510395789283890ac1d1","src/linux.rs":"82ebc969c367294291259e5c70f4674ca2f348d11786eece4b17b54f3b619ff8","src/linux/getcontext.rs":"698e687ac0341e4f48ddd5d5b5284a69c6e4f666e9090dbb87199600747ca025","src/linux/getcontext/aarch64.rs":"1193e68f06f7f2f4d3e64d80a196804e6cdfd03643ac50332c7af10928a5eccb","src/linux/getcontext/arm.rs":"d7f4b94acabfbbd332d3d56975d4bbd4302abfc8f5da1ca15d8d954bdc9fc785","src/linux/getcontext/loongarch64.rs":"5cb9e57d061523ca5376daeff249fe396337f1363f24367466f01003779ffc16","src/linux/getcontext/riscv64.rs":"ef675a729951f2b636a6b33a26d1cfac30b4ab7ada6df435e3f0d762bc71ae23","src/linux/getcontext/s390x.rs":"d6489e346bdc1b61ef91125439d9b90e02d65e6df96be3acb7bfc97f2587840c","src/linux/getcontext/x86.rs":"7c585ec44835910f99801cbb3ac34153e8d687b5dcbc682f9b7768873655c4a0","src/linux/getcontext/x86_64.rs":"bf2067bb2b9274488f55aa64a8bfda60024f2070f2252195cfe489d6f9fb5231","src/mac.rs":"13d25443466d387eabf28adae361708f4b6297949c7eeb5bf1b38cb0ca13a418","src/mac/guard.rs":"115d1e8d5ac7bd9ecc666b11a0c584ed1e997160aacb0a1cc0f215ff5a1e9803","src/mac/ipc.rs":"98db18243a090c03132e75693bf396352eb63cbef87809e4fe3642706639866a","src/mac/resource.rs":"152dba61569b698e08c4a96b83edc0016126775ef0bc3ae3aa476605b81106f8","src/windows.rs":"2a38f4143e9423f738ac8b5fe06a4ccd8b3a5c22d0f2bf40e9fd839dde15b0e4","tests/capture_context.rs":"899e94c522cd015fd1f45230aff5c8970346ba20623da46cd34da892bbd07f7e"},"package":null} \ No newline at end of file diff --git a/third_party/rust/crash-context/.cargo_vcs_info.json b/third_party/rust/crash-context/.cargo_vcs_info.json deleted file mode 100644 index ebc622f08369..000000000000 --- a/third_party/rust/crash-context/.cargo_vcs_info.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "git": { - "sha1": "16c2545f2a46b6b21d1e401cfeaf0d5b9a130b08" - }, - "path_in_vcs": "crash-context" -} \ No newline at end of file diff --git a/third_party/rust/crash-context/CHANGELOG.md b/third_party/rust/crash-context/CHANGELOG.md index 666ba89c52e7..cd0c66ed6d63 100644 --- a/third_party/rust/crash-context/CHANGELOG.md +++ b/third_party/rust/crash-context/CHANGELOG.md @@ -9,6 +9,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - ReleaseDate +## [0.8.0] - 2026-07-17 +### Added +- [PR#113](https://github.com/EmbarkStudios/crash-handling/pull/113) added support for loongarch64 `getcontext`. + +### Changed +- [PR#190](https://github.com/rust-minidump/minidump-writer/pull/190) moved this crate from . + +## [0.7.0] - 2026-01-13 +### Added +- [PR#102](https://github.com/EmbarkStudios/crash-handling/pull/102) added support for RISCV64 `getcontext`. +- [PR#109](https://github.com/EmbarkStudios/crash-handling/pull/102) added support for s390x `getcontext`. + +### Changed +- [PR#111](https://github.com/EmbarkStudios/crash-handling/pull/111) updated MSRV to 1.85.0. + +## [0.6.3] - 2024-07-25 +### Fixed +- [PR#89](https://github.com/EmbarkStudios/crash-handling/pull/89) fixed compilation for `arm-unknown-linux-gnueabihf`...again. + +## [0.6.2] - 2024-06-08 +### Changed +- Update MSRV to 1.62.0 + ## [0.6.1] - 2023-06-19 ### Added - [PR#76](https://github.com/EmbarkStudios/crash-handling/pull/76) added support for `i686-linux-android` and `x86_64-linux-android`. Thanks [@gabrielesvelto](https://github.com/gabrielesvelto)! @@ -68,7 +91,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial pass of crash-context, Linux only -[Unreleased]: https://github.com/EmbarkStudios/crash-handling/compare/crash-context-0.6.1...HEAD +[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/crash-context-0.8.0...HEAD +[0.8.0]: https://github.com/EmbarkStudios/crash-handling/compare/crash-context-0.7.0...crash-context-0.8.0 +[0.7.0]: https://github.com/EmbarkStudios/crash-handling/compare/{{tag_name}}...crash-context-0.7.0 +[0.6.3]: https://github.com/EmbarkStudios/crash-handling/compare/crash-context-0.6.2...{{tag_name}} +[0.6.2]: https://github.com/EmbarkStudios/crash-handling/compare/crash-context-0.6.1...crash-context-0.6.2 [0.6.1]: https://github.com/EmbarkStudios/crash-handling/compare/crash-context-0.6.0...crash-context-0.6.1 [0.6.0]: https://github.com/EmbarkStudios/crash-handling/compare/crash-context-0.5.1...crash-context-0.6.0 [0.5.1]: https://github.com/EmbarkStudios/crash-handling/compare/crash-context-0.5.0...crash-context-0.5.1 diff --git a/third_party/rust/crash-context/Cargo.toml b/third_party/rust/crash-context/Cargo.toml index add4000609e5..cbb6a5fdd30c 100644 --- a/third_party/rust/crash-context/Cargo.toml +++ b/third_party/rust/crash-context/Cargo.toml @@ -10,16 +10,19 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2021" -rust-version = "1.59.0" +edition = "2024" +rust-version = "1.88.0" name = "crash-context" -version = "0.6.1" -authors = [ - "Embark ", - "Jake Shadle ", -] +version = "0.8.0" +authors = ["Jake Shadle "] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "Provides portable types containing target specific contextual information at the time of a crash" -homepage = "https://github.com/EmbarkStudios/crash-handling/tree/main/crash-context" +homepage = "https://github.com/rust-minidump/minidump-writer/tree/main/crates/crash-context" documentation = "https://docs.rs/crash-context" readme = "README.md" keywords = [ @@ -28,15 +31,23 @@ keywords = [ "getcontext", ] categories = ["external-ffi-bindings"] -license = "MIT OR Apache-2.0" -repository = "https://github.com/EmbarkStudios/crash-handling" -resolver = "1" +license = "MIT" +repository = "https://github.com/rust-minidump/minidump-writer" + +[lib] +name = "crash_context" +path = "src/lib.rs" + +[[test]] +name = "capture_context" +path = "tests/capture_context.rs" [dependencies.cfg-if] version = "1.0" -[target."cfg(any(target_os = \"linux\", target_os = \"android\"))".dependencies.libc] +[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies.libc] version = "0.2" +default-features = false -[target."cfg(target_os = \"macos\")".dependencies.mach2] -version = "0.4" +[target.'cfg(target_os = "macos")'.dependencies.mach2] +version = "0.6" diff --git a/third_party/rust/crash-context/Cargo.toml.orig b/third_party/rust/crash-context/Cargo.toml.orig deleted file mode 100644 index ac56afa56783..000000000000 --- a/third_party/rust/crash-context/Cargo.toml.orig +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "crash-context" -version = "0.6.1" -description = "Provides portable types containing target specific contextual information at the time of a crash" -repository = "https://github.com/EmbarkStudios/crash-handling" -authors = [ - "Embark ", - "Jake Shadle ", -] -edition = "2021" -license = "MIT OR Apache-2.0" -readme = "README.md" -documentation = "https://docs.rs/crash-context" -homepage = "https://github.com/EmbarkStudios/crash-handling/tree/main/crash-context" -categories = ["external-ffi-bindings"] -keywords = ["crash", "libc", "getcontext"] -rust-version = "1.59.0" # We use `global_asm!` - -[dependencies] -# Nicer cfg handling -cfg-if = "1.0" - -[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] -libc = "0.2" - -[target.'cfg(target_os = "macos")'.dependencies] -# provides bindings to mach specifics -mach2 = "0.4" diff --git a/third_party/rust/crash-context/README.md b/third_party/rust/crash-context/README.md index 91375c9b5749..d04fba3913b4 100644 --- a/third_party/rust/crash-context/README.md +++ b/third_party/rust/crash-context/README.md @@ -10,12 +10,10 @@ **Provides portable types containing target specific contextual information at the time of a crash** -[![Embark](https://img.shields.io/badge/embark-open%20source-blueviolet.svg)](https://embark.dev) -[![Embark](https://img.shields.io/badge/discord-ark-%237289da.svg?logo=discord)](https://discord.gg/dAuKfZS) [![Crates.io](https://img.shields.io/crates/v/crash-context.svg)](https://crates.io/crates/crash-context) [![Docs](https://docs.rs/crash-context/badge.svg)](https://docs.rs/crash-context) -[![dependency status](https://deps.rs/repo/github/EmbarkStudios/crash-handling/status.svg)](https://deps.rs/repo/github/EmbarkStudios/crash-handling) -[![Build status](https://github.com/EmbarkStudios/crash-handling/workflows/CI/badge.svg)](https://github.com/EmbarkStudios/crash-handling/actions) +[![dependency status](https://deps.rs/repo/github/rust-minidump/minidump-writer/status.svg)](https://deps.rs/repo/github/rust-minidump/minidump-writer) +[![Build status](https://github.com/rust-minidump/minidump-writer/workflows/CI/badge.svg)](https://github.com/rust-minidump/minidump-writer/actions) @@ -31,23 +29,14 @@ - `i686-linux-android` - `i686-unknown-linux-gnu` - `i686-unknown-linux-musl` +- `loongarch64-unknown-linux-gnu` +- `loongarch64-unknown-linux-musl` - `x86_64-apple-darwin` - `x86_64-linux-android` - `x86_64-pc-windows-msvc` - `x86_64-unknown-linux-gnu` - `x86_64-unknown-linux-musl` -## Contribution - -[![Contributor Covenant](https://img.shields.io/badge/contributor%20covenant-v1.4-ff69b4.svg)](../CODE_OF_CONDUCT.md) - -We welcome community contributions to this project. - -Please read our [Contributor Guide](../CONTRIBUTING.md) for more information on how to get started. -Please also read our [Contributor Terms](../CONTRIBUTING.md#contributor-terms) before you make any contributions. - -Any contribution intentionally submitted for inclusion in an Embark Studios project, shall comply with the Rust standard licensing model (MIT OR Apache 2.0) and therefore be dual licensed as described below, without any additional terms or conditions: - ### License This contribution is dual licensed under EITHER OF diff --git a/third_party/rust/crash-context/release.toml b/third_party/rust/crash-context/release.toml index cf6a8e5c5478..833f8c3260e2 100644 --- a/third_party/rust/crash-context/release.toml +++ b/third_party/rust/crash-context/release.toml @@ -6,5 +6,5 @@ pre-release-replacements = [ { file = "CHANGELOG.md", search = "\\.\\.\\.HEAD", replace = "...{{tag_name}}" }, { file = "CHANGELOG.md", search = "ReleaseDate", replace = "{{date}}" }, { file = "CHANGELOG.md", search = "", replace = "\n## [Unreleased] - ReleaseDate" }, - { file = "CHANGELOG.md", search = "", replace = "\n[Unreleased]: https://github.com/EmbarkStudios/crash-handling/compare/{{tag_name}}...HEAD" }, + { file = "CHANGELOG.md", search = "", replace = "\n[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/{{tag_name}}...HEAD" }, ] diff --git a/third_party/rust/crash-context/src/linux.rs b/third_party/rust/crash-context/src/linux.rs index f9952c12d945..2226de949930 100644 --- a/third_party/rust/crash-context/src/linux.rs +++ b/third_party/rust/crash-context/src/linux.rs @@ -10,7 +10,7 @@ pub struct CrashContext { /// /// Note that we use [`crate::ucontext_t`] instead of [`libc::ucontext_t`] /// as libc's differs between glibc and musl - /// even though the ucontext_t received from a signal will be the same + /// even though the `ucontext_t` received from a signal will be the same /// regardless of the libc implementation used as it is only arch specific /// and not libc specific /// @@ -52,7 +52,7 @@ impl CrashContext { return None; } - unsafe { Some((*bytes.as_ptr().cast::()).clone()) } + unsafe { Some(std::ptr::read_unaligned(bytes.as_ptr().cast::())) } } } @@ -87,6 +87,8 @@ cfg_if::cfg_if! { pub uc_mcontext: mcontext_t, pub uc_sigmask: sigset_t, __private: [u8; 512], + /// Shadow stack + __ssp: [u64; 4], } #[repr(C)] @@ -256,6 +258,175 @@ cfg_if::cfg_if! { pub arm_cpsr: u32, pub fault_address: u32, } + } else if #[cfg(target_arch = "riscv64")] { + #[repr(C)] + #[derive(Clone)] + #[doc(hidden)] + pub struct ucontext_t { + pub __uc_flags: u64, + pub uc_link: *mut ucontext_t, + pub uc_stack: stack_t, + pub uc_sigmask: sigset_t, + pub uc_mcontext: mcontext_t, + } + + #[repr(C, align(16))] + #[derive(Clone)] + #[doc(hidden)] + pub struct mcontext_t { + pub __gregs: [u64; 32], + pub __fpregs: __riscv_mc_fp_state, + } + + #[repr(C)] + #[derive(Clone, Copy)] + #[doc(hidden)] + pub union __riscv_mc_fp_state { + pub __f: __riscv_mc_f_ext_state, + pub __d: __riscv_mc_d_ext_state, + pub __q: __riscv_mc_q_ext_state, + } + + #[repr(C)] + #[derive(Clone, Copy)] + #[doc(hidden)] + pub struct __riscv_mc_f_ext_state { + pub __f: [u32; 32], + pub __fcsr: u32, + } + + #[repr(C)] + #[derive(Clone, Copy)] + #[doc(hidden)] + pub struct __riscv_mc_d_ext_state { + pub __f: [u64; 32], + pub __fcsr: u32, + } + + #[repr(C, align(16))] + #[derive(Clone, Copy)] + #[doc(hidden)] + pub struct __riscv_mc_q_ext_state { + pub __f: [u64; 64], + pub __fcsr: u32, + pub __reserved: [u32; 3], + } + + pub type fpregset_t = __riscv_mc_fp_state; + } else if #[cfg(target_arch = "s390x")] { + #[repr(C)] + #[derive(Clone)] + #[doc(hidden)] + pub struct ucontext_t { + pub uc_flags: u64, + pub uc_link: *mut ucontext_t, + pub uc_stack: stack_t, + pub uc_mcontext: mcontext_t, + pub uc_sigmask: sigset_t, + } + + #[repr(C, align(8))] + #[derive(Clone,Copy)] + #[doc(hidden)] + pub struct mcontext_t { + pub psw: psw_t, + pub gregs: [u64; 16], + pub aregs: [u32; 16], + pub __fpregs: fpregset_t, + } + + #[repr(C)] + #[derive(Clone,Copy)] + #[doc(hidden)] + pub struct fpregset_t { + pub fpc: u32, + __pad: u32, + pub fprs: [fpreg_t; 16], + } + + #[repr(C)] + #[derive(Clone,Copy)] + #[doc(hidden)] + pub struct fpreg_t { + pub d: f64, + // pub f: f32, + } + + #[repr(C)] + #[derive(Clone,Copy)] + #[doc(hidden)] + pub struct psw_t { + pub mask: u64, + pub addr: u64, + } + } else if #[cfg(target_arch = "loongarch64")] { + pub const SC_USED_FP: u32 = 1; + pub const FPU_CTX_MAGIC: u32 = 0x46505501; + pub const FPU_CTX_ALIGN: usize = 8; + pub const LSX_CTX_MAGIC: u32 = 0x53580001; + pub const LSX_CTX_ALIGN: usize = 16; + pub const LASX_CTX_MAGIC: u32 = 0x41535801; + pub const LASX_CTX_ALIGN: usize = 32; + + #[repr(C)] + #[derive(Clone)] + #[doc(hidden)] + pub struct ucontext_t { + pub uc_flags: u64, + pub uc_link: *mut ucontext_t, + pub uc_stack: stack_t, + pub uc_sigmask: sigset_t, + pub uc_mcontext: mcontext_t, + } + + #[repr(C, align(16))] + #[derive(Clone,Copy)] + #[doc(hidden)] + pub struct mcontext_t { + pub __pc: u64, + pub __gregs: [u64; 32], + pub __flags: u32, + pub __extcontext: [u64; 0], + } + + #[repr(C, align(16))] + #[derive(Clone,Copy)] + #[doc(hidden)] + pub struct sctx_info { + pub magic: u32, + pub size: u32, + padding: u64, + } + + #[repr(C, align(8))] + #[derive(Clone,Copy)] + #[doc(hidden)] + pub struct fpu_context { + pub regs: [u64; 32], + pub fcc: u64, + pub fcsr: u32, + } + + #[repr(C, align(16))] + #[derive(Clone,Copy)] + #[doc(hidden)] + pub struct lsx_context { + pub regs: [u64; 2*32], + pub fcc: u64, + pub fcsr: u32, + } + + #[repr(C, align(32))] + #[derive(Clone,Copy)] + #[doc(hidden)] + pub struct lasx_context { + pub regs: [u64; 4*32], + pub fcc: u64, + pub fcsr: u32, + } + + #[doc(hidden)] + pub type fpregset_t = fpu_context; } } diff --git a/third_party/rust/crash-context/src/linux/getcontext.rs b/third_party/rust/crash-context/src/linux/getcontext.rs index 93bb5fdaff94..4c4edd62e7ea 100644 --- a/third_party/rust/crash-context/src/linux/getcontext.rs +++ b/third_party/rust/crash-context/src/linux/getcontext.rs @@ -1,6 +1,6 @@ //! Implementation of [`getcontext`](https://man7.org/linux/man-pages/man3/getcontext.3.html) -extern "C" { +unsafe extern "C" { /// A portable implementation of [`getcontext`](https://man7.org/linux/man-pages/man3/getcontext.3.html) /// since it is not supported by all libc implementations, namely `musl`, as /// it has been deprecated from POSIX for over a decade @@ -20,5 +20,11 @@ cfg_if::cfg_if! { mod aarch64; } else if #[cfg(target_arch = "arm")] { mod arm; + } else if #[cfg(target_arch = "riscv64")] { + mod riscv64; + } else if #[cfg(target_arch = "s390x")] { + mod s390x; + } else if #[cfg(target_arch = "loongarch64")] { + mod loongarch64; } } diff --git a/third_party/rust/crash-context/src/linux/getcontext/arm.rs b/third_party/rust/crash-context/src/linux/getcontext/arm.rs index 0734634a3e52..83b4b75f1f63 100644 --- a/third_party/rust/crash-context/src/linux/getcontext/arm.rs +++ b/third_party/rust/crash-context/src/linux/getcontext/arm.rs @@ -46,7 +46,7 @@ std::arch::global_asm! { // Return 0 "mov r0, #0", - "bx lr", + "mov pc, lr", ".fnend", ".size crash_context_getcontext, . - crash_context_getcontext", diff --git a/third_party/rust/crash-context/src/linux/getcontext/loongarch64.rs b/third_party/rust/crash-context/src/linux/getcontext/loongarch64.rs new file mode 100644 index 000000000000..1e5fee140a72 --- /dev/null +++ b/third_party/rust/crash-context/src/linux/getcontext/loongarch64.rs @@ -0,0 +1,64 @@ +std::arch::global_asm! { + ".text", + ".global crash_context_getcontext", + ".hidden crash_context_getcontext", + ".type crash_context_getcontext, @function", + ".align 4", + ".cfi_startproc", +"crash_context_getcontext:", + + // Save general registers + "st.d $ra, $a0, 176", + "st.d $zero, $a0, 184", + "st.d $ra, $a0, 192", + "st.d $tp, $a0, 200", + "st.d $sp, $a0, 208", + "st.d $a0, $a0, 216", + "st.d $a1, $a0, 224", + "st.d $a2, $a0, 232", + "st.d $a3, $a0, 240", + "st.d $a4, $a0, 248", + "st.d $a5, $a0, 256", + "st.d $a6, $a0, 264", + "st.d $a7, $a0, 272", + "st.d $t0, $a0, 280", + "st.d $t1, $a0, 288", + "st.d $t2, $a0, 296", + "st.d $t3, $a0, 304", + "st.d $t4, $a0, 312", + "st.d $t5, $a0, 320", + "st.d $t6, $a0, 328", + "st.d $t7, $a0, 336", + "st.d $t8, $a0, 344", + "st.d $r21, $a0, 352", + "st.d $fp, $a0, 360", + "st.d $s0, $a0, 368", + "st.d $s1, $a0, 376", + "st.d $s2, $a0, 384", + "st.d $s3, $a0, 392", + "st.d $s4, $a0, 400", + "st.d $s5, $a0, 408", + "st.d $s6, $a0, 416", + "st.d $s7, $a0, 424", + "st.d $s8, $a0, 432", + + "li.w $t0, 0", // mcontext_t.__flags + "st.w $t0, $a0, 440", + "li.w $t0, 0", // sctx_info.magic + "st.w $t0, $a0, 448", + "li.w $t0, 0", // sctx_info.size + "st.w $t0, $a0, 452", + + "move $a1, $zero", // NULL + "addi.d $a2, $a0, 40", // UCONTEXT_SIGMASK_OFFSET + "li.w $a3, 8", // _NSIG8 + "move $a0, $zero", // SIG_BLOCK + "li.w $a7, 135", // __NR_rt_sigprocmask + "syscall 0", + + "move $a0, $zero", + "ret", + + ".cfi_endproc", + ".size crash_context_getcontext, . - crash_context_getcontext", +} diff --git a/third_party/rust/crash-context/src/linux/getcontext/riscv64.rs b/third_party/rust/crash-context/src/linux/getcontext/riscv64.rs new file mode 100644 index 000000000000..e84ac6a05c9e --- /dev/null +++ b/third_party/rust/crash-context/src/linux/getcontext/riscv64.rs @@ -0,0 +1,97 @@ +// UCONTEXT_SIGMASK_OFFSET = 40 +// MCONTEXT_GREGS_OFFSET = 168 +// MCONTEXT_GREGS_SIZE = 8 + +std::arch::global_asm! { + ".text", + ".attribute arch, \"rv64gc\"", + ".globl crash_context_getcontext", + ".hidden crash_context_getcontext", + ".type crash_context_getcontext, @function", + ".align 0", + ".cfi_startproc", +"crash_context_getcontext:", + + // Save general registers + "sd ra, 0xa8(a0)", + "sd ra, 0xb0(a0)", + "sd sp, 0xb8(a0)", + "sd gp, 0xc0(a0)", + "sd tp, 0xc8(a0)", + "sd t0, 0xd0(a0)", + "sd t1, 0xd8(a0)", + "sd t2, 0xe0(a0)", + "sd s0, 0xe8(a0)", + "sd s1, 0xf0(a0)", + "sd a0, 0xf8(a0)", + "sd a1, 0x100(a0)", + "sd a2, 0x108(a0)", + "sd a3, 0x110(a0)", + "sd a4, 0x118(a0)", + "sd a5, 0x120(a0)", + "sd a6, 0x128(a0)", + "sd a7, 0x130(a0)", + "sd s2, 0x138(a0)", + "sd s3, 0x140(a0)", + "sd s4, 0x148(a0)", + "sd s5, 0x150(a0)", + "sd s6, 0x158(a0)", + "sd s7, 0x160(a0)", + "sd s8, 0x168(a0)", + "sd s9, 0x170(a0)", + "sd s10, 0x178(a0)", + "sd s11, 0x180(a0)", + "sd t3, 0x188(a0)", + "sd t4, 0x190(a0)", + "sd t5, 0x198(a0)", + "sd t6 , 0x1a0(a0)", + + // Save floating point registers + "frsr a1", // Save CSR + "fsd ft0, 0x1a8(a0)", + "fsd ft1, 0x1b0(a0)", + "fsd ft2, 0x1b8(a0)", + "fsd ft3, 0x1c0(a0)", + "fsd ft4, 0x1c8(a0)", + "fsd ft5, 0x1d0(a0)", + "fsd ft6, 0x1d8(a0)", + "fsd ft7, 0x1e0(a0)", + "fsd fs0, 0x1e8(a0)", + "fsd fs1, 0x1f0(a0)", + "fsd fa0, 0x1f8(a0)", + "fsd fa1, 0x200(a0)", + "fsd fa2, 0x208(a0)", + "fsd fa3, 0x210(a0)", + "fsd fa4, 0x218(a0)", + "fsd fa5, 0x220(a0)", + "fsd fa6, 0x228(a0)", + "fsd fa7, 0x230(a0)", + "fsd fs2, 0x238(a0)", + "fsd fs3, 0x240(a0)", + "fsd fs4, 0x248(a0)", + "fsd fs5, 0x250(a0)", + "fsd fs6, 0x258(a0)", + "fsd fs7, 0x260(a0)", + "fsd fs8, 0x268(a0)", + "fsd fs9, 0x270(a0)", + "fsd fs10, 0x278(a0)", + "fsd fs11, 0x280(a0)", + "fsd ft8, 0x288(a0)", + "fsd ft9, 0x290(a0)", + "fsd ft10, 0x298(a0)", + "fsd ft11, 0x2a0(a0)", + "sw a1, 0x2a8(a0)", + + "mv a1, zero", + "add a2, a0, 40", // UCONTEXT_SIGMASK_OFFSET + "li a3, 8", // _NSIG8 + "mv a0, zero", + "li a7, 135", // __NR_rt_sigprocmask + "ecall", + + "mv a0, zero", + "ret", + + ".cfi_endproc", + ".size crash_context_getcontext, . - crash_context_getcontext", +} diff --git a/third_party/rust/crash-context/src/linux/getcontext/s390x.rs b/third_party/rust/crash-context/src/linux/getcontext/s390x.rs new file mode 100644 index 000000000000..9e7328435531 --- /dev/null +++ b/third_party/rust/crash-context/src/linux/getcontext/s390x.rs @@ -0,0 +1,58 @@ +std::arch::global_asm! { + ".text", + ".global crash_context_getcontext", + ".hidden crash_context_getcontext", + ".type crash_context_getcontext, @function", + ".align 8", + ".cfi_startproc", + "crash_context_getcontext:", + + "lgr %r0,%r2", + + /* rt_sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask, sigsetsize). */ + "la %r4,384(%r2)", + "la %r2,0", + "slgr %r3,%r3", + "lghi %r5,8", + "lghi %r1,175", + "svc 0", + + /* Store fpu context. */ + "lgr %r1,%r0", + "stfpc 248(%r1)", + "std %f0,256(%r1)", + "std %f1,264(%r1)", + "std %f2,272(%r1)", + "std %f3,280(%r1)", + "std %f4,288(%r1)", + "std %f5,296(%r1)", + "std %f6,304(%r1)", + "std %f7,312(%r1)", + "std %f8,320(%r1)", + "std %f9,328(%r1)", + "std %f10,336(%r1)", + "std %f11,344(%r1)", + "std %f12,352(%r1)", + "std %f13,360(%r1)", + "std %f14,368(%r1)", + "std %f15,376(%r1)", + + /* Set __getcontext return value to 0. */ + "slgr %r2,%r2", + + /* Store access registers. */ + "stam %a0,%a15,184(%r1)", + + /* Store general purpose registers. */ + "stmg %r0,%r15,56(%r1)", + + /* Store psw mask to 0x0 and addr to return address. Then the address + can be retrieved from the ucontext structure in the same way as if it + is created by kernel and passed to a signal-handler. */ + "stg %r2,40(%r1)", + "stg %r14,48(%r1)", + "br %r14", + + ".cfi_endproc", + ".size crash_context_getcontext, . - crash_context_getcontext", +} diff --git a/third_party/rust/crash-context/src/linux/getcontext/x86_64.rs b/third_party/rust/crash-context/src/linux/getcontext/x86_64.rs index 2ecbf2c24c9c..ee759f8e3f04 100644 --- a/third_party/rust/crash-context/src/linux/getcontext/x86_64.rs +++ b/third_party/rust/crash-context/src/linux/getcontext/x86_64.rs @@ -32,7 +32,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // adding certain lines/blocks of asm based using cfg https://github.com/rust-lang/rust/issues/15701 // and they're not really inputs, just literals, so...yah -#[cfg(any(target_os = "linux", target_os = "android"))] +#![cfg(any(target_os = "linux", target_os = "android"))] // Unfortunately, the asm! macro has a few really annoying limitations at the // moment diff --git a/third_party/rust/crash-context/src/mac/ipc.rs b/third_party/rust/crash-context/src/mac/ipc.rs index cb5fb2fcf172..e83eb9eb2ba6 100644 --- a/third_party/rust/crash-context/src/mac/ipc.rs +++ b/third_party/rust/crash-context/src/mac/ipc.rs @@ -15,13 +15,13 @@ use crate::CrashContext; use mach2::{ bootstrap, kern_return::KERN_SUCCESS, mach_port, message as msg, port, task, - traps::mach_task_self, + task_special_ports::TASK_BOOTSTRAP_PORT, traps::mach_task_self, }; pub use mach2::{kern_return::kern_return_t, message::mach_msg_return_t}; use std::{ffi::CStr, time::Duration}; -extern "C" { - /// From , there is no binding for this in mach2 +unsafe extern "C" { + /// From ``, there is no binding for this in mach2 pub fn pid_for_task(task: port::mach_port_name_t, pid: *mut i32) -> kern_return_t; } @@ -99,7 +99,7 @@ struct CrashContextMessage { /// The optional exception subcode exception_subcode: u64, /// We don't actually send this, but it's tacked on by the kernel :( - trailer: MachMsgTrailer, + _trailer: MachMsgTrailer, } const FLAG_HAS_EXCEPTION: u32 = 0x1; @@ -110,6 +110,7 @@ const FLAG_HAS_SUBCODE: u32 = 0x2; struct AcknowledgementMessage { head: MachMsgHeader, result: u32, + _trailer: MachMsgTrailer, } /// An error that can occur while interacting with mach ports @@ -175,7 +176,7 @@ impl Client { let mut task_bootstrap_port = 0; kern!(task::task_get_special_port( mach_task_self(), - task::TASK_BOOTSTRAP_PORT, + TASK_BOOTSTRAP_PORT, &mut task_bootstrap_port )); @@ -235,7 +236,8 @@ impl Client { head: MachMsgHeader { bits: msg::MACH_MSG_TYPE_COPY_SEND | msg::MACH_MSGH_BITS_COMPLEX, // We don't send the trailer, that's added by the kernel - size: std::mem::size_of::() as u32 - 8, + size: std::mem::size_of::() as u32 + - std::mem::size_of::() as u32, remote_port: self.port, local_port: port::MACH_PORT_NULL, voucher_port: port::MACH_PORT_NULL, @@ -257,7 +259,7 @@ impl Client { exception_subcode, // We don't actually send this but I didn't feel like making // two types - trailer: MachMsgTrailer { kind: 0, size: 8 }, + _trailer: MachMsgTrailer { kind: 0, size: 8 }, }; // Try to actually send the message to the Server @@ -314,7 +316,7 @@ impl Server { let mut task_bootstrap_port = 0; kern!(task::task_get_special_port( mach_task_self(), - task::TASK_BOOTSTRAP_PORT, + TASK_BOOTSTRAP_PORT, &mut task_bootstrap_port )); @@ -441,13 +443,15 @@ impl Acknowledger { let mut msg = AcknowledgementMessage { head: MachMsgHeader { bits: msg::MACH_MSG_TYPE_COPY_SEND, - size: std::mem::size_of::() as u32, + size: std::mem::size_of::() as u32 + - std::mem::size_of::() as u32, remote_port: port, local_port: port::MACH_PORT_NULL, voucher_port: port::MACH_PORT_NULL, id: 0, }, result: ack, + _trailer: MachMsgTrailer { kind: 0, size: 8 }, }; // Try to actually send the message @@ -487,21 +491,23 @@ impl AckReceiver { /// Performs syscalls. Only used internally hence the entire function being /// marked unsafe. unsafe fn new() -> Result { - let mut port = 0; - kern!(mach_port::mach_port_allocate( - mach_task_self(), - port::MACH_PORT_RIGHT_RECEIVE, - &mut port - )); + unsafe { + let mut port = 0; + kern!(mach_port::mach_port_allocate( + mach_task_self(), + port::MACH_PORT_RIGHT_RECEIVE, + &mut port + )); - kern!(mach_port::mach_port_insert_right( - mach_task_self(), - port, - port, - msg::MACH_MSG_TYPE_MAKE_SEND - )); + kern!(mach_port::mach_port_insert_right( + mach_task_self(), + port, + port, + msg::MACH_MSG_TYPE_MAKE_SEND + )); - Ok(Self { port }) + Ok(Self { port }) + } } /// Waits for the specified duration to receive a result from the [`Server`] @@ -516,30 +522,33 @@ impl AckReceiver { /// Performs syscalls. Only used internally hence the entire function being /// marked unsafe. unsafe fn recv_ack(&mut self, timeout: Option) -> Result { - let mut ack = AcknowledgementMessage { - head: MachMsgHeader { - bits: 0, - size: std::mem::size_of::() as u32, - remote_port: port::MACH_PORT_NULL, - local_port: self.port, - voucher_port: port::MACH_PORT_NULL, - id: 0, - }, - result: 0, - }; + unsafe { + let mut ack = AcknowledgementMessage { + head: MachMsgHeader { + bits: 0, + size: std::mem::size_of::() as u32, + remote_port: port::MACH_PORT_NULL, + local_port: self.port, + voucher_port: port::MACH_PORT_NULL, + id: 0, + }, + result: 0, + _trailer: MachMsgTrailer { kind: 0, size: 8 }, + }; - // Wait for a response from the Server - msg!(msg::mach_msg( - ((&mut ack.head) as *mut MachMsgHeader).cast(), - msg::MACH_RCV_MSG | msg::MACH_RCV_TIMEOUT, - 0, - ack.head.size, - self.port, - timeout.map(|t| t.as_millis() as u32).unwrap_or_default(), - port::MACH_PORT_NULL - )); + // Wait for a response from the Server + msg!(msg::mach_msg( + ((&mut ack.head) as *mut MachMsgHeader).cast(), + msg::MACH_RCV_MSG | msg::MACH_RCV_TIMEOUT, + 0, + ack.head.size, + self.port, + timeout.map(|t| t.as_millis() as u32).unwrap_or_default(), + port::MACH_PORT_NULL + )); - Ok(ack.result) + Ok(ack.result) + } } } diff --git a/third_party/rust/crash-context/src/mac/resource.rs b/third_party/rust/crash-context/src/mac/resource.rs index c93acfe97a40..bf4890a0b864 100644 --- a/third_party/rust/crash-context/src/mac/resource.rs +++ b/third_party/rust/crash-context/src/mac/resource.rs @@ -17,7 +17,7 @@ pub enum ResourceException { Cpu(CpuResourceException), /// This is sent by the kernel when the platform idle wakeups monitor is tripped. Possibly fatal. Wakeups(WakeupsResourceException), - /// This is sent by the kernel when a task crosses its high watermark memory limit. Never fatal at least on current MacOS versions. + /// This is sent by the kernel when a task crosses its high watermark memory limit. Never fatal at least on current `MacOS` versions. Memory(MemoryResourceException), /// This is sent by the kernel when a task crosses its I/O limits. Never fatal. Io(IoResourceException), @@ -27,7 +27,7 @@ pub enum ResourceException { /// filled its port space. Always fatal. Ports(PortsResourceException), /// An unknown resource kind due to an addition to the set of possible - /// resource exception kinds in exc_resource.h + /// resource exception kinds in `exc_resource.h` Unknown { kind: u8, flavor: u8 }, } diff --git a/third_party/rust/crash-context/src/windows.rs b/third_party/rust/crash-context/src/windows.rs index 231a608c08a8..076a6b37bfdc 100644 --- a/third_party/rust/crash-context/src/windows.rs +++ b/third_party/rust/crash-context/src/windows.rs @@ -5,7 +5,7 @@ pub struct CrashContext { /// Note that this is a pointer into the actual memory of the crashed process, /// and is a pointer to an [EXCEPTION_POINTERS](https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_pointers) pub exception_pointers: *const EXCEPTION_POINTERS, - /// The top level exception code from the exception_pointers. This is provided + /// The top level exception code from the `exception_pointers`. This is provided /// so that external processes don't need to use `ReadProcessMemory` to inspect /// the exception code pub exception_code: i32, @@ -16,7 +16,7 @@ pub struct CrashContext { } #[link(name = "kernel32")] -extern "system" { +unsafe extern "system" { #[link_name = "RtlCaptureContext"] pub fn capture_context(ctx_rec: *mut CONTEXT); } diff --git a/third_party/rust/mach2/.cargo-checksum.json b/third_party/rust/mach2/.cargo-checksum.json index a3fb83ed6650..b4a725ee0106 100644 --- a/third_party/rust/mach2/.cargo-checksum.json +++ b/third_party/rust/mach2/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo_vcs_info.json":"1a9e945be639994bb2058763dfe3d35e2755a68c8701ca602bc260f31ba21be9","Cargo.lock":"ce3f068be5f36927a9592b2f54548d9009c516e3f497a807ae048bb0c41507f3","Cargo.toml":"e6cb1c9aa2b65d61801e0f03de848525a9f7104234db25d0b1c9fa337b372626","Cargo.toml.orig":"c8b9a1dc0ab69809f55073be4490d9216370d7880e9c36507a41fbbc37091582","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-BSD":"044983df14c97f2f9570766aaf977b3cdfc4a06cf1f36b776331c5ff89b4fb89","LICENSE-MIT":"3f9f0f7e5a5911a8042e32c83ff5d061ce1ffd02e8a207ec2135a44ad73b4191","README.md":"c2cb79f8e79e22b13e4c25e43829bf578ef25a3a338d5553081a1e5f39556fa8","src/boolean.rs":"1d24ea9872748881cd7269a383a7c344e3a650df23f0e44e3b6c266fb8205d9a","src/bootstrap.rs":"a5ab69d74ad8bfb8fad1cb45c8c571977c0bf907a70e767309a437580cee184c","src/clock.rs":"a33c1bfb2f174abb695d164c469ee744be52fec4bc345656e6027d063e150d71","src/clock_priv.rs":"a8e6a96896a94eda67c9fb6e45c564581a711cc9fdcf7674251bb6c0c28b47c2","src/clock_reply.rs":"bac04b6602dcdd4daac8e3a0a1e56fa4b6de20cf2c3fe7bb583358166aca8a3b","src/clock_types.rs":"d55d1d2a953e477f9dd064bd684b118235aa7bd79de85cdeaf75e21510aaaefa","src/dyld_kernel.rs":"566a17f597aa29619a1ce15f6b22577fc70ac5356f96e00fddbcb28560a5c83c","src/exc.rs":"2246493bef2c596b92f115ab673a10d50c6003d11abb8e73d7707ebc19e8ae5a","src/exception_types.rs":"c7894831d73145adb1a4b5d2a5d0b346f2b2dc05382b97f2f3f0275d337f6dfc","src/kern_return.rs":"153339995674136ef05d9595bdcf831595db0d0714a737ecd1ccd45391c56657","src/lib.rs":"4c8a9d906303a67246b32b6f96228bff6b045deb0a68073a7f8d1061c8d072bd","src/mach_init.rs":"df49bd287fd05fb74bc76254df7607fad0d6b90cb20da803e9f9a1dc2fcfe2fc","src/mach_port.rs":"d71ef4f4875824410d2d829474303926a56e3218a00fbe04024801a3245b67ad","src/mach_time.rs":"b9493e820acf21fee1f6e7e82a510d887925dc1117d6b71b681acc40cfa776af","src/mach_types.rs":"e2d17741ebcdcdff9686ec9ee5c90fb7a150ce990979507da01c351771fb3a19","src/memory_object_types.rs":"6fcb446c00ddd5ef4920efe618bd89df2e87f7ae3cf660a2bc1d25cf1f331dc2","src/message.rs":"126dfcdef0f690cd17f4403528403721b81f7e6a95821eff867d11dd6bfa9718","src/port.rs":"7ef8af905edd7d0de9c11813d6cf56ae82171e85efdde2c986622be0e7debf6f","src/structs.rs":"132e21e91313e6ec13e3ad5ed9c71852e8a55fbbaba449dbb1b3ca889bed4889","src/task.rs":"282ea602db2d08711785e0050a06b322a3fe4a4aac34b3c9116fe13e033898dd","src/task_info.rs":"cf87cffe567fee8871e0ce9762b7d8bbd5058dfbb309678d382149dedbe7f14a","src/thread_act.rs":"647198e0f9e3fe409a0610ee98560de3af4f152bcc4761f943e67723193b8a25","src/thread_policy.rs":"e8999b03a03d398a456056274ed8ebc4c38a1cbbbba2da931503885da0e9c2e3","src/thread_status.rs":"3fe98fadd61ce01b4f9dc3bc0ef8c9496798f0147822a4ddffe5d0eaf2f32c0a","src/traps.rs":"59a65e0cc3cf67d79180eabfe31248287afa7a2daa58ec367ebb6302ff39f4cb","src/vm.rs":"1e3fe55704dbbc0c287ad543f5642389a823539f72b337cbff726d6927566b23","src/vm_attributes.rs":"7f73f41572d1ca854b45199a17e9008197f3898cfe6a82dba6d14293d49269c6","src/vm_behavior.rs":"a5d195a52602f5ebe2991774c2390a6f20f1bfa82168dd62e88f2804134da1f3","src/vm_inherit.rs":"dbc7432350869733d6e7cf1da8617d97aafbeb1afcb1bdc60ed7ab53e37abf61","src/vm_page_size.rs":"1cd209f8f6fbc4d3b7a44b77f5a3c53c578f357199e3c616b2386a63e5bfe70a","src/vm_prot.rs":"65e5f7179e155c600cec1a1b3e030f2d0d6b446a6ec9ebad0d04f56ccd884a86","src/vm_purgable.rs":"e32963f20905c4edd1cfee364ad489ef646ad7d401967d0ed9e1e7ed6cd57e5d","src/vm_region.rs":"905daa12391c0c3bca9200ceaecbd02dd03550bbdc9c3342dceeeb6e4056184f","src/vm_statistics.rs":"abee2c810b13fa007a7e38dd2b3d6460005e9e78f5972e069d7fc3e0df80190e","src/vm_sync.rs":"e6006b66f0fa1a06c5e853d765a9366aab85009cc77a095b93f902330cf4ec81","src/vm_types.rs":"a47f71193172ce233018dfd40de2b9a56cdfcdfb18e04c1c0761cb6fc36f51b8"},"package":"6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"1112f481219e54febaa8388dc1906f36c3793c58444a17f8ed979a34a65c88ba","Cargo.lock":"e24197c8db2a7459c43c1911fd30ad548f40dea88d5de8ed27e13405d70eb157","Cargo.toml":"42129f41b7b2076b27752b0cc10634f6ba450edd6d7b9f33b633cbf02fdf3449","Cargo.toml.orig":"ffd83c0747a3efcbca2cb9b73cea21bf8e6d6c50c10ccf90557d74dbf0f6d6b9","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-BSD":"044983df14c97f2f9570766aaf977b3cdfc4a06cf1f36b776331c5ff89b4fb89","LICENSE-MIT":"3f9f0f7e5a5911a8042e32c83ff5d061ce1ffd02e8a207ec2135a44ad73b4191","README.md":"9e25ed91751192c227eeb9e23206c1d3d05aa2fac2c286186af12c54d1e24611","src/boolean.rs":"8755de7dfd6b9daadaea0db765cb1bcab14172591ca3bcae8e83bfa73d712653","src/bootstrap.rs":"9edf64482ffd2b71c43a8435702bedc410fe1bb5437c8e18766f7927081a22cb","src/clock.rs":"b66f418394dbbf22ae93e9c4a33b8f1bc2f6c4bf6a0eb5ba51ee71fd556a7d7a","src/clock_priv.rs":"0c013d67488bbf1d464a4d012b8cb2c4b1e5aa1ef681a36eb0ba5fe1a5c33d75","src/clock_reply.rs":"ec9c23485169efd9db964bb2aee10c0064a26fa9514e1b9f8f3cef6485b7da19","src/clock_types.rs":"fbdc084b181b79c78376978b33d772411faf02e33250f2836799d67592cffb58","src/dyld.rs":"310b02d70b64e66ec4b92962c6021a2caa24b8b057a09c697f3a2b859195e59c","src/dyld_kernel.rs":"7073d2660bf69c598443cbfd981f9b7de591ae082ae7234793897ec34632e043","src/error.rs":"edd0d07c425fef75b799454ba0b495abd45937fc6e5bdb6550aa08710d6200a4","src/exc.rs":"beb530bc62c2359835ec1d5267c08ad1201bad192ab5bd4844211930473f5d8a","src/exception_types.rs":"88c17dfa6297b6021f4f518a3c6fdc26143f43b4728ec94d96b7c1916528b59e","src/kern_return.rs":"98b05ebdac9e0f6cc0de424b38395f4a0c28470483763cd3f2b0c802637747ef","src/lib.rs":"e6af92e269f09615f5463afeac46cca5c9f6038b97888ab2e95f0ea5afa922f1","src/loader.rs":"7918d97dcfaee2eb5ff5a5959f6aa596f6a23d1ca97f2e452d17e07590c1a803","src/mach_debug/ipc_info.rs":"79aa620191ff10851763a4959392883e51c8cfa3b85b24d58213d60066e3fab1","src/mach_debug/mod.rs":"02e9609d12a051989406b30f036f71aa53fc99a047ff7127dc77613102eb552b","src/mach_debug/zone_info.rs":"fc05e4f161bd6d5d161f0d05b4508cbdf5bb1eb8a353b689cbbd788228f4f97c","src/mach_init.rs":"f4512c0d400b5b88d1bfc606ad6d941056e639f9862d9e09e21d88a7c6b797ea","src/mach_port.rs":"4ec608d04f692e85d146f6c9f75ef112b0544b35f9f296f082cb2f2c064050e4","src/mach_time.rs":"4601c1b309f7576d278654dc93d3b22caae75ab57365f8e9a593381d7288fa33","src/mach_types.rs":"fc55ffacea09e2e349b44763c2cb67c619a871c04422dfe281d28c600132a983","src/mach_voucher_types.rs":"237ed654a6180af4b6d9cf52fb8c238ebaa4cf09ca690fefd1876d7d611dad84","src/memory_object_types.rs":"08aaf5a9503d4f606820938befe46c9b2b04b83e1e4b8f70956f433ec529b6f3","src/message.rs":"e3758af3d9b08d8852cecac8baaf8a25c86658232a71eb49ee8480f38cd9d961","src/mig.rs":"dee95e0d9be3cefd338b514a83a078a6f36faf23894c62ee5a35b7e274592ffc","src/ndr.rs":"353a941ca6e170bf08f2263b16483c27b6be4fc3fa1108da94f7930d32c807f9","src/notify.rs":"b050d1cf93f289de145e77a8470664e05399659c80216766091571a68fd74f32","src/policy.rs":"c0f7f7dff7d2745d617f00c59db4a0436e6215ae7950ec2c17ed16a99cd61e0f","src/port.rs":"b8501aab1c5235a3610b218d34710d72bc0110003376a0bc8284c777c9099307","src/semaphore.rs":"403ce9116ae63d237b6ddab0e2df9ff210b0ceeb4781b21faa5c6ab1f7f644bf","src/structs.rs":"0bc965f6a6933a5c7f6d3611632e836b9b23665950b830b1ee5b9081a0ffc7e6","src/sync_policy.rs":"f1d3896e93fb9a26f2a91596ef2e733b4960d352b3b7f4a55aaa4b65041880cd","src/task.rs":"6bd88b86ed1243ff5c37350e8aa92246e6a9ce296c2032c1b103be0513f56dc7","src/task_info.rs":"39b622c1ed10ce9023d25d9b3ffec26338679580762987d92c67b1adc2cae39e","src/task_inspect.rs":"e19fa77833a2ba3c16f0ae18dccdaf92bfd9781f58453afaedf61aaff57802de","src/task_special_ports.rs":"2c56549572c9471669a140fab7f211fd50fc9e9716d346b3f19f1e8537e28e12","src/thread_act.rs":"1f4de35110f9096b55c3042de9f99e5a45f7de0c70cefea2b6af69614b9ab722","src/thread_policy.rs":"07098e621716ed04dcac1b2068fa4320a03faea95c92f460c78a8c01b8870d53","src/thread_special_ports.rs":"5bc64117b3ee5bc6ebd550079b9beaad8f20d63763a7321e05917e56ec9159b7","src/thread_state.rs":"fe37378dd49c02ee51ac41f6db718c2cff8250d564fa1e3de58eb8ef441c6cdc","src/thread_status.rs":"a2d4a0c0dd3f9c3df35262fcc1e396f789e4ca65b80702f20af4c039ede3c81c","src/thread_switch.rs":"3baeab8a77e6592d2068907d7588f6b0d2be629af78287db41bb8730f066d85b","src/time_value.rs":"6ad86d49c52be0f6c20f247bee1da52c110a71feef18f20d953ea855f0dbbc9c","src/traps.rs":"c033493f153103f4fc6cb4c4c7fe0d1967ab8a535a0013486d7f543761a55cf3","src/vm.rs":"74013e2a6e9156df556e147b0d72611e0a800b940b636a305072bb5bdffde4c4","src/vm_attributes.rs":"dae9dd28fd69b67732496390c8eca9086e2af366df2539291332547dd38a8eda","src/vm_behavior.rs":"54fe4a65d58e72c66228817ba17408638a696b9bb037fe0118223b0764406cae","src/vm_inherit.rs":"645a890b4e956cf873ff48375a3e37bac56621ab10eef4d6d594a3e99c8637bb","src/vm_page_size.rs":"ed24b32ed8d91069eaa2f108892a074fb75993191cf335472f694903c0adee96","src/vm_prot.rs":"7940a4ca21bb9587d7e4a5af3ae82932317943949bf6783bc413ee770af95e5e","src/vm_purgable.rs":"613a295c4a8b961391133219e4f0bdecc2c2967553e75074729d129313b917be","src/vm_region.rs":"383ec5a3dbfe99edaa65854df4c241198b40c2ec34759dc7b4f18d65df5961f2","src/vm_statistics.rs":"a93e8b47480729af8afaf7da17bf2e27f8f61e848f2fb7c6c97c6e0f55a56501","src/vm_sync.rs":"2ece70fbfc7bd2460ab9f0c3ff1b1c62517573c86f0a3b157a1c98c7a4aac449","src/vm_types.rs":"7a9d367795e0b7dbd3ff15e7e9ceddf8b3d68487a3b4cee113fc701d1d3c7445"},"package":"dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b"} \ No newline at end of file diff --git a/third_party/rust/mach2/.cargo_vcs_info.json b/third_party/rust/mach2/.cargo_vcs_info.json index 1d028a5d92be..1d0bbc19b03a 100644 --- a/third_party/rust/mach2/.cargo_vcs_info.json +++ b/third_party/rust/mach2/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "11476e373ca8ab203234b67788ae00e703112a41" + "sha1": "74fabb1965ef580abfcbf5aa75368c5930caebb8" }, "path_in_vcs": "" } \ No newline at end of file diff --git a/third_party/rust/mach2/Cargo.lock b/third_party/rust/mach2/Cargo.lock index 4d34198dab5e..6b19ae96fbba 100644 --- a/third_party/rust/mach2/Cargo.lock +++ b/third_party/rust/mach2/Cargo.lock @@ -1,16 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 - -[[package]] -name = "libc" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +version = 4 [[package]] name = "mach2" -version = "0.4.1" -dependencies = [ - "libc", -] +version = "0.6.0" diff --git a/third_party/rust/mach2/Cargo.toml b/third_party/rust/mach2/Cargo.toml index 422e53094c61..285083814f48 100644 --- a/third_party/rust/mach2/Cargo.toml +++ b/third_party/rust/mach2/Cargo.toml @@ -10,14 +10,20 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2015" +edition = "2024" name = "mach2" -version = "0.4.1" +version = "0.6.0" +build = false include = [ "src/**/*", "LICENSE-*", "README.md", ] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "A Rust interface to the user-space API of the Mach 3.0 kernel that underlies OSX." readme = "README.md" keywords = [ @@ -35,15 +41,12 @@ license = "BSD-2-Clause OR MIT OR Apache-2.0" repository = "https://github.com/JohnTitor/mach2" [package.metadata.docs.rs] -default-target = "x86_64-apple-darwin" +default-target = "aarch64-apple-darwin" [features] default = [] unstable = [] -[target."cfg(any(target_os = \"macos\", target_os = \"ios\"))".dependencies.libc] -version = "0.2" -default-features = false - -[badges.maintenance] -status = "passively-maintained" +[lib] +name = "mach2" +path = "src/lib.rs" diff --git a/third_party/rust/mach2/Cargo.toml.orig b/third_party/rust/mach2/Cargo.toml.orig index ccced74d3a90..180a940c3695 100644 --- a/third_party/rust/mach2/Cargo.toml.orig +++ b/third_party/rust/mach2/Cargo.toml.orig @@ -1,21 +1,15 @@ [package] name = "mach2" -version = "0.4.1" +version = "0.6.0" license = "BSD-2-Clause OR MIT OR Apache-2.0" description = "A Rust interface to the user-space API of the Mach 3.0 kernel that underlies OSX." repository = "https://github.com/JohnTitor/mach2" readme = "README.md" keywords = ["kernel", "macos", "darwin"] categories = ["api-bindings", "external-ffi-bindings", "no-std", "os"] -edition = "2015" +edition = "2024" include = ["src/**/*", "LICENSE-*", "README.md"] -[badges] -maintenance = { status = "passively-maintained" } - -[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] -libc = { version = "0.2", default-features = false } - [features] default = [] # Uses newer APIs @@ -25,4 +19,4 @@ unstable = [] members = ["mach-test"] [package.metadata.docs.rs] -default-target = "x86_64-apple-darwin" +default-target = "aarch64-apple-darwin" diff --git a/third_party/rust/mach2/README.md b/third_party/rust/mach2/README.md index f297ebe6330f..824a4bf1566b 100644 --- a/third_party/rust/mach2/README.md +++ b/third_party/rust/mach2/README.md @@ -8,7 +8,7 @@ A Rust interface to the **user-space** API of the Mach 3.0 kernel exposed in This library does not expose the **kernel-space** API of the Mach 3.0 kernel exposed in -`SDK/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/mach`. +`SDK/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/mach`. That is, if you are writing a kernel-resident device drivers or some other kernel extensions you have to use something else. The user-space kernel API is @@ -22,8 +22,8 @@ Add the following to your `Cargo.toml` to conditionally include mach on those platforms that support it. ```toml -[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.mach] -version = "0.4" +[target.'cfg(target_vendor = "apple")'.dependencies.mach] +version = "0.6" ``` Available crate feature: @@ -31,7 +31,6 @@ Available crate feature: * **unstable** (disabled by default): Exposes newly changed APIs. Enabling this may bring breaking changes (see the breaking change policy). - ### Breaking change policy We do the following steps when an item is changed/removed on latest toolchain: @@ -46,17 +45,42 @@ we expose the newer one, i.e. `4`, under `unstable` first. So the `unstable` users should notice the change on the first release since deprecating. After a month or more, all the users should notice it. +## Examples + +Examples can be found in the [examples](./examples) directory of this repository. + +Since [`examples/dump_process_registers.rs`](./examples/dump_process_registers.rs) makes use of the `task_for_pid()` function, which requires elevated privileges, it is necessary to disable System Integrity Protection (SIP) and to be part of the `admin` or `_developer` group in order to run the example. However, do note that disabling SIP is in no way encouraged, and should only be done for development/debugging purposes. + +1. Reboot macOS in recovery mode. +2. Click on `Options`. +3. Log in to your user. +4. In the menu click on `Utilities` and then `Terminal`. +5. In the terminal type the following command to disable SIP: `csrutil disable` (`csrutil enable` to re-enable SIP). +6. Reboot your machine. + +To run the example, build it as follows: + +``` +cargo b --example dump_process_registers +``` + +Then run it using `sudo`: + +``` +sudo ./target/debug/examples/dump_process_registers +``` + ## Platform support The following table describes the current CI set-up: -| Target | Min. Rust | XCode | build | ctest | run | -|-------------------------|-----------|-----------------|-------|-------|-----| -| `x86_64-apple-darwin` | 1.33.0 | 10.3.0 - 13.1.0 | ✓ | ✓ | ✓ | -| `aarch64-apple-darwin` | nightly | 13.1.0 | ✓ | - | - | -| `aarch64-apple-ios` | nightly | 13.1.0 | ✓ | - | - | -| `aarch64-apple-ios-sim` | nightly | 13.1.0 | ✓ | - | - | -| `x86_64-apple-ios` | nightly | 13.1.0 | ✓ | - | - | +| Target | XCode | build | ctest | run | +|-------------------------|--------|-------|-------|-----| +| `x86_64-apple-darwin` | 26.1.0 | ✓ | ✓ | ✓ | +| `aarch64-apple-darwin` | 26.1.0 | ✓ | ✓ | ✓ | +| `aarch64-apple-ios` | 26.1.0 | ✓ | - | - | +| `aarch64-apple-ios-sim` | 26.1.0 | ✓ | - | - | +| `x86_64-apple-ios` | 26.1.0 | ✓ | - | - | ## License diff --git a/third_party/rust/mach2/src/boolean.rs b/third_party/rust/mach2/src/boolean.rs index cedffa122029..2fd0e069ec32 100644 --- a/third_party/rust/mach2/src/boolean.rs +++ b/third_party/rust/mach2/src/boolean.rs @@ -1,7 +1,7 @@ //! This module corresponds to `mach/i386/boolean.h`. #[cfg(target_arch = "x86_64")] -pub type boolean_t = ::libc::c_uint; +pub type boolean_t = core::ffi::c_uint; #[cfg(not(target_arch = "x86_64"))] -pub type boolean_t = ::libc::c_int; +pub type boolean_t = core::ffi::c_int; diff --git a/third_party/rust/mach2/src/bootstrap.rs b/third_party/rust/mach2/src/bootstrap.rs index 3642b94627d9..aaf3719ed8db 100644 --- a/third_party/rust/mach2/src/bootstrap.rs +++ b/third_party/rust/mach2/src/bootstrap.rs @@ -1,42 +1,43 @@ //! This module corresponds to `bootstrap.h` -use boolean::boolean_t; -use kern_return::kern_return_t; -use port::mach_port_t; +use crate::boolean::boolean_t; +use crate::kern_return::kern_return_t; +use crate::port::mach_port_t; +use core::ffi::{c_char, c_int, c_uint}; -pub const BOOTSTRAP_MAX_NAME_LEN: ::libc::c_uint = 128; -pub const BOOTSTRAP_MAX_CMD_LEN: ::libc::c_uint = 512; +pub const BOOTSTRAP_MAX_NAME_LEN: c_uint = 128; +pub const BOOTSTRAP_MAX_CMD_LEN: c_uint = 512; -pub const BOOTSTRAP_MAX_LOOKUP_COUNT: ::libc::c_uint = 20; +pub const BOOTSTRAP_MAX_LOOKUP_COUNT: c_uint = 20; -pub const BOOTSTRAP_SUCCESS: ::libc::c_uint = 0; -pub const BOOTSTRAP_NOT_PRIVILEGED: ::libc::c_uint = 1100; -pub const BOOTSTRAP_NAME_IN_USE: ::libc::c_uint = 1101; -pub const BOOTSTRAP_UNKNOWN_SERVICE: ::libc::c_uint = 1102; -pub const BOOTSTRAP_SERVICE_ACTIVE: ::libc::c_uint = 1103; -pub const BOOTSTRAP_BAD_COUNT: ::libc::c_uint = 1104; -pub const BOOTSTRAP_NO_MEMORY: ::libc::c_uint = 1105; -pub const BOOTSTRAP_NO_CHILDREN: ::libc::c_uint = 1106; +pub const BOOTSTRAP_SUCCESS: c_uint = 0; +pub const BOOTSTRAP_NOT_PRIVILEGED: c_uint = 1100; +pub const BOOTSTRAP_NAME_IN_USE: c_uint = 1101; +pub const BOOTSTRAP_UNKNOWN_SERVICE: c_uint = 1102; +pub const BOOTSTRAP_SERVICE_ACTIVE: c_uint = 1103; +pub const BOOTSTRAP_BAD_COUNT: c_uint = 1104; +pub const BOOTSTRAP_NO_MEMORY: c_uint = 1105; +pub const BOOTSTRAP_NO_CHILDREN: c_uint = 1106; -pub const BOOTSTRAP_STATUS_INACTIVE: ::libc::c_uint = 0; -pub const BOOTSTRAP_STATUS_ACTIVE: ::libc::c_uint = 1; -pub const BOOTSTRAP_STATUS_ON_DEMAND: ::libc::c_uint = 2; +pub const BOOTSTRAP_STATUS_INACTIVE: c_uint = 0; +pub const BOOTSTRAP_STATUS_ACTIVE: c_uint = 1; +pub const BOOTSTRAP_STATUS_ON_DEMAND: c_uint = 2; -pub type name_t = [::libc::c_char; 128]; -pub type cmd_t = [::libc::c_char; 512]; +pub type name_t = [c_char; 128]; +pub type cmd_t = [c_char; 512]; pub type name_array_t = *mut name_t; -pub type bootstrap_status_t = ::libc::c_int; +pub type bootstrap_status_t = c_int; pub type bootstrap_status_array_t = *mut bootstrap_status_t; -pub type bootstrap_property_t = ::libc::c_uint; +pub type bootstrap_property_t = c_uint; pub type bootstrap_property_array_t = *mut bootstrap_property_t; pub type bool_array_t = *mut boolean_t; -extern "C" { +unsafe extern "C" { pub static bootstrap_port: mach_port_t; pub fn bootstrap_create_server( bp: mach_port_t, - server_cmd: *mut ::libc::c_char, - server_uid: ::libc::uid_t, + server_cmd: *mut c_char, + server_uid: c_uint, on_demand: boolean_t, server_port: *mut mach_port_t, ) -> kern_return_t; @@ -49,28 +50,28 @@ extern "C" { pub fn bootstrap_parent(bp: mach_port_t, parent_port: *mut mach_port_t) -> kern_return_t; pub fn bootstrap_register( bp: mach_port_t, - service_name: *mut ::libc::c_char, + service_name: *mut c_char, sp: mach_port_t, ) -> kern_return_t; pub fn bootstrap_create_service( bp: mach_port_t, - service_name: *mut ::libc::c_char, + service_name: *mut c_char, sp: *mut mach_port_t, ) -> kern_return_t; pub fn bootstrap_check_in( bp: mach_port_t, - service_name: *const ::libc::c_char, + service_name: *const c_char, sp: *mut mach_port_t, ) -> kern_return_t; pub fn bootstrap_look_up( bp: mach_port_t, - service_name: *const ::libc::c_char, + service_name: *const c_char, sp: *mut mach_port_t, ) -> kern_return_t; pub fn bootstrap_status( bp: mach_port_t, - service_name: *mut ::libc::c_char, + service_name: *mut c_char, service_active: *mut bootstrap_status_t, ) -> kern_return_t; - pub fn bootstrap_strerror(r: kern_return_t) -> *const ::libc::c_char; + pub fn bootstrap_strerror(r: kern_return_t) -> *const c_char; } diff --git a/third_party/rust/mach2/src/clock.rs b/third_party/rust/mach2/src/clock.rs index 1d5437951dd2..3f70755389ca 100644 --- a/third_party/rust/mach2/src/clock.rs +++ b/third_party/rust/mach2/src/clock.rs @@ -1,13 +1,13 @@ //! This module roughly corresponds to `mach/clock.h`. +use crate::clock_types::{alarm_type_t, clock_attr_t, clock_flavor_t, mach_timespec_t}; +use crate::kern_return::kern_return_t; +use crate::mach_types::{clock_reply_t, clock_serv_t}; +use crate::message::mach_msg_type_number_t; +use core::ffi::c_uint; -pub const clock_MSG_COUNT: ::libc::c_uint = 3; +pub const clock_MSG_COUNT: c_uint = 3; -use clock_types::{alarm_type_t, clock_attr_t, clock_flavor_t, mach_timespec_t}; -use kern_return::kern_return_t; -use mach_types::{clock_reply_t, clock_serv_t}; -use message::mach_msg_type_number_t; - -extern "C" { +unsafe extern "C" { pub fn clock_get_time( clock_serv: clock_serv_t, cur_time: *mut mach_timespec_t, diff --git a/third_party/rust/mach2/src/clock_priv.rs b/third_party/rust/mach2/src/clock_priv.rs index d534e79a3c20..fd952c4171a5 100644 --- a/third_party/rust/mach2/src/clock_priv.rs +++ b/third_party/rust/mach2/src/clock_priv.rs @@ -1,11 +1,11 @@ //! This module roughly corresponds to `mach/clock_priv.h`. -use clock_types::{clock_attr_t, clock_flavor_t, mach_timespec_t}; -use kern_return::kern_return_t; -use mach_types::clock_ctrl_t; -use message::mach_msg_type_number_t; +use crate::clock_types::{clock_attr_t, clock_flavor_t, mach_timespec_t}; +use crate::kern_return::kern_return_t; +use crate::mach_types::clock_ctrl_t; +use crate::message::mach_msg_type_number_t; -extern "C" { +unsafe extern "C" { pub fn clock_set_time(clock_ctrl: clock_ctrl_t, new_time: mach_timespec_t) -> kern_return_t; pub fn clock_set_attributes( clock_ctrl: clock_ctrl_t, diff --git a/third_party/rust/mach2/src/clock_reply.rs b/third_party/rust/mach2/src/clock_reply.rs index 854eb22bf581..84c5a51e2650 100644 --- a/third_party/rust/mach2/src/clock_reply.rs +++ b/third_party/rust/mach2/src/clock_reply.rs @@ -1,11 +1,11 @@ //! This module roughly corresponds to `mach/clock_reply.h`. -use clock_types::{alarm_type_t, mach_timespec_t}; -use kern_return::kern_return_t; -use mach_types::clock_reply_t; -use message::mach_msg_type_name_t; +use crate::clock_types::{alarm_type_t, mach_timespec_t}; +use crate::kern_return::kern_return_t; +use crate::mach_types::clock_reply_t; +use crate::message::mach_msg_type_name_t; -extern "C" { +unsafe extern "C" { pub fn clock_alarm_reply( alarm_port: clock_reply_t, alarm_portPoly: mach_msg_type_name_t, diff --git a/third_party/rust/mach2/src/clock_types.rs b/third_party/rust/mach2/src/clock_types.rs index c0949c83158b..13bcc28fb364 100644 --- a/third_party/rust/mach2/src/clock_types.rs +++ b/third_party/rust/mach2/src/clock_types.rs @@ -1,55 +1,56 @@ //! This module roughly corresponds to `mach/clock_types.h`. +use core::ffi::{c_int, c_uint, c_ulonglong}; -pub type alarm_type_t = ::libc::c_int; -pub type sleep_type_t = ::libc::c_int; -pub type clock_id_t = ::libc::c_int; -pub type clock_flavor_t = ::libc::c_int; -pub type clock_attr_t = *mut ::libc::c_int; -pub type clock_res_t = ::libc::c_int; +pub type alarm_type_t = c_int; +pub type sleep_type_t = c_int; +pub type clock_id_t = c_int; +pub type clock_flavor_t = c_int; +pub type clock_attr_t = *mut c_int; +pub type clock_res_t = c_int; #[repr(C)] #[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] pub struct mach_timespec { - pub tv_sec: ::libc::c_uint, + pub tv_sec: c_uint, pub tv_nsec: clock_res_t, } pub type mach_timespec_t = mach_timespec; -pub const SYSTEM_CLOCK: ::libc::c_uint = 0; -pub const CALENDAR_CLOCK: ::libc::c_uint = 1; -pub const REALTIME_CLOCK: ::libc::c_uint = 0; +pub const SYSTEM_CLOCK: c_uint = 0; +pub const CALENDAR_CLOCK: c_uint = 1; +pub const REALTIME_CLOCK: c_uint = 0; -pub const CLOCK_GET_TIME_RES: ::libc::c_uint = 1; -pub const CLOCK_ALARM_CURRES: ::libc::c_uint = 3; -pub const CLOCK_ALARM_MINRES: ::libc::c_uint = 4; -pub const CLOCK_ALARM_MAXRES: ::libc::c_uint = 5; +pub const CLOCK_GET_TIME_RES: c_uint = 1; +pub const CLOCK_ALARM_CURRES: c_uint = 3; +pub const CLOCK_ALARM_MINRES: c_uint = 4; +pub const CLOCK_ALARM_MAXRES: c_uint = 5; -pub const NSEC_PER_USEC: ::libc::c_ulonglong = 1000; -pub const USEC_PER_SEC: ::libc::c_ulonglong = 1_000_000; -pub const NSEC_PER_SEC: ::libc::c_ulonglong = 1_000_000_000; -pub const NSEC_PER_MSEC: ::libc::c_ulonglong = 1_000_000; +pub const NSEC_PER_USEC: c_ulonglong = 1000; +pub const USEC_PER_SEC: c_ulonglong = 1_000_000; +pub const NSEC_PER_SEC: c_ulonglong = 1_000_000_000; +pub const NSEC_PER_MSEC: c_ulonglong = 1_000_000; #[allow(non_snake_case)] pub fn BAD_MACH_TIMESPEC(t: mach_timespec) -> bool { - t.tv_nsec < 0 || (t.tv_nsec as ::libc::c_ulonglong) >= NSEC_PER_SEC + t.tv_nsec < 0 || (t.tv_nsec as c_ulonglong) >= NSEC_PER_SEC } #[allow(non_snake_case)] -pub fn CMP_MACH_TIMESPEC(t1: &mach_timespec, t2: &mach_timespec) -> ::libc::c_ulonglong { +pub fn CMP_MACH_TIMESPEC(t1: &mach_timespec, t2: &mach_timespec) -> c_ulonglong { if t1.tv_sec > t2.tv_sec { return NSEC_PER_SEC; } if t1.tv_sec < t2.tv_sec { return !NSEC_PER_SEC; } - (t1.tv_nsec as ::libc::c_ulonglong) - (t2.tv_nsec as ::libc::c_ulonglong) + (t1.tv_nsec as c_ulonglong) - (t2.tv_nsec as c_ulonglong) } #[allow(non_snake_case)] pub fn ADD_MACH_TIMESPEC(t1: &mut mach_timespec, t2: &mach_timespec) { t1.tv_nsec += t2.tv_nsec; - if (t1.tv_nsec as ::libc::c_ulonglong) >= NSEC_PER_SEC { - t1.tv_nsec = (t1.tv_nsec as ::libc::c_ulonglong - NSEC_PER_SEC) as clock_res_t; + if (t1.tv_nsec as c_ulonglong) >= NSEC_PER_SEC { + t1.tv_nsec = (t1.tv_nsec as c_ulonglong - NSEC_PER_SEC) as clock_res_t; t1.tv_sec += 1; } t1.tv_sec += t2.tv_sec; @@ -59,17 +60,17 @@ pub fn ADD_MACH_TIMESPEC(t1: &mut mach_timespec, t2: &mach_timespec) { pub fn SUB_MACH_TIMESPEC(t1: &mut mach_timespec, t2: &mach_timespec) { t1.tv_nsec -= t2.tv_nsec; if t1.tv_nsec < 0 { - t1.tv_nsec = (t1.tv_nsec as ::libc::c_ulonglong + NSEC_PER_SEC) as clock_res_t; + t1.tv_nsec = (t1.tv_nsec as c_ulonglong + NSEC_PER_SEC) as clock_res_t; t1.tv_sec -= 1; } t1.tv_sec -= t2.tv_sec; } -pub const ALRMTYPE: ::libc::c_uint = 0xff; -pub const TIME_ABSOLUTE: ::libc::c_uint = 0x00; -pub const TIME_RELATIVE: ::libc::c_uint = 0x01; +pub const ALRMTYPE: c_uint = 0xff; +pub const TIME_ABSOLUTE: c_uint = 0x00; +pub const TIME_RELATIVE: c_uint = 0x01; #[allow(non_snake_case)] -pub fn BAD_ALRMTYPE(t: ::libc::c_uint) -> bool { +pub fn BAD_ALRMTYPE(t: c_uint) -> bool { t & (!TIME_RELATIVE) != 0 } diff --git a/third_party/rust/mach2/src/dyld.rs b/third_party/rust/mach2/src/dyld.rs new file mode 100644 index 000000000000..3cdb8cc9eef5 --- /dev/null +++ b/third_party/rust/mach2/src/dyld.rs @@ -0,0 +1,11 @@ +//! This module roughly corresponds to `mach-o/dyld.h`. + +use crate::loader::mach_header; +use core::ffi::c_char; + +unsafe extern "C" { + pub fn _dyld_image_count() -> u32; + pub fn _dyld_get_image_header(image_index: u32) -> *const mach_header; + pub fn _dyld_get_image_vmaddr_slide(image_index: u32) -> isize; + pub fn _dyld_get_image_name(image_index: u32) -> *const c_char; +} diff --git a/third_party/rust/mach2/src/dyld_kernel.rs b/third_party/rust/mach2/src/dyld_kernel.rs index 9a264dfafd59..58aaaaf17912 100644 --- a/third_party/rust/mach2/src/dyld_kernel.rs +++ b/third_party/rust/mach2/src/dyld_kernel.rs @@ -1,7 +1,7 @@ //! This module roughly corresponds to `mach/dyld_kernel.h`. -use boolean::boolean_t; -use mach_types::{fsid_t, fsobj_id_t, uuid_t}; +use crate::boolean::boolean_t; +use crate::mach_types::{fsid_t, fsobj_id_t, uuid_t}; #[repr(C)] #[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] diff --git a/third_party/rust/mach2/src/error.rs b/third_party/rust/mach2/src/error.rs new file mode 100644 index 000000000000..9673b9570111 --- /dev/null +++ b/third_party/rust/mach2/src/error.rs @@ -0,0 +1,57 @@ +//! This module corresponds to `mach/error.h`. + +use crate::kern_return::kern_return_t; +use core::ffi::c_int; + +pub type mach_error_t = kern_return_t; +pub type mach_error_fn_t = Option mach_error_t>; + +pub const err_none: mach_error_t = 0; +pub const ERR_SUCCESS: mach_error_t = err_none; +pub const ERR_ROUTINE_NIL: mach_error_fn_t = None; + +#[inline] +pub const fn err_system(x: c_int) -> mach_error_t { + (((x as u32) & 0x3f) << 26) as mach_error_t +} + +#[inline] +pub const fn err_sub(x: c_int) -> mach_error_t { + (((x as u32) & 0xfff) << 14) as mach_error_t +} + +#[inline] +pub const fn err_get_system(err: mach_error_t) -> c_int { + (((err as u32) >> 26) & 0x3f) as c_int +} + +#[inline] +pub const fn err_get_sub(err: mach_error_t) -> c_int { + (((err as u32) >> 14) & 0xfff) as c_int +} + +#[inline] +pub const fn err_get_code(err: mach_error_t) -> c_int { + ((err as u32) & 0x3fff) as c_int +} + +pub const system_emask: mach_error_t = err_system(0x3f); +pub const sub_emask: mach_error_t = err_sub(0xfff); +pub const code_emask: mach_error_t = 0x3fff; + +pub const err_kern: mach_error_t = err_system(0x0); +pub const err_us: mach_error_t = err_system(0x1); +pub const err_server: mach_error_t = err_system(0x2); +pub const err_ipc: mach_error_t = err_system(0x3); +pub const err_mach_ipc: mach_error_t = err_system(0x4); +pub const err_dipc: mach_error_t = err_system(0x7); +pub const err_vm: mach_error_t = err_system(0x8); +pub const err_local: mach_error_t = err_system(0x3e); +pub const err_ipc_compat: mach_error_t = err_system(0x3f); + +pub const err_max_system: c_int = 0x3f; + +#[inline] +pub const fn unix_err(errno: mach_error_t) -> mach_error_t { + err_kern | err_sub(3) | errno +} diff --git a/third_party/rust/mach2/src/exc.rs b/third_party/rust/mach2/src/exc.rs index 9330740c4e29..786945dbc5df 100644 --- a/third_party/rust/mach2/src/exc.rs +++ b/third_party/rust/mach2/src/exc.rs @@ -1,14 +1,19 @@ //! This module roughly corresponds to `mach/exc.h`. -use exception_types::{exception_data_t, exception_type_t}; -use kern_return::kern_return_t; -use message::mach_msg_type_number_t; -use port::mach_port_t; -use thread_status::thread_state_t; +use crate::exception_types::{exception_data_t, exception_type_t}; +use crate::kern_return::kern_return_t; +use crate::message::{ + mach_msg_body_t, mach_msg_header_t, mach_msg_port_descriptor_t, mach_msg_type_number_t, +}; +use crate::ndr::NDR_record_t; +use crate::port::mach_port_t; +use crate::thread_status::thread_state_t; +use crate::vm_types::integer_t; +use core::ffi::{c_int, c_uint}; -pub const exc_MSG_COUNT: ::libc::c_uint = 3; +pub const exc_MSG_COUNT: c_uint = 3; -extern "C" { +unsafe extern "C" { pub fn exception_raise( exception_port: mach_port_t, thread: mach_port_t, @@ -22,7 +27,7 @@ extern "C" { exception: exception_type_t, code: exception_data_t, codeCnt: mach_msg_type_number_t, - flavor: *mut ::libc::c_int, + flavor: *mut c_int, old_state: thread_state_t, old_stateCnt: mach_msg_type_number_t, new_state: thread_state_t, @@ -35,10 +40,35 @@ extern "C" { exception: exception_type_t, code: exception_data_t, codeCnt: mach_msg_type_number_t, - flavor: *mut ::libc::c_int, + flavor: *mut c_int, old_state: thread_state_t, old_stateCnt: mach_msg_type_number_t, new_state: thread_state_t, new_stateCnt: *mut mach_msg_type_number_t, ) -> kern_return_t; } + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__exception_raise_t { + pub Head: mach_msg_header_t, + /* start of the kernel processed data */ + pub msgh_body: mach_msg_body_t, + pub thread: mach_msg_port_descriptor_t, + pub task: mach_msg_port_descriptor_t, + /* end of the kernel processed data */ + pub NDR: NDR_record_t, + pub exception: exception_type_t, + pub codeCnt: mach_msg_type_number_t, + pub code: [integer_t; 2], +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__exception_raise_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} diff --git a/third_party/rust/mach2/src/exception_types.rs b/third_party/rust/mach2/src/exception_types.rs index f042443d8a7f..f38850f03f9d 100644 --- a/third_party/rust/mach2/src/exception_types.rs +++ b/third_party/rust/mach2/src/exception_types.rs @@ -1,53 +1,53 @@ //! This module roughly corresponds to `mach/exception_types.h`. -use port::mach_port_t; -use thread_status::thread_state_flavor_t; -use vm_types::integer_t; +use crate::port::mach_port_t; +use crate::thread_status::thread_state_flavor_t; +use crate::vm_types::integer_t; +use core::ffi::{c_int, c_uint}; -pub const EXC_BAD_ACCESS: ::libc::c_uint = 1; -pub const EXC_BAD_INSTRUCTION: ::libc::c_uint = 2; -pub const EXC_ARITHMETIC: ::libc::c_uint = 3; -pub const EXC_EMULATION: ::libc::c_uint = 4; -pub const EXC_SOFTWARE: ::libc::c_uint = 5; -pub const EXC_BREAKPOINT: ::libc::c_uint = 6; -pub const EXC_SYSCALL: ::libc::c_uint = 7; -pub const EXC_MACH_SYSCALL: ::libc::c_uint = 8; -pub const EXC_RPC_ALERT: ::libc::c_uint = 9; -pub const EXC_CRASH: ::libc::c_uint = 10; -pub const EXC_RESOURCE: ::libc::c_uint = 11; -pub const EXC_GUARD: ::libc::c_uint = 12; -pub const EXC_CORPSE_NOTIFY: ::libc::c_uint = 13; -pub const EXC_CORPSE_VARIANT_BIT: ::libc::c_uint = 256; -pub const EXCEPTION_DEFAULT: ::libc::c_uint = 1; -pub const EXCEPTION_STATE: ::libc::c_uint = 2; -pub const EXCEPTION_STATE_IDENTITY: ::libc::c_uint = 3; -pub const MACH_EXCEPTION_CODES: ::libc::c_uint = 2_147_483_648; -pub const EXC_MASK_BAD_ACCESS: ::libc::c_uint = 2; -pub const EXC_MASK_BAD_INSTRUCTION: ::libc::c_uint = 4; -pub const EXC_MASK_ARITHMETIC: ::libc::c_uint = 8; -pub const EXC_MASK_EMULATION: ::libc::c_uint = 16; -pub const EXC_MASK_SOFTWARE: ::libc::c_uint = 32; -pub const EXC_MASK_BREAKPOINT: ::libc::c_uint = 64; -pub const EXC_MASK_SYSCALL: ::libc::c_uint = 128; -pub const EXC_MASK_MACH_SYSCALL: ::libc::c_uint = 256; -pub const EXC_MASK_RPC_ALERT: ::libc::c_uint = 512; -pub const EXC_MASK_CRASH: ::libc::c_uint = 1024; -pub const EXC_MASK_RESOURCE: ::libc::c_uint = 2048; -pub const EXC_MASK_GUARD: ::libc::c_uint = 4096; -pub const EXC_MASK_CORPSE_NOTIFY: ::libc::c_uint = 8192; -pub const EXC_MASK_ALL: ::libc::c_uint = 7166; -pub const FIRST_EXCEPTION: ::libc::c_uint = 1; -pub const EXC_SOFT_SIGNAL: ::libc::c_uint = 65_539; -pub const EXC_MACF_MIN: ::libc::c_uint = 131_072; -pub const EXC_MACF_MAX: ::libc::c_uint = 196_607; +pub const EXC_BAD_ACCESS: c_uint = 1; +pub const EXC_BAD_INSTRUCTION: c_uint = 2; +pub const EXC_ARITHMETIC: c_uint = 3; +pub const EXC_EMULATION: c_uint = 4; +pub const EXC_SOFTWARE: c_uint = 5; +pub const EXC_BREAKPOINT: c_uint = 6; +pub const EXC_SYSCALL: c_uint = 7; +pub const EXC_MACH_SYSCALL: c_uint = 8; +pub const EXC_RPC_ALERT: c_uint = 9; +pub const EXC_CRASH: c_uint = 10; +pub const EXC_RESOURCE: c_uint = 11; +pub const EXC_GUARD: c_uint = 12; +pub const EXC_CORPSE_NOTIFY: c_uint = 13; +pub const EXCEPTION_DEFAULT: c_uint = 1; +pub const EXCEPTION_STATE: c_uint = 2; +pub const EXCEPTION_STATE_IDENTITY: c_uint = 3; +pub const MACH_EXCEPTION_CODES: c_uint = 2_147_483_648; +pub const EXC_MASK_BAD_ACCESS: c_uint = 2; +pub const EXC_MASK_BAD_INSTRUCTION: c_uint = 4; +pub const EXC_MASK_ARITHMETIC: c_uint = 8; +pub const EXC_MASK_EMULATION: c_uint = 16; +pub const EXC_MASK_SOFTWARE: c_uint = 32; +pub const EXC_MASK_BREAKPOINT: c_uint = 64; +pub const EXC_MASK_SYSCALL: c_uint = 128; +pub const EXC_MASK_MACH_SYSCALL: c_uint = 256; +pub const EXC_MASK_RPC_ALERT: c_uint = 512; +pub const EXC_MASK_CRASH: c_uint = 1024; +pub const EXC_MASK_RESOURCE: c_uint = 2048; +pub const EXC_MASK_GUARD: c_uint = 4096; +pub const EXC_MASK_CORPSE_NOTIFY: c_uint = 8192; +pub const EXC_MASK_ALL: c_uint = 7166; +pub const FIRST_EXCEPTION: c_uint = 1; +pub const EXC_SOFT_SIGNAL: c_uint = 65_539; +pub const EXC_MACF_MIN: c_uint = 131_072; +pub const EXC_MACF_MAX: c_uint = 196_607; -pub type exception_type_t = ::libc::c_int; +pub type exception_type_t = c_int; pub type exception_data_type_t = integer_t; pub type mach_exception_data_type_t = i64; -pub type exception_behavior_t = ::libc::c_int; +pub type exception_behavior_t = c_int; pub type exception_data_t = *mut exception_data_type_t; pub type mach_exception_data_t = *mut mach_exception_data_type_t; -pub type exception_mask_t = ::libc::c_uint; +pub type exception_mask_t = c_uint; pub type exception_mask_array_t = *mut exception_mask_t; pub type exception_behavior_array_t = *mut exception_behavior_t; pub type exception_flavor_array_t = *mut thread_state_flavor_t; diff --git a/third_party/rust/mach2/src/kern_return.rs b/third_party/rust/mach2/src/kern_return.rs index 3d447b402664..1a3660fb24b0 100644 --- a/third_party/rust/mach2/src/kern_return.rs +++ b/third_party/rust/mach2/src/kern_return.rs @@ -1,7 +1,9 @@ -//! This module corresponds to `mach/kern_return.h` and -//! `mach/i386/kern_return.h`. +//! This module corresponds to `mach/kern_return.h`. +use core::ffi::c_int; -pub type kern_return_t = ::libc::c_int; +// ...Except for this particular type, which is taken from `mach/i386/kern_return.h` and +// `mach/arm/kern_return.h` (also used for aarch64): it is the same type in both header files. +pub type kern_return_t = c_int; pub const KERN_SUCCESS: kern_return_t = 0; pub const KERN_INVALID_ADDRESS: kern_return_t = 1; diff --git a/third_party/rust/mach2/src/lib.rs b/third_party/rust/mach2/src/lib.rs index 0b68a706aad9..17b9c542501c 100644 --- a/third_party/rust/mach2/src/lib.rs +++ b/third_party/rust/mach2/src/lib.rs @@ -10,10 +10,8 @@ )] #![no_std] -#[cfg(not(any(target_os = "macos", target_os = "ios")))] -compile_error!("mach requires macOS or iOS"); - -extern crate libc; +#[cfg(not(target_vendor = "apple"))] +compile_error!("mach requires macOS, iOS, tvOS, watchOS or visionOS"); #[allow(unused_imports)] use core::{clone, cmp, default, fmt, hash, marker, mem, option}; @@ -23,25 +21,41 @@ pub mod bootstrap; pub mod clock; pub mod clock_priv; pub mod clock_reply; -pub mod clock_types; // TODO: test +pub mod clock_types; +pub mod dyld; pub mod dyld_kernel; -// pub mod error; // TODO +pub mod error; pub mod exc; pub mod exception_types; pub mod kern_return; +pub mod loader; +pub mod mach_debug; pub mod mach_init; pub mod mach_port; pub mod mach_time; pub mod mach_types; +pub mod mach_voucher_types; pub mod memory_object_types; pub mod message; +pub mod mig; +pub mod ndr; +pub mod notify; +pub mod policy; pub mod port; +pub mod semaphore; pub mod structs; +pub mod sync_policy; pub mod task; pub mod task_info; +pub mod task_inspect; +pub mod task_special_ports; pub mod thread_act; pub mod thread_policy; +pub mod thread_special_ports; +pub mod thread_state; pub mod thread_status; +pub mod thread_switch; +pub mod time_value; pub mod traps; pub mod vm; pub mod vm_attributes; diff --git a/third_party/rust/mach2/src/loader.rs b/third_party/rust/mach2/src/loader.rs new file mode 100644 index 000000000000..d1077dafb8d5 --- /dev/null +++ b/third_party/rust/mach2/src/loader.rs @@ -0,0 +1,18 @@ +//! This module roughly corresponds to `mach-o/loader.h`. +use core::ffi::c_int; + +pub type cpu_type_t = c_int; +pub type cpu_subtype_t = c_int; + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct mach_header { + pub magic: u32, + pub cputype: cpu_type_t, + pub cpusubtype: cpu_subtype_t, + pub filetype: u32, + pub ncmds: u32, + pub sizeofcmds: u32, + pub flags: u32, +} diff --git a/third_party/rust/mach2/src/mach_debug/ipc_info.rs b/third_party/rust/mach2/src/mach_debug/ipc_info.rs new file mode 100644 index 000000000000..548a55c05ef6 --- /dev/null +++ b/third_party/rust/mach2/src/mach_debug/ipc_info.rs @@ -0,0 +1,124 @@ +//! This module corresponds to `mach_debug/ipc_info.h`. + +use crate::port::{mach_port_name_t, mach_port_type_t, mach_port_urefs_t}; +use crate::vm_types::{integer_t, natural_t}; + +pub type ipc_info_object_type_t = natural_t; + +pub const IPC_OTYPE_NONE: ipc_info_object_type_t = 0; +pub const IPC_OTYPE_THREAD_CONTROL: ipc_info_object_type_t = 1; +pub const IPC_OTYPE_TASK_CONTROL: ipc_info_object_type_t = 2; +pub const IPC_OTYPE_HOST: ipc_info_object_type_t = 3; +pub const IPC_OTYPE_HOST_PRIV: ipc_info_object_type_t = 4; +pub const IPC_OTYPE_PROCESSOR: ipc_info_object_type_t = 5; +pub const IPC_OTYPE_PROCESSOR_SET: ipc_info_object_type_t = 6; +pub const IPC_OTYPE_PROCESSOR_SET_NAME: ipc_info_object_type_t = 7; +pub const IPC_OTYPE_TIMER: ipc_info_object_type_t = 8; +pub const IPC_OTYPE_PORT_SUBST_ONCE: ipc_info_object_type_t = 9; +pub const IPC_OTYPE_MIG: ipc_info_object_type_t = 10; +pub const IPC_OTYPE_MEMORY_OBJECT: ipc_info_object_type_t = 11; +pub const IPC_OTYPE_XMM_PAGER: ipc_info_object_type_t = 12; +pub const IPC_OTYPE_XMM_KERNEL: ipc_info_object_type_t = 13; +pub const IPC_OTYPE_XMM_REPLY: ipc_info_object_type_t = 14; +pub const IPC_OTYPE_UND_REPLY: ipc_info_object_type_t = 15; +pub const IPC_OTYPE_HOST_NOTIFY: ipc_info_object_type_t = 16; +pub const IPC_OTYPE_HOST_SECURITY: ipc_info_object_type_t = 17; +pub const IPC_OTYPE_LEDGER: ipc_info_object_type_t = 18; +pub const IPC_OTYPE_MAIN_DEVICE: ipc_info_object_type_t = 19; +pub const IPC_OTYPE_TASK_NAME: ipc_info_object_type_t = 20; +pub const IPC_OTYPE_SUBSYSTEM: ipc_info_object_type_t = 21; +pub const IPC_OTYPE_IO_DONE_QUEUE: ipc_info_object_type_t = 22; +pub const IPC_OTYPE_SEMAPHORE: ipc_info_object_type_t = 23; +pub const IPC_OTYPE_LOCK_SET: ipc_info_object_type_t = 24; +pub const IPC_OTYPE_CLOCK: ipc_info_object_type_t = 25; +pub const IPC_OTYPE_CLOCK_CTRL: ipc_info_object_type_t = 26; +pub const IPC_OTYPE_IOKIT_IDENT: ipc_info_object_type_t = 27; +pub const IPC_OTYPE_NAMED_ENTRY: ipc_info_object_type_t = 28; +pub const IPC_OTYPE_IOKIT_CONNECT: ipc_info_object_type_t = 29; +pub const IPC_OTYPE_IOKIT_OBJECT: ipc_info_object_type_t = 30; +pub const IPC_OTYPE_UPL: ipc_info_object_type_t = 31; +pub const IPC_OTYPE_MEM_OBJ_CONTROL: ipc_info_object_type_t = 32; +pub const IPC_OTYPE_AU_SESSIONPORT: ipc_info_object_type_t = 33; +pub const IPC_OTYPE_FILEPORT: ipc_info_object_type_t = 34; +pub const IPC_OTYPE_LABELH: ipc_info_object_type_t = 35; +pub const IPC_OTYPE_TASK_RESUME: ipc_info_object_type_t = 36; +pub const IPC_OTYPE_VOUCHER: ipc_info_object_type_t = 37; +pub const IPC_OTYPE_VOUCHER_ATTR_CONTROL: ipc_info_object_type_t = 38; +pub const IPC_OTYPE_WORK_INTERVAL: ipc_info_object_type_t = 39; +pub const IPC_OTYPE_UX_HANDLER: ipc_info_object_type_t = 40; +pub const IPC_OTYPE_UEXT_OBJECT: ipc_info_object_type_t = 41; +pub const IPC_OTYPE_ARCADE_REG: ipc_info_object_type_t = 42; +pub const IPC_OTYPE_EVENTLINK: ipc_info_object_type_t = 43; +pub const IPC_OTYPE_TASK_INSPECT: ipc_info_object_type_t = 44; +pub const IPC_OTYPE_TASK_READ: ipc_info_object_type_t = 45; +pub const IPC_OTYPE_THREAD_INSPECT: ipc_info_object_type_t = 46; +pub const IPC_OTYPE_THREAD_READ: ipc_info_object_type_t = 47; +pub const IPC_OTYPE_SUID_CRED: ipc_info_object_type_t = 48; +pub const IPC_OTYPE_HYPERVISOR: ipc_info_object_type_t = 49; +pub const IPC_OTYPE_TASK_ID_TOKEN: ipc_info_object_type_t = 50; +pub const IPC_OTYPE_TASK_FATAL: ipc_info_object_type_t = 51; +pub const IPC_OTYPE_KCDATA: ipc_info_object_type_t = 52; +pub const IPC_OTYPE_EXCLAVES_RESOURCE: ipc_info_object_type_t = 53; +pub const IPC_OTYPE_UNKNOWN: ipc_info_object_type_t = !0; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct ipc_info_space { + pub iis_genno_mask: natural_t, + pub iis_table_size: natural_t, + pub iis_table_next: natural_t, + pub iis_tree_size: natural_t, + pub iis_tree_small: natural_t, + pub iis_tree_hash: natural_t, +} + +pub type ipc_info_space_t = ipc_info_space; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct ipc_info_space_basic { + pub iisb_genno_mask: natural_t, + pub iisb_table_size: natural_t, + pub iisb_table_next: natural_t, + pub iisb_table_inuse: natural_t, + pub iisb_reserved: [natural_t; 2], +} + +pub type ipc_info_space_basic_t = ipc_info_space_basic; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct ipc_info_name { + pub iin_name: mach_port_name_t, + pub iin_collision: integer_t, + pub iin_type: mach_port_type_t, + pub iin_urefs: mach_port_urefs_t, + pub iin_object: natural_t, + pub iin_next: natural_t, + pub iin_hash: natural_t, +} + +pub type ipc_info_name_t = ipc_info_name; +pub type ipc_info_name_array_t = *mut ipc_info_name_t; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct ipc_info_tree_name { + pub iitn_name: ipc_info_name_t, + pub iitn_lchild: mach_port_name_t, + pub iitn_rchild: mach_port_name_t, +} + +pub type ipc_info_tree_name_t = ipc_info_tree_name; +pub type ipc_info_tree_name_array_t = *mut ipc_info_tree_name_t; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct ipc_info_port { + pub iip_port_object: natural_t, + pub iip_receiver_object: natural_t, +} + +pub type ipc_info_port_t = ipc_info_port; +pub type exception_port_info_array_t = *mut ipc_info_port_t; +pub type exception_handler_info_array_t = *mut ipc_info_port_t; diff --git a/third_party/rust/mach2/src/mach_debug/mod.rs b/third_party/rust/mach2/src/mach_debug/mod.rs new file mode 100644 index 000000000000..083c5c6ed9de --- /dev/null +++ b/third_party/rust/mach2/src/mach_debug/mod.rs @@ -0,0 +1,2 @@ +pub mod ipc_info; +pub mod zone_info; diff --git a/third_party/rust/mach2/src/mach_debug/zone_info.rs b/third_party/rust/mach2/src/mach_debug/zone_info.rs new file mode 100644 index 000000000000..12513610a653 --- /dev/null +++ b/third_party/rust/mach2/src/mach_debug/zone_info.rs @@ -0,0 +1,139 @@ +//! This module corresponds to `mach_debug/zone_info.h`. + +use crate::vm_types::{integer_t, vm_size_t}; +use core::ffi::c_char; + +pub const ZONE_NAME_MAX_LEN: usize = 80; +pub const MACH_ZONE_NAME_MAX_LEN: usize = 80; +pub const MACH_MEMORY_INFO_NAME_MAX_LEN: usize = 80; +pub const MAX_ZTRACE_DEPTH: usize = 15; + +pub const ZOP_ALLOC: u32 = 1; +pub const ZOP_FREE: u32 = 0; + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct zone_name { + pub zn_name: [c_char; ZONE_NAME_MAX_LEN], +} + +pub type zone_name_t = zone_name; +pub type zone_name_array_t = *mut zone_name_t; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct zone_info { + pub zi_count: integer_t, + pub zi_cur_size: vm_size_t, + pub zi_max_size: vm_size_t, + pub zi_elem_size: vm_size_t, + pub zi_alloc_size: vm_size_t, + pub zi_pageable: integer_t, + pub zi_sleepable: integer_t, + pub zi_exhaustible: integer_t, + pub zi_collectable: integer_t, +} + +pub type zone_info_t = zone_info; +pub type zone_info_array_t = *mut zone_info_t; + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct mach_zone_name { + pub mzn_name: [c_char; ZONE_NAME_MAX_LEN], +} + +pub type mach_zone_name_t = mach_zone_name; +pub type mach_zone_name_array_t = *mut mach_zone_name_t; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct mach_zone_info_data { + pub mzi_count: u64, + pub mzi_cur_size: u64, + pub mzi_max_size: u64, + pub mzi_elem_size: u64, + pub mzi_alloc_size: u64, + pub mzi_sum_size: u64, + pub mzi_exhaustible: u64, + pub mzi_collectable: u64, +} + +pub type mach_zone_info_t = mach_zone_info_data; +pub type mach_zone_info_array_t = *mut mach_zone_info_t; + +#[inline] +pub const fn get_mzi_collectable_bytes(val: u64) -> u64 { + val >> 1 +} + +#[inline] +pub const fn get_mzi_collectable_flag(val: u64) -> u64 { + val & 1 +} + +#[inline] +pub fn set_mzi_collectable_bytes(val: &mut u64, size: u64) { + *val = (*val & 1) | (size << 1); +} + +#[inline] +pub fn set_mzi_collectable_flag(val: &mut u64, flag: bool) { + if flag { + *val |= 1; + } else { + *val &= !1; + } +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_zone_info_data { + pub tzi_count: u64, + pub tzi_cur_size: u64, + pub tzi_max_size: u64, + pub tzi_elem_size: u64, + pub tzi_alloc_size: u64, + pub tzi_sum_size: u64, + pub tzi_exhaustible: u64, + pub tzi_collectable: u64, + pub tzi_caller_acct: u64, + pub tzi_task_alloc: u64, + pub tzi_task_free: u64, +} + +pub type task_zone_info_t = task_zone_info_data; +pub type task_zone_info_array_t = *mut task_zone_info_t; + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +#[allow(non_snake_case)] +pub struct mach_memory_info { + pub flags: u64, + pub site: u64, + pub size: u64, + pub free: u64, + pub largest: u64, + pub collectable_bytes: u64, + pub mapped: u64, + pub peak: u64, + pub tag: u16, + pub zone: u16, + pub _resvA: [u16; 2], + pub _resv: [u64; 3], + pub name: [c_char; MACH_MEMORY_INFO_NAME_MAX_LEN], +} + +pub type mach_memory_info_t = mach_memory_info; +pub type mach_memory_info_array_t = *mut mach_memory_info_t; + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct zone_btrecord { + pub ref_count: u32, + pub operation_type: u32, + pub bt: [u64; MAX_ZTRACE_DEPTH], +} + +pub type zone_btrecord_t = zone_btrecord; +pub type zone_btrecord_array_t = *mut zone_btrecord_t; diff --git a/third_party/rust/mach2/src/mach_init.rs b/third_party/rust/mach2/src/mach_init.rs index 5776988cb519..3184036b8ae3 100644 --- a/third_party/rust/mach2/src/mach_init.rs +++ b/third_party/rust/mach2/src/mach_init.rs @@ -1,15 +1,16 @@ //! This module corresponds to `mach/mach_init.h`. -use mach_types::thread_port_t; +use crate::mach_types::thread_port_t; -extern "C" { +unsafe extern "C" { pub fn mach_thread_self() -> thread_port_t; + pub fn mach_host_self() -> thread_port_t; } #[cfg(test)] mod tests { - use mach_init::*; - use port::*; + use crate::mach_init::*; + use crate::port::*; #[test] fn mach_thread_self_test() { diff --git a/third_party/rust/mach2/src/mach_port.rs b/third_party/rust/mach2/src/mach_port.rs index e14a08e957fe..f937a9774c5d 100644 --- a/third_party/rust/mach2/src/mach_port.rs +++ b/third_party/rust/mach2/src/mach_port.rs @@ -1,11 +1,14 @@ //! This module corresponds to `mach/mach_port.h` -use kern_return::kern_return_t; -use mach_types::ipc_space_t; -use message::mach_msg_type_name_t; -use port::{mach_port_delta_t, mach_port_name_t, mach_port_right_t, mach_port_t}; +use crate::kern_return::kern_return_t; +use crate::mach_types::ipc_space_t; +use crate::message::mach_msg_type_name_t; +use crate::port::{ + mach_port_delta_t, mach_port_name_t, mach_port_options_t, mach_port_right_t, mach_port_t, +}; +use crate::vm_types::mach_port_context_t; -extern "C" { +unsafe extern "C" { pub fn mach_port_allocate( task: ipc_space_t, right: mach_port_right_t, @@ -32,4 +35,16 @@ extern "C" { right: mach_port_right_t, delta: mach_port_delta_t, ) -> kern_return_t; + pub fn mach_port_construct( + task: ipc_space_t, + options: *mut mach_port_options_t, + context: mach_port_context_t, + name: *mut mach_port_name_t, + ) -> kern_return_t; + pub fn mach_port_destruct( + task: ipc_space_t, + name: mach_port_name_t, + srdelta: mach_port_delta_t, + guard: mach_port_context_t, + ) -> kern_return_t; } diff --git a/third_party/rust/mach2/src/mach_time.rs b/third_party/rust/mach2/src/mach_time.rs index 9011c0c0af76..d6ec7cde5bcd 100644 --- a/third_party/rust/mach2/src/mach_time.rs +++ b/third_party/rust/mach2/src/mach_time.rs @@ -1,5 +1,5 @@ //! This module corresponds to `mach/mach_time.h` -use kern_return::kern_return_t; +use crate::kern_return::kern_return_t; pub type mach_timebase_info_t = *mut mach_timebase_info; pub type mach_timebase_info_data_t = mach_timebase_info; @@ -10,7 +10,7 @@ pub struct mach_timebase_info { pub denom: u32, } -extern "C" { +unsafe extern "C" { pub fn mach_timebase_info(info: mach_timebase_info_t) -> kern_return_t; pub fn mach_wait_until(deadline: u64) -> kern_return_t; pub fn mach_absolute_time() -> u64; diff --git a/third_party/rust/mach2/src/mach_types.rs b/third_party/rust/mach2/src/mach_types.rs index fa257b2a5383..b527d6652d14 100644 --- a/third_party/rust/mach2/src/mach_types.rs +++ b/third_party/rust/mach2/src/mach_types.rs @@ -1,13 +1,23 @@ //! This module corresponds to `mach/mach_types.h` -use port::mach_port_t; +use crate::port::mach_port_t; +use core::ffi::{c_long, c_uchar}; pub type task_t = mach_port_t; pub type task_name_t = mach_port_t; +pub type task_policy_set_t = mach_port_t; +pub type task_policy_get_t = mach_port_t; +pub type task_inspect_t = mach_port_t; +pub type task_read_t = mach_port_t; pub type task_suspension_token_t = mach_port_t; +pub type task_id_token_t = mach_port_t; pub type thread_t = mach_port_t; pub type thread_act_t = mach_port_t; +pub type thread_inspect_t = mach_port_t; +pub type thread_read_t = mach_port_t; pub type ipc_space_t = mach_port_t; +pub type ipc_space_read_t = mach_port_t; +pub type ipc_space_inspect_t = mach_port_t; pub type coalition_t = mach_port_t; pub type host_t = mach_port_t; pub type host_priv_t = mach_port_t; @@ -21,6 +31,11 @@ pub type ledger_t = mach_port_t; pub type alarm_t = mach_port_t; pub type clock_serv_t = mach_port_t; pub type clock_ctrl_t = mach_port_t; +pub type arcade_register_t = mach_port_t; +pub type ipc_eventlink_t = mach_port_t; +pub type eventlink_port_pair_t = [mach_port_t; 2]; +pub type mach_eventlink_t = mach_port_t; +pub type kcdata_object_t = mach_port_t; pub type processor_set_name_t = processor_set_t; @@ -30,6 +45,7 @@ pub type mem_entry_name_port_t = mach_port_t; pub type exception_handler_t = mach_port_t; pub type exception_handler_array_t = *mut exception_handler_t; pub type vm_task_entry_t = mach_port_t; +pub type io_main_t = mach_port_t; pub type io_master_t = mach_port_t; pub type UNDServerRef = mach_port_t; @@ -68,10 +84,16 @@ pub type exception_port_arrary_t = exception_handler_array_t; pub const TASK_NULL: task_t = 0; pub const TASK_NAME_NULL: task_name_t = 0; +pub const TASK_INSPECT_NULL: task_inspect_t = 0; +pub const TASK_READ_NULL: task_read_t = 0; pub const THREAD_NULL: thread_t = 0; +pub const THREAD_INSPECT_NULL: thread_inspect_t = 0; +pub const THREAD_READ_NULL: thread_read_t = 0; pub const TID_NULL: u64 = 0; pub const THR_ACT_NULL: thread_act_t = 0; pub const IPC_SPACE_NULL: ipc_space_t = 0; +pub const IPC_SPACE_READ_NULL: ipc_space_read_t = 0; +pub const IPC_SPACE_INSPECT_NULL: ipc_space_inspect_t = 0; pub const COALITION_NULL: coalition_t = 0; pub const HOST_NULL: host_t = 0; pub const HOST_PRIV_NULL: host_priv_t = 0; @@ -82,11 +104,18 @@ pub const SEMAPHORE_NULL: semaphore_t = 0; pub const LOCK_SET_NULL: lock_set_t = 0; pub const LEDGER_NULL: ledger_t = 0; pub const ALARM_NULL: alarm_t = 0; -pub const CLOCK_NULL: ::libc::clock_t = 0; +pub type clock_t = c_long; + +pub const CLOCK_NULL: clock_t = 0; pub const UND_SERVER_NULL: UNDServerRef = 0; +pub const ARCADE_REG_NULL: arcade_register_t = 0; +pub const MACH_EVENTLINK_NULL: mach_eventlink_t = 0; +pub const IPC_EVENTLINK_NULL: ipc_eventlink_t = 0; +pub const TASK_ID_TOKEN_NULL: task_id_token_t = 0; +pub const KCDATA_OBJECT_NULL: kcdata_object_t = 0; // : typedef unsigned char __darwin_uuid_t[16]; -pub type uuid_t = [::libc::c_uchar; 16]; +pub type uuid_t = [c_uchar; 16]; // #[repr(C)] diff --git a/third_party/rust/mach2/src/mach_voucher_types.rs b/third_party/rust/mach2/src/mach_voucher_types.rs new file mode 100644 index 000000000000..d2d56e709807 --- /dev/null +++ b/third_party/rust/mach2/src/mach_voucher_types.rs @@ -0,0 +1,97 @@ +//! This module corresponds to `mach/mach_voucher_types.h`. + +use crate::message::mach_msg_type_number_t; +use crate::port::{mach_port_name_t, mach_port_t}; + +pub type mach_voucher_t = mach_port_t; +pub const MACH_VOUCHER_NULL: mach_voucher_t = 0; + +pub type mach_voucher_name_t = mach_port_name_t; +pub const MACH_VOUCHER_NAME_NULL: mach_voucher_name_t = 0; + +pub type mach_voucher_name_array_t = *mut mach_voucher_name_t; +pub const MACH_VOUCHER_NAME_ARRAY_NULL: mach_voucher_name_array_t = core::ptr::null_mut(); + +pub type ipc_voucher_t = mach_voucher_t; +pub const IPC_VOUCHER_NULL: ipc_voucher_t = 0; + +pub type mach_voucher_selector_t = u32; +pub const MACH_VOUCHER_SELECTOR_CURRENT: mach_voucher_selector_t = 0; +pub const MACH_VOUCHER_SELECTOR_EFFECTIVE: mach_voucher_selector_t = 1; + +pub type mach_voucher_attr_key_t = u32; +pub type mach_voucher_attr_key_array_t = *mut mach_voucher_attr_key_t; + +pub const MACH_VOUCHER_ATTR_KEY_ALL: mach_voucher_attr_key_t = !0; +pub const MACH_VOUCHER_ATTR_KEY_NONE: mach_voucher_attr_key_t = 0; +pub const MACH_VOUCHER_ATTR_KEY_ATM: mach_voucher_attr_key_t = 1; +pub const MACH_VOUCHER_ATTR_KEY_IMPORTANCE: mach_voucher_attr_key_t = 2; +pub const MACH_VOUCHER_ATTR_KEY_BANK: mach_voucher_attr_key_t = 3; +pub const MACH_VOUCHER_ATTR_KEY_PTHPRIORITY: mach_voucher_attr_key_t = 4; +pub const MACH_VOUCHER_ATTR_KEY_USER_DATA: mach_voucher_attr_key_t = 7; +pub const MACH_VOUCHER_ATTR_KEY_BITS: mach_voucher_attr_key_t = MACH_VOUCHER_ATTR_KEY_USER_DATA; +pub const MACH_VOUCHER_ATTR_KEY_TEST: mach_voucher_attr_key_t = 8; +pub const MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN: mach_voucher_attr_key_t = + MACH_VOUCHER_ATTR_KEY_TEST; + +pub type mach_voucher_attr_content_t = *mut u8; +pub type mach_voucher_attr_content_size_t = u32; + +pub type mach_voucher_attr_command_t = u32; +pub type mach_voucher_attr_recipe_command_t = u32; +pub type mach_voucher_attr_recipe_command_array_t = *mut mach_voucher_attr_recipe_command_t; + +pub const MACH_VOUCHER_ATTR_NOOP: mach_voucher_attr_recipe_command_t = 0; +pub const MACH_VOUCHER_ATTR_COPY: mach_voucher_attr_recipe_command_t = 1; +pub const MACH_VOUCHER_ATTR_REMOVE: mach_voucher_attr_recipe_command_t = 2; +pub const MACH_VOUCHER_ATTR_SET_VALUE_HANDLE: mach_voucher_attr_recipe_command_t = 3; +pub const MACH_VOUCHER_ATTR_AUTO_REDEEM: mach_voucher_attr_recipe_command_t = 4; +pub const MACH_VOUCHER_ATTR_SEND_PREPROCESS: mach_voucher_attr_recipe_command_t = 5; +pub const MACH_VOUCHER_ATTR_REDEEM: mach_voucher_attr_recipe_command_t = 10; +pub const MACH_VOUCHER_ATTR_IMPORTANCE_SELF: mach_voucher_attr_recipe_command_t = 200; +pub const MACH_VOUCHER_ATTR_USER_DATA_STORE: mach_voucher_attr_recipe_command_t = 211; +pub const MACH_VOUCHER_ATTR_BITS_STORE: mach_voucher_attr_recipe_command_t = + MACH_VOUCHER_ATTR_USER_DATA_STORE; +pub const MACH_VOUCHER_ATTR_TEST_STORE: mach_voucher_attr_recipe_command_t = + MACH_VOUCHER_ATTR_USER_DATA_STORE; + +pub type mach_voucher_attr_recipe_size_t = mach_msg_type_number_t; + +pub type mach_voucher_attr_raw_recipe_t = *mut u8; +pub type mach_voucher_attr_raw_recipe_array_t = mach_voucher_attr_raw_recipe_t; +pub type mach_voucher_attr_raw_recipe_size_t = mach_msg_type_number_t; +pub type mach_voucher_attr_raw_recipe_array_size_t = mach_msg_type_number_t; + +pub const MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE: mach_msg_type_number_t = 5120; +pub const MACH_VOUCHER_TRAP_STACK_LIMIT: mach_msg_type_number_t = 256; + +pub type mach_voucher_attr_manager_t = mach_port_t; +pub const MACH_VOUCHER_ATTR_MANAGER_NULL: mach_voucher_attr_manager_t = 0; + +pub type mach_voucher_attr_control_t = mach_port_t; +pub const MACH_VOUCHER_ATTR_CONTROL_NULL: mach_voucher_attr_control_t = 0; + +pub type ipc_voucher_attr_manager_t = mach_port_t; +pub type ipc_voucher_attr_control_t = mach_port_t; +pub const IPC_VOUCHER_ATTR_MANAGER_NULL: ipc_voucher_attr_manager_t = 0; +pub const IPC_VOUCHER_ATTR_CONTROL_NULL: ipc_voucher_attr_control_t = 0; + +pub type mach_voucher_attr_value_handle_t = u64; +pub type mach_voucher_attr_value_handle_array_t = *mut mach_voucher_attr_value_handle_t; +pub type mach_voucher_attr_value_handle_array_size_t = mach_msg_type_number_t; + +pub const MACH_VOUCHER_ATTR_VALUE_MAX_NESTED: mach_voucher_attr_value_handle_array_size_t = 4; + +pub type mach_voucher_attr_value_reference_t = u32; +pub type mach_voucher_attr_value_flags_t = u32; +pub const MACH_VOUCHER_ATTR_VALUE_FLAGS_NONE: mach_voucher_attr_value_flags_t = 0; +pub const MACH_VOUCHER_ATTR_VALUE_FLAGS_PERSIST: mach_voucher_attr_value_flags_t = 1; + +pub type mach_voucher_attr_control_flags_t = u32; +pub const MACH_VOUCHER_ATTR_CONTROL_FLAGS_NONE: mach_voucher_attr_control_flags_t = 0; + +pub const MACH_VOUCHER_IMPORTANCE_ATTR_ADD_EXTERNAL: u32 = 1; +pub const MACH_VOUCHER_IMPORTANCE_ATTR_DROP_EXTERNAL: u32 = 2; +pub type mach_voucher_attr_importance_refs = u32; + +pub const MACH_ACTIVITY_ID_COUNT_MAX: u32 = 16; diff --git a/third_party/rust/mach2/src/memory_object_types.rs b/third_party/rust/mach2/src/memory_object_types.rs index 8399e71676a2..1c07b2794f51 100644 --- a/third_party/rust/mach2/src/memory_object_types.rs +++ b/third_party/rust/mach2/src/memory_object_types.rs @@ -1,9 +1,10 @@ //! This module roughly corresponds to `mach/memory_object_types.h`. -use vm_types::natural_t; +use crate::vm_types::natural_t; +use core::ffi::c_ulonglong; -pub type memory_object_offset_t = ::libc::c_ulonglong; -pub type memory_object_size_t = ::libc::c_ulonglong; +pub type memory_object_offset_t = c_ulonglong; +pub type memory_object_size_t = c_ulonglong; pub type memory_object_cluster_size_t = natural_t; pub type memory_object_fault_info_t = *mut natural_t; -pub type vm_object_id_t = ::libc::c_ulonglong; +pub type vm_object_id_t = c_ulonglong; diff --git a/third_party/rust/mach2/src/message.rs b/third_party/rust/mach2/src/message.rs index 40114ad3edef..f7e557e5338e 100644 --- a/third_party/rust/mach2/src/message.rs +++ b/third_party/rust/mach2/src/message.rs @@ -1,21 +1,24 @@ //! This module corresponds to `mach/message.h`. -use kern_return::kern_return_t; -use port::{mach_port_name_t, mach_port_t}; -use vm_types::{integer_t, natural_t}; +use crate::kern_return::kern_return_t; +use crate::port::{mach_port_name_t, mach_port_seqno_t, mach_port_t}; +use crate::vm_types::{integer_t, natural_t}; +use core::ffi::{c_uint, c_void}; pub type mach_msg_timeout_t = natural_t; -pub type mach_msg_bits_t = ::libc::c_uint; +pub type mach_msg_bits_t = c_uint; pub type mach_msg_id_t = integer_t; pub type mach_msg_size_t = natural_t; -pub type mach_msg_copy_options_t = ::libc::c_uint; -pub type mach_msg_descriptor_type_t = ::libc::c_uint; -pub type mach_msg_type_name_t = ::libc::c_uint; +pub type mach_msg_copy_options_t = c_uint; +pub type mach_msg_descriptor_type_t = c_uint; +pub type mach_msg_type_name_t = c_uint; -pub type mach_msg_trailer_type_t = ::libc::c_uint; -pub type mach_msg_trailer_size_t = ::libc::c_uint; +pub type mach_msg_guard_flags_t = c_uint; + +pub type mach_msg_trailer_type_t = c_uint; +pub type mach_msg_trailer_size_t = c_uint; pub type mach_msg_option_t = integer_t; @@ -59,10 +62,16 @@ pub const MACH_MSG_PHYSICAL_COPY: mach_msg_copy_options_t = 0; pub const MACH_MSG_VIRTUAL_COPY: mach_msg_copy_options_t = 1; pub const MACH_MSG_ALLOCATE: mach_msg_copy_options_t = 2; +pub const MACH_MSG_GUARD_FLAGS_NONE: mach_msg_guard_flags_t = 0; +pub const MACH_MSG_GUARD_FLAGS_IMMOVABLE_RECEIVE: mach_msg_guard_flags_t = 1; +pub const MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND: mach_msg_guard_flags_t = 2; +pub const MACH_MSG_GUARD_FLAGS_MASK: mach_msg_guard_flags_t = 3; + pub const MACH_MSG_PORT_DESCRIPTOR: mach_msg_descriptor_type_t = 0; pub const MACH_MSG_OOL_DESCRIPTOR: mach_msg_descriptor_type_t = 1; pub const MACH_MSG_OOL_PORTS_DESCRIPTOR: mach_msg_descriptor_type_t = 2; pub const MACH_MSG_OOL_VOLATILE_DESCRIPTOR: mach_msg_descriptor_type_t = 3; +pub const MACH_MSG_GUARDED_PORT_DESCRIPTOR: mach_msg_descriptor_type_t = 4; pub const MACH_MSG_OPTION_NONE: mach_msg_option_t = 0x0000_0000; @@ -73,19 +82,37 @@ pub const MACH_RCV_LARGE: mach_msg_option_t = 0x0000_0004; pub const MACH_RCV_LARGE_IDENTITY: mach_msg_option_t = 0x0000_0008; pub const MACH_SEND_TIMEOUT: mach_msg_option_t = 0x0000_0010; +pub const MACH_SEND_OVERRIDE: mach_msg_option_t = 0x0000_0020; pub const MACH_SEND_INTERRUPT: mach_msg_option_t = 0x0000_0040; pub const MACH_SEND_NOTIFY: mach_msg_option_t = 0x0000_0080; pub const MACH_SEND_ALWAYS: mach_msg_option_t = 0x0001_0000; +pub const MACH_SEND_FILTER_NONFATAL: mach_msg_option_t = 0x0001_0000; pub const MACH_SEND_TRAILER: mach_msg_option_t = 0x0002_0000; pub const MACH_SEND_NOIMPORTANCE: mach_msg_option_t = 0x0004_0000; pub const MACH_SEND_NODENAP: mach_msg_option_t = MACH_SEND_NOIMPORTANCE; pub const MACH_SEND_IMPORTANCE: mach_msg_option_t = 0x0008_0000; +pub const MACH_SEND_SYNC_OVERRIDE: mach_msg_option_t = 0x0010_0000; +pub const MACH_SEND_PROPAGATE_QOS: mach_msg_option_t = 0x0020_0000; +pub const MACH_SEND_SYNC_USE_THRPRI: mach_msg_option_t = MACH_SEND_PROPAGATE_QOS; pub const MACH_RCV_TIMEOUT: mach_msg_option_t = 0x0000_0100; pub const MACH_RCV_NOTIFY: mach_msg_option_t = 0x0000_0000; pub const MACH_RCV_INTERRUPT: mach_msg_option_t = 0x0000_0400; pub const MACH_RCV_VOUCHER: mach_msg_option_t = 0x0000_0800; pub const MACH_RCV_OVERWRITE: mach_msg_option_t = 0x0000_0000; +pub const MACH_RCV_GUARDED_DESC: mach_msg_option_t = 0x0000_1000; +pub const MACH_RCV_SYNC_WAIT: mach_msg_option_t = 0x0000_4000; +pub const MACH_RCV_SYNC_PEEK: mach_msg_option_t = 0x0000_8000; + +pub const MACH_MSG_STRICT_REPLY: mach_msg_option_t = 0x0000_0200; + +pub const MACH_RCV_TRAILER_NULL: mach_msg_trailer_type_t = 0; +pub const MACH_RCV_TRAILER_SEQNO: mach_msg_trailer_type_t = 1; +pub const MACH_RCV_TRAILER_SENDER: mach_msg_trailer_type_t = 2; +pub const MACH_RCV_TRAILER_AUDIT: mach_msg_trailer_type_t = 3; +pub const MACH_RCV_TRAILER_CTX: mach_msg_trailer_type_t = 4; +pub const MACH_RCV_TRAILER_AV: mach_msg_trailer_type_t = 7; +pub const MACH_RCV_TRAILER_LABELS: mach_msg_trailer_type_t = 8; pub const MACH_MSG_SUCCESS: mach_msg_return_t = 0x0000_0000; @@ -111,7 +138,10 @@ pub const MACH_SEND_TOO_LARGE: mach_msg_return_t = 0x1000_000e; pub const MACH_SEND_INVALID_TYPE: mach_msg_return_t = 0x1000_000f; pub const MACH_SEND_INVALID_HEADER: mach_msg_return_t = 0x1000_0010; pub const MACH_SEND_INVALID_TRAILER: mach_msg_return_t = 0x1000_0011; +pub const MACH_SEND_INVALID_CONTEXT: mach_msg_return_t = 0x1000_0012; pub const MACH_SEND_INVALID_RT_OOL_SIZE: mach_msg_return_t = 0x1000_0015; +pub const MACH_SEND_NO_GRANT_DEST: mach_msg_return_t = 0x1000_0016; +pub const MACH_SEND_MSG_FILTERED: mach_msg_return_t = 0x1000_0017; pub const MACH_RCV_IN_PROGRESS: mach_msg_return_t = 0x1000_4001; pub const MACH_RCV_INVALID_NAME: mach_msg_return_t = 0x1000_4002; @@ -129,6 +159,7 @@ pub const MACH_RCV_INVALID_TYPE: mach_msg_return_t = 0x1000_400d; pub const MACH_RCV_SCATTER_SMALL: mach_msg_return_t = 0x1000_400e; pub const MACH_RCV_INVALID_TRAILER: mach_msg_return_t = 0x1000_400f; pub const MACH_RCV_IN_PROGRESS_TIMED: mach_msg_return_t = 0x1000_4011; +pub const MACH_RCV_INVALID_REPLY: mach_msg_return_t = 0x1000_4012; #[repr(C)] #[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] @@ -163,6 +194,54 @@ pub struct mach_msg_trailer_t { pub msgh_trailer_size: mach_msg_trailer_size_t, } +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct mach_msg_seqno_trailer_t { + pub msgh_trailer_type: mach_msg_trailer_type_t, + pub msgh_trailer_size: mach_msg_trailer_size_t, + pub msgh_seqno: mach_port_seqno_t, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct security_token_t { + pub val: [c_uint; 2], +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct mach_msg_security_trailer_t { + pub msgh_trailer_type: mach_msg_trailer_type_t, + pub msgh_trailer_size: mach_msg_trailer_size_t, + pub msgh_seqno: mach_port_seqno_t, + pub msgh_sender: security_token_t, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct audit_token_t { + pub val: [c_uint; 8], +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct mach_msg_audit_trailer_t { + pub msgh_trailer_type: mach_msg_trailer_type_t, + pub msgh_trailer_size: mach_msg_trailer_size_t, + pub msgh_seqno: mach_port_seqno_t, + pub msgh_sender: security_token_t, + pub msgh_audit: audit_token_t, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct mach_msg_type_descriptor_t { + pub pad1: natural_t, + pub pad2: mach_msg_size_t, + pub pad3: [u8; 3], + pub type_: u8, // mach_msg_descriptor_type_t bitfield +} + #[repr(C)] #[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] pub struct mach_msg_port_descriptor_t { @@ -188,7 +267,7 @@ impl mach_msg_port_descriptor_t { #[repr(C)] #[derive(Copy, Clone, Debug, Hash, PartialOrd, PartialEq, Eq, Ord)] pub struct mach_msg_ool_descriptor_t { - pub address: *mut ::libc::c_void, + pub address: *mut c_void, #[cfg(not(target_pointer_width = "64"))] pub size: mach_msg_size_t, pub deallocate: u8, // boolean_t bitfield @@ -201,10 +280,10 @@ pub struct mach_msg_ool_descriptor_t { impl mach_msg_ool_descriptor_t { pub fn new( - address: *mut ::libc::c_void, + address: *mut c_void, deallocate: bool, copy: mach_msg_copy_options_t, - size: u32, + size: mach_msg_size_t, ) -> Self { Self { address, @@ -220,7 +299,7 @@ impl mach_msg_ool_descriptor_t { #[repr(C)] #[derive(Copy, Clone, Debug, Hash, PartialOrd, PartialEq, Eq, Ord)] pub struct mach_msg_ool_ports_descriptor_t { - pub address: *mut ::libc::c_void, + pub address: *mut c_void, #[cfg(not(target_pointer_width = "64"))] pub count: mach_msg_size_t, pub deallocate: u8, // boolean_t bitfield @@ -231,7 +310,26 @@ pub struct mach_msg_ool_ports_descriptor_t { pub count: mach_msg_size_t, } -extern "C" { +impl mach_msg_ool_ports_descriptor_t { + pub fn new( + address: *mut c_void, + deallocate: bool, + copy: mach_msg_copy_options_t, + disposition: mach_msg_type_name_t, + count: mach_msg_size_t, + ) -> Self { + Self { + address, + deallocate: if deallocate { 1 } else { 0 }, + copy: copy as u8, + disposition: disposition as u8, + type_: MACH_MSG_OOL_PORTS_DESCRIPTOR as u8, + count, + } + } +} + +unsafe extern "C" { pub fn mach_msg( msg: *mut mach_msg_header_t, option: mach_msg_option_t, diff --git a/third_party/rust/mach2/src/mig.rs b/third_party/rust/mach2/src/mig.rs new file mode 100644 index 000000000000..ad0bfa5c881e --- /dev/null +++ b/third_party/rust/mach2/src/mig.rs @@ -0,0 +1,74 @@ +//! This module corresponds to `mach/mig.h`. + +use crate::kern_return::kern_return_t; +use crate::message::{ + mach_msg_header_t, mach_msg_id_t, mach_msg_size_t, mach_msg_type_descriptor_t, +}; +use crate::port::mach_port_t; +use crate::vm_types::{vm_address_t, vm_size_t}; +use core::ffi::{c_char, c_int, c_uint}; +use core::ptr; + +pub type mig_stub_routine_t = + Option; +pub type mig_routine_t = mig_stub_routine_t; +pub type mig_server_routine_t = + Option mig_routine_t>; +pub type mig_impl_routine_t = Option kern_return_t>; + +pub type routine_arg_descriptor_t = *mut mach_msg_type_descriptor_t; +pub type mig_routine_arg_descriptor_t = *mut mach_msg_type_descriptor_t; + +pub const MIG_ROUTINE_ARG_DESCRIPTOR_NULL: mig_routine_arg_descriptor_t = ptr::null_mut(); + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct routine_descriptor { + pub impl_routine: mig_impl_routine_t, + pub stub_routine: mig_stub_routine_t, + pub argc: c_uint, + pub descr_count: c_uint, + pub arg_descr: routine_arg_descriptor_t, + pub max_reply_msg: c_uint, +} + +pub type routine_descriptor_t = *mut routine_descriptor; +pub type mig_routine_descriptor = routine_descriptor; +pub type mig_routine_descriptor_t = *mut mig_routine_descriptor; + +pub const MIG_ROUTINE_DESCRIPTOR_NULL: mig_routine_descriptor_t = ptr::null_mut(); + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct mig_subsystem { + pub server: mig_server_routine_t, + pub start: mach_msg_id_t, + pub end: mach_msg_id_t, + pub maxsize: mach_msg_size_t, + pub reserved: vm_address_t, + pub routine: [mig_routine_descriptor; 1], +} + +pub type mig_subsystem_t = *mut mig_subsystem; + +pub const MIG_SUBSYSTEM_NULL: mig_subsystem_t = ptr::null_mut(); + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct mig_symtab { + pub ms_routine_name: *mut c_char, + pub ms_routine_number: c_int, + pub ms_routine: Option, +} + +pub type mig_symtab_t = mig_symtab; + +unsafe extern "C" { + pub fn mig_get_reply_port() -> mach_port_t; + pub fn mig_dealloc_reply_port(reply_port: mach_port_t); + pub fn mig_put_reply_port(reply_port: mach_port_t); + pub fn mig_strncpy(dest: *mut c_char, src: *const c_char, len: c_int) -> c_int; + pub fn mig_strncpy_zerofill(dest: *mut c_char, src: *const c_char, len: c_int) -> c_int; + pub fn mig_allocate(address: *mut vm_address_t, size: vm_size_t); + pub fn mig_deallocate(address: vm_address_t, size: vm_size_t); +} diff --git a/third_party/rust/mach2/src/ndr.rs b/third_party/rust/mach2/src/ndr.rs new file mode 100644 index 000000000000..e381eeefd667 --- /dev/null +++ b/third_party/rust/mach2/src/ndr.rs @@ -0,0 +1,21 @@ +//! This module roughly corresponds to `mach/ndr.h`. + +use core::ffi::c_uchar; + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +#[allow(dead_code)] +pub struct NDR_record_t { + mig_vers: c_uchar, + if_vers: c_uchar, + reserved1: c_uchar, + mig_encoding: c_uchar, + int_rep: c_uchar, + char_rep: c_uchar, + float_rep: c_uchar, + reserved32: c_uchar, +} + +unsafe extern "C" { + pub static NDR_record: NDR_record_t; +} diff --git a/third_party/rust/mach2/src/notify.rs b/third_party/rust/mach2/src/notify.rs new file mode 100644 index 000000000000..8f70cc161b71 --- /dev/null +++ b/third_party/rust/mach2/src/notify.rs @@ -0,0 +1,77 @@ +//! This module corresponds to `mach/notify.h`. + +use crate::message::{ + mach_msg_body_t, mach_msg_header_t, mach_msg_port_descriptor_t, mach_msg_security_trailer_t, + mach_msg_type_number_t, +}; +use crate::ndr::NDR_record_t; +use crate::port::mach_port_name_t; +use crate::port::mach_port_t; +use core::ffi::c_int; + +pub const MACH_NOTIFY_FIRST: c_int = 0o100; +pub const MACH_NOTIFY_PORT_DELETED: c_int = MACH_NOTIFY_FIRST + 0o01; +pub const MACH_NOTIFY_SEND_POSSIBLE: c_int = MACH_NOTIFY_FIRST + 0o02; +pub const MACH_NOTIFY_PORT_DESTROYED: c_int = MACH_NOTIFY_FIRST + 0o05; +pub const MACH_NOTIFY_NO_SENDERS: c_int = MACH_NOTIFY_FIRST + 0o06; +pub const MACH_NOTIFY_SEND_ONCE: c_int = MACH_NOTIFY_FIRST + 0o07; +pub const MACH_NOTIFY_DEAD_NAME: c_int = MACH_NOTIFY_FIRST + 0o10; +pub const MACH_NOTIFY_LAST: c_int = MACH_NOTIFY_FIRST + 0o15; + +pub type notify_port_t = mach_port_t; + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +#[allow(non_snake_case)] +pub struct mach_port_deleted_notification_t { + pub not_header: mach_msg_header_t, + pub NDR: NDR_record_t, + pub not_port: mach_port_name_t, + pub trailer: mach_msg_security_trailer_t, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +#[allow(non_snake_case)] +pub struct mach_send_possible_notification_t { + pub not_header: mach_msg_header_t, + pub NDR: NDR_record_t, + pub not_port: mach_port_name_t, + pub trailer: mach_msg_security_trailer_t, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct mach_port_destroyed_notification_t { + pub not_header: mach_msg_header_t, + pub not_body: mach_msg_body_t, + pub not_port: mach_msg_port_descriptor_t, + pub trailer: mach_msg_security_trailer_t, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +#[allow(non_snake_case)] +pub struct mach_no_senders_notification_t { + pub not_header: mach_msg_header_t, + pub NDR: NDR_record_t, + pub not_count: mach_msg_type_number_t, + pub trailer: mach_msg_security_trailer_t, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct mach_send_once_notification_t { + pub not_header: mach_msg_header_t, + pub trailer: mach_msg_security_trailer_t, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +#[allow(non_snake_case)] +pub struct mach_dead_name_notification_t { + pub not_header: mach_msg_header_t, + pub NDR: NDR_record_t, + pub not_port: mach_port_name_t, + pub trailer: mach_msg_security_trailer_t, +} diff --git a/third_party/rust/mach2/src/policy.rs b/third_party/rust/mach2/src/policy.rs new file mode 100644 index 000000000000..1d369f100a65 --- /dev/null +++ b/third_party/rust/mach2/src/policy.rs @@ -0,0 +1,147 @@ +//! This module corresponds to `mach/policy.h`. + +use crate::boolean::boolean_t; +use crate::message::mach_msg_type_number_t; +use crate::vm_types::integer_t; +use core::ffi::c_int; +use core::mem; + +pub type policy_t = c_int; +pub type policy_info_t = *mut integer_t; +pub type policy_base_t = *mut integer_t; +pub type policy_limit_t = *mut integer_t; + +pub const POLICY_NULL: policy_t = 0; +pub const POLICY_TIMESHARE: policy_t = 1; +pub const POLICY_RR: policy_t = 2; +pub const POLICY_FIFO: policy_t = 4; + +pub const POLICYCLASS_FIXEDPRI: policy_t = POLICY_RR | POLICY_FIFO; + +#[inline] +pub const fn invalid_policy(policy: policy_t) -> bool { + !(policy == POLICY_TIMESHARE || policy == POLICY_RR || policy == POLICY_FIFO) +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct policy_timeshare_base { + pub base_priority: integer_t, +} + +pub type policy_timeshare_base_t = *mut policy_timeshare_base; +pub type policy_timeshare_base_data_t = policy_timeshare_base; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct policy_timeshare_limit { + pub max_priority: integer_t, +} + +pub type policy_timeshare_limit_t = *mut policy_timeshare_limit; +pub type policy_timeshare_limit_data_t = policy_timeshare_limit; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct policy_timeshare_info { + pub max_priority: integer_t, + pub base_priority: integer_t, + pub cur_priority: integer_t, + pub depressed: boolean_t, + pub depress_priority: integer_t, +} + +pub type policy_timeshare_info_t = *mut policy_timeshare_info; +pub type policy_timeshare_info_data_t = policy_timeshare_info; + +pub const POLICY_TIMESHARE_BASE_COUNT: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; +pub const POLICY_TIMESHARE_LIMIT_COUNT: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; +pub const POLICY_TIMESHARE_INFO_COUNT: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct policy_rr_base { + pub base_priority: integer_t, + pub quantum: integer_t, +} + +pub type policy_rr_base_t = *mut policy_rr_base; +pub type policy_rr_base_data_t = policy_rr_base; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct policy_rr_limit { + pub max_priority: integer_t, +} + +pub type policy_rr_limit_t = *mut policy_rr_limit; +pub type policy_rr_limit_data_t = policy_rr_limit; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct policy_rr_info { + pub max_priority: integer_t, + pub base_priority: integer_t, + pub quantum: integer_t, + pub depressed: boolean_t, + pub depress_priority: integer_t, +} + +pub type policy_rr_info_t = *mut policy_rr_info; +pub type policy_rr_info_data_t = policy_rr_info; + +pub const POLICY_RR_BASE_COUNT: mach_msg_type_number_t = (mem::size_of::() + / mem::size_of::()) + as mach_msg_type_number_t; +pub const POLICY_RR_LIMIT_COUNT: mach_msg_type_number_t = (mem::size_of::() + / mem::size_of::()) + as mach_msg_type_number_t; +pub const POLICY_RR_INFO_COUNT: mach_msg_type_number_t = (mem::size_of::() + / mem::size_of::()) + as mach_msg_type_number_t; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct policy_fifo_base { + pub base_priority: integer_t, +} + +pub type policy_fifo_base_t = *mut policy_fifo_base; +pub type policy_fifo_base_data_t = policy_fifo_base; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct policy_fifo_limit { + pub max_priority: integer_t, +} + +pub type policy_fifo_limit_t = *mut policy_fifo_limit; +pub type policy_fifo_limit_data_t = policy_fifo_limit; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct policy_fifo_info { + pub max_priority: integer_t, + pub base_priority: integer_t, + pub depressed: boolean_t, + pub depress_priority: integer_t, +} + +pub type policy_fifo_info_t = *mut policy_fifo_info; +pub type policy_fifo_info_data_t = policy_fifo_info; + +pub const POLICY_FIFO_BASE_COUNT: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; +pub const POLICY_FIFO_LIMIT_COUNT: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; +pub const POLICY_FIFO_INFO_COUNT: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; diff --git a/third_party/rust/mach2/src/port.rs b/third_party/rust/mach2/src/port.rs index 151a3aa40ca0..8c1749c166bf 100644 --- a/third_party/rust/mach2/src/port.rs +++ b/third_party/rust/mach2/src/port.rs @@ -1,16 +1,12 @@ //! This module corresponds to `mach/port.h` -use vm_types::{integer_t, natural_t}; +use crate::vm_types::{integer_t, natural_t}; +use core::ffi::c_uint; pub type mach_port_name_t = natural_t; -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] -pub struct ipc_port; - -pub type ipc_port_t = *mut ipc_port; - -pub type mach_port_t = ::libc::c_uint; +pub type mach_port_t = c_uint; +pub type mach_port_array_t = *mut mach_port_t; pub const MACH_PORT_NULL: mach_port_t = 0; pub const MACH_PORT_DEAD: mach_port_t = !0; @@ -25,4 +21,44 @@ pub const MACH_PORT_RIGHT_DEAD_NAME: mach_port_right_t = 4; pub const MACH_PORT_RIGHT_LABELH: mach_port_right_t = 5; pub const MACH_PORT_RIGHT_NUMBER: mach_port_right_t = 6; +pub type mach_port_type_t = natural_t; + +pub type mach_port_urefs_t = natural_t; pub type mach_port_delta_t = integer_t; + +pub type mach_port_seqno_t = natural_t; +pub type mach_port_mscount_t = natural_t; +pub type mach_port_msgcount_t = natural_t; +pub type mach_port_rights_t = natural_t; + +pub const MACH_PORT_QLIMIT_ZERO: mach_port_msgcount_t = 0; +pub const MACH_PORT_QLIMIT_BASIC: mach_port_msgcount_t = 5; +pub const MACH_PORT_QLIMIT_SMALL: mach_port_msgcount_t = 16; +pub const MACH_PORT_QLIMIT_LARGE: mach_port_msgcount_t = 1024; +pub const MACH_PORT_QLIMIT_KERNEL: mach_port_msgcount_t = 65534; +pub const MACH_PORT_QLIMIT_MIN: mach_port_msgcount_t = MACH_PORT_QLIMIT_ZERO; +pub const MACH_PORT_QLIMIT_DEFAULT: mach_port_msgcount_t = MACH_PORT_QLIMIT_BASIC; +pub const MACH_PORT_QLIMIT_MAX: mach_port_msgcount_t = MACH_PORT_QLIMIT_LARGE; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct mach_port_limits_t { + pub mpl_qlimit: mach_port_msgcount_t, +} + +pub const MPO_CONTEXT_AS_GUARD: u32 = 1; +pub const MPO_QLIMIT: u32 = 2; +pub const MPO_TEMPOWNER: u32 = 4; +pub const MPO_IMPORTANCE_RECEIVER: u32 = 8; +pub const MPO_INSERT_SEND_RIGHT: u32 = 0x10; +pub const MPO_STRICT: u32 = 0x20; +pub const MPO_DENAP_RECEIVER: u32 = 0x40; +pub const MPO_IMMOVABLE_RECEIVE: u32 = 0x80; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct mach_port_options_t { + pub flags: u32, + pub mpl: mach_port_limits_t, + pub reserved: [u64; 2], +} diff --git a/third_party/rust/mach2/src/semaphore.rs b/third_party/rust/mach2/src/semaphore.rs new file mode 100644 index 000000000000..ce0ac5dba2ab --- /dev/null +++ b/third_party/rust/mach2/src/semaphore.rs @@ -0,0 +1,23 @@ +//! This module corresponds to `mach/semaphore.h` + +use crate::clock_types::mach_timespec_t; +use crate::kern_return::kern_return_t; +use crate::mach_types::{semaphore_t, task_t}; +use crate::sync_policy::sync_policy_t; +use core::ffi::c_int; + +unsafe extern "C" { + pub fn semaphore_create( + task: task_t, + semaphore: *mut semaphore_t, + policy: sync_policy_t, + value: c_int, + ) -> kern_return_t; + pub fn semaphore_signal(semaphore: *mut semaphore_t) -> kern_return_t; + pub fn semaphore_wait(semaphore: *mut semaphore_t) -> kern_return_t; + pub fn semaphore_timedwait( + semaphore: *mut semaphore_t, + timeout: mach_timespec_t, + ) -> kern_return_t; + pub fn semaphore_destroy(task: task_t, semaphore: *mut semaphore_t) -> kern_return_t; +} diff --git a/third_party/rust/mach2/src/structs.rs b/third_party/rust/mach2/src/structs.rs index 75dc0e8dba5f..8e041e14cd8f 100644 --- a/third_party/rust/mach2/src/structs.rs +++ b/third_party/rust/mach2/src/structs.rs @@ -1,8 +1,33 @@ -//! This module corresponds to `mach/_structs.h`. +//! This module corresponds to `mach/i386/_structs.h` and `mach/arm/_structs.h`. -use mem; -use message::mach_msg_type_number_t; +use crate::message::mach_msg_type_number_t; +use core::ffi::c_int; +#[cfg(target_arch = "aarch64")] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct arm_thread_state64_t { + pub __x: [u64; 29], + pub __fp: u64, + pub __lr: u64, + pub __sp: u64, + pub __pc: u64, + pub __cpsr: u32, + pub __pad: u32, +} + +#[cfg(target_arch = "aarch64")] +impl arm_thread_state64_t { + pub fn new() -> Self { + Default::default() + } + + pub fn count() -> mach_msg_type_number_t { + (core::mem::size_of::() / core::mem::size_of::()) as mach_msg_type_number_t + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[repr(C)] #[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] pub struct x86_thread_state64_t { @@ -29,34 +54,13 @@ pub struct x86_thread_state64_t { pub __gs: u64, } +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] impl x86_thread_state64_t { pub fn new() -> Self { - Self { - __rax: 0, - __rbx: 0, - __rcx: 0, - __rdx: 0, - __rdi: 0, - __rsi: 0, - __rbp: 0, - __rsp: 0, - __r8: 0, - __r9: 0, - __r10: 0, - __r11: 0, - __r12: 0, - __r13: 0, - __r14: 0, - __r15: 0, - __rip: 0, - __rflags: 0, - __cs: 0, - __fs: 0, - __gs: 0, - } + Default::default() } pub fn count() -> mach_msg_type_number_t { - (mem::size_of::() / mem::size_of::<::libc::c_int>()) as mach_msg_type_number_t + (core::mem::size_of::() / core::mem::size_of::()) as mach_msg_type_number_t } } diff --git a/third_party/rust/mach2/src/sync_policy.rs b/third_party/rust/mach2/src/sync_policy.rs new file mode 100644 index 000000000000..29604ecca82d --- /dev/null +++ b/third_party/rust/mach2/src/sync_policy.rs @@ -0,0 +1,10 @@ +//! This module corresponds to `mach/sync_policy.h` +use core::ffi::c_int; + +pub type sync_policy_t = c_int; + +pub const SYNC_POLICY_FIFO: sync_policy_t = 0x0; +pub const SYNC_POLICY_FIXED_PRIORITY: sync_policy_t = 0x1; +pub const SYNC_POLICY_REVERSED: sync_policy_t = 0x2; +pub const SYNC_POLICY_ORDER_MASK: sync_policy_t = 0x3; +pub const SYNC_POLICY_LIFO: sync_policy_t = SYNC_POLICY_FIFO | SYNC_POLICY_REVERSED; diff --git a/third_party/rust/mach2/src/task.rs b/third_party/rust/mach2/src/task.rs index 1ca2280eb100..3e45819a2fe9 100644 --- a/third_party/rust/mach2/src/task.rs +++ b/third_party/rust/mach2/src/task.rs @@ -1,31 +1,69 @@ -//! This module corresponds to `mach/task.defs`. +//! This module corresponds to `mach/task.h`. -use kern_return::kern_return_t; -use mach_types::{task_name_t, task_t, thread_act_array_t}; -use message::mach_msg_type_number_t; -use port::mach_port_t; -use task_info::{task_flavor_t, task_info_t}; +use crate::boolean::boolean_t; +use crate::dyld_kernel::{ + dyld_kernel_image_info_array_t, dyld_kernel_image_info_t, dyld_kernel_process_info_t, +}; +use crate::exception_types::{ + exception_behavior_array_t, exception_behavior_t, exception_flavor_array_t, + exception_mask_array_t, exception_mask_t, +}; +use crate::kern_return::kern_return_t; +use crate::mach_debug::ipc_info::exception_handler_info_array_t; +use crate::mach_debug::zone_info::{mach_zone_name_array_t, task_zone_info_array_t}; +use crate::mach_types::{ + exception_handler_array_t, kcdata_object_t, ledger_array_t, lock_set_t, processor_set_name_t, + processor_set_t, task_id_token_t, task_inspect_t, task_name_t, task_read_t, + task_suspension_token_t, task_t, thread_act_array_t, thread_act_t, +}; +use crate::mach_voucher_types::{ipc_voucher_t, mach_voucher_selector_t}; +use crate::message::{ + mach_msg_body_t, mach_msg_header_t, mach_msg_ool_descriptor_t, mach_msg_ool_ports_descriptor_t, + mach_msg_port_descriptor_t, mach_msg_type_number_t, +}; +use crate::ndr::NDR_record_t; +use crate::policy::{policy_base_t, policy_limit_t, policy_t}; +use crate::port::{mach_port_array_t, mach_port_name_t, mach_port_t}; +use crate::task_info::{ + task_corpse_forking_behavior_t, task_exc_guard_behavior_t, task_flavor_t, task_info_t, + task_purgable_info_t, +}; +use crate::task_inspect::{task_inspect_flavor_t, task_inspect_info_t}; +use crate::task_special_ports::task_special_port_t; +use crate::thread_status::{thread_state_flavor_t, thread_state_t}; +use crate::vm_types::{integer_t, mach_vm_address_t, mach_vm_size_t, natural_t, vm_address_t}; +use core::ffi::{c_int, c_uint}; -pub type task_special_port_t = ::libc::c_int; +pub const task_MSG_COUNT: c_uint = 66; -pub const TASK_KERNEL_PORT: task_special_port_t = 1; -pub const TASK_HOST_PORT: task_special_port_t = 2; -pub const TASK_NAME_PORT: task_special_port_t = 3; -pub const TASK_BOOTSTRAP_PORT: task_special_port_t = 4; +pub type task_policy_flavor_t = natural_t; +pub type task_policy_t = *mut integer_t; +pub type emulation_vector_t = *mut integer_t; -extern "C" { - pub fn task_resume(target_task: task_t) -> kern_return_t; - pub fn task_suspend(target_task: task_t) -> kern_return_t; - pub fn task_get_special_port( - task: task_t, - which_port: task_special_port_t, - special_port: *mut mach_port_t, +unsafe extern "C" { + pub fn task_create( + target_task: task_t, + ledgers: ledger_array_t, + ledgersCnt: mach_msg_type_number_t, + inherit_memory: boolean_t, + child_task: *mut task_t, ) -> kern_return_t; + pub fn task_terminate(target_task: task_t) -> kern_return_t; pub fn task_threads( target_task: task_t, act_list: *mut thread_act_array_t, act_list_cnt: *mut mach_msg_type_number_t, ) -> kern_return_t; + pub fn mach_ports_register( + target_task: task_t, + init_port_set: mach_port_array_t, + init_port_setCnt: mach_msg_type_number_t, + ) -> kern_return_t; + pub fn mach_ports_lookup( + target_task: task_t, + init_port_set: *mut mach_port_array_t, + init_port_setCnt: *mut mach_msg_type_number_t, + ) -> kern_return_t; pub fn task_info( target_task: task_name_t, flavor: task_flavor_t, @@ -38,4 +76,920 @@ extern "C" { task_info_in: task_info_t, task_info_inCnt: mach_msg_type_number_t, ) -> kern_return_t; + pub fn task_suspend(target_task: task_t) -> kern_return_t; + pub fn task_resume(target_task: task_t) -> kern_return_t; + pub fn task_get_special_port( + task: task_t, + which_port: task_special_port_t, + special_port: *mut mach_port_t, + ) -> kern_return_t; + pub fn task_set_special_port( + task: task_t, + which_port: task_special_port_t, + special_port: mach_port_t, + ) -> kern_return_t; + pub fn thread_create(parent_task: task_t, child_act: *mut thread_act_t) -> kern_return_t; + pub fn thread_create_running( + parent_task: task_t, + flavor: thread_state_flavor_t, + new_state: thread_state_t, + new_stateCnt: mach_msg_type_number_t, + child_act: *mut thread_act_t, + ) -> kern_return_t; + pub fn task_set_exception_ports( + task: task_t, + exception_mask: exception_mask_t, + new_port: mach_port_t, + behavior: exception_behavior_t, + new_flavor: thread_state_flavor_t, + ) -> kern_return_t; + pub fn task_get_exception_ports( + task: task_t, + exception_mask: exception_mask_t, + masks: exception_mask_array_t, + masksCnt: *mut mach_msg_type_number_t, + old_handlers: exception_handler_array_t, + old_behaviors: exception_behavior_array_t, + old_flavors: exception_flavor_array_t, + ) -> kern_return_t; + pub fn task_swap_exception_ports( + task: task_t, + exception_mask: exception_mask_t, + new_port: mach_port_t, + behavior: exception_behavior_t, + new_flavor: thread_state_flavor_t, + masks: exception_mask_array_t, + masksCnt: *mut mach_msg_type_number_t, + old_handlers: exception_handler_array_t, + old_behaviors: exception_behavior_array_t, + old_flavors: exception_flavor_array_t, + ) -> kern_return_t; + pub fn lock_set_create( + task: task_t, + new_lock_set: *mut lock_set_t, + n_ulocks: c_int, + policy: c_int, + ) -> kern_return_t; + pub fn lock_set_destroy(task: task_t, lock_set: lock_set_t) -> kern_return_t; + pub fn task_policy_set( + task: task_t, + flavor: task_policy_flavor_t, + policy_info: task_policy_t, + policy_infoCnt: mach_msg_type_number_t, + ) -> kern_return_t; + pub fn task_policy_get( + task: task_t, + flavor: task_policy_flavor_t, + policy_info: task_policy_t, + policy_infoCnt: *mut mach_msg_type_number_t, + get_default: *mut boolean_t, + ) -> kern_return_t; + pub fn task_sample(task: task_t, reply: mach_port_t) -> kern_return_t; + pub fn task_policy( + task: task_t, + policy: policy_t, + base: policy_base_t, + baseCnt: mach_msg_type_number_t, + set_limit: boolean_t, + change: boolean_t, + ) -> kern_return_t; + pub fn task_set_emulation( + target_port: task_t, + routine_entry_pt: vm_address_t, + routine_number: c_int, + ) -> kern_return_t; + pub fn task_get_emulation_vector( + task: task_t, + vector_start: *mut c_int, + emulation_vector: *mut emulation_vector_t, + emulation_vectorCnt: *mut mach_msg_type_number_t, + ) -> kern_return_t; + pub fn task_set_emulation_vector( + task: task_t, + vector_start: c_int, + emulation_vector: emulation_vector_t, + emulation_vectorCnt: mach_msg_type_number_t, + ) -> kern_return_t; + pub fn task_set_ras_pc( + target_task: task_t, + basepc: vm_address_t, + boundspc: vm_address_t, + ) -> kern_return_t; + pub fn task_assign( + task: task_t, + new_set: processor_set_t, + assign_threads: boolean_t, + ) -> kern_return_t; + pub fn task_assign_default(task: task_t, assign_threads: boolean_t) -> kern_return_t; + pub fn task_get_assignment( + task: task_t, + assigned_set: *mut processor_set_name_t, + ) -> kern_return_t; + pub fn task_set_policy( + task: task_t, + pset: processor_set_t, + policy: policy_t, + base: policy_base_t, + baseCnt: mach_msg_type_number_t, + limit: policy_limit_t, + limitCnt: mach_msg_type_number_t, + change: boolean_t, + ) -> kern_return_t; + pub fn task_get_state( + task: task_t, + flavor: thread_state_flavor_t, + old_state: thread_state_t, + old_stateCnt: *mut mach_msg_type_number_t, + ) -> kern_return_t; + pub fn task_set_state( + task: task_t, + flavor: thread_state_flavor_t, + new_state: thread_state_t, + new_stateCnt: mach_msg_type_number_t, + ) -> kern_return_t; + pub fn task_zone_info( + target_task: task_inspect_t, + names: *mut mach_zone_name_array_t, + namesCnt: *mut mach_msg_type_number_t, + info: *mut task_zone_info_array_t, + infoCnt: *mut mach_msg_type_number_t, + ) -> kern_return_t; + pub fn task_set_phys_footprint_limit( + task: task_t, + new_limit: c_int, + old_limit: *mut c_int, + ) -> kern_return_t; + pub fn task_suspend2( + target_task: task_read_t, + suspend_token: *mut task_suspension_token_t, + ) -> kern_return_t; + pub fn task_resume2(suspend_token: task_suspension_token_t) -> kern_return_t; + pub fn task_purgable_info( + task: task_inspect_t, + stats: *mut task_purgable_info_t, + ) -> kern_return_t; + pub fn task_get_mach_voucher( + task: task_read_t, + which: mach_voucher_selector_t, + voucher: *mut ipc_voucher_t, + ) -> kern_return_t; + pub fn task_set_mach_voucher(task: task_t, voucher: ipc_voucher_t) -> kern_return_t; + pub fn task_swap_mach_voucher( + task: task_t, + new_voucher: ipc_voucher_t, + old_voucher: *mut ipc_voucher_t, + ) -> kern_return_t; + pub fn task_generate_corpse( + task: task_read_t, + corpse_task_port: *mut mach_port_t, + ) -> kern_return_t; + pub fn task_map_corpse_info( + task: task_t, + corspe_task: task_read_t, + kcd_addr_begin: *mut vm_address_t, + kcd_size: *mut u32, + ) -> kern_return_t; + pub fn task_register_dyld_image_infos( + task: task_t, + dyld_images: dyld_kernel_image_info_array_t, + dyld_imagesCnt: mach_msg_type_number_t, + ) -> kern_return_t; + pub fn task_unregister_dyld_image_infos( + task: task_t, + dyld_images: dyld_kernel_image_info_array_t, + dyld_imagesCnt: mach_msg_type_number_t, + ) -> kern_return_t; + pub fn task_get_dyld_image_infos( + task: task_read_t, + dyld_images: *mut dyld_kernel_image_info_array_t, + dyld_imagesCnt: *mut mach_msg_type_number_t, + ) -> kern_return_t; + pub fn task_register_dyld_shared_cache_image_info( + task: task_t, + dyld_cache_image: dyld_kernel_image_info_t, + no_cache: boolean_t, + private_cache: boolean_t, + ) -> kern_return_t; + pub fn task_register_dyld_set_dyld_state(task: task_t, dyld_state: u8) -> kern_return_t; + pub fn task_register_dyld_get_process_state( + task: task_t, + dyld_process_state: *mut dyld_kernel_process_info_t, + ) -> kern_return_t; + pub fn task_map_corpse_info_64( + task: task_t, + corspe_task: task_read_t, + kcd_addr_begin: *mut mach_vm_address_t, + kcd_size: *mut mach_vm_size_t, + ) -> kern_return_t; + pub fn task_inspect( + task: task_inspect_t, + flavor: task_inspect_flavor_t, + info_out: task_inspect_info_t, + info_outCnt: *mut mach_msg_type_number_t, + ) -> kern_return_t; + pub fn task_get_exc_guard_behavior( + task: task_inspect_t, + behavior: *mut task_exc_guard_behavior_t, + ) -> kern_return_t; + pub fn task_set_exc_guard_behavior( + task: task_t, + behavior: task_exc_guard_behavior_t, + ) -> kern_return_t; + pub fn task_dyld_process_info_notify_register( + target_task: task_read_t, + notify: mach_port_t, + ) -> kern_return_t; + pub fn task_create_identity_token(task: task_t, token: *mut task_id_token_t) -> kern_return_t; + pub fn task_identity_token_get_task_port( + token: task_id_token_t, + flavor: task_flavor_t, + task_port: *mut mach_port_t, + ) -> kern_return_t; + pub fn task_dyld_process_info_notify_deregister( + target_task: task_read_t, + notify: mach_port_name_t, + ) -> kern_return_t; + pub fn task_get_exception_ports_info( + port: mach_port_t, + exception_mask: exception_mask_t, + masks: exception_mask_array_t, + masksCnt: *mut mach_msg_type_number_t, + old_handlers_info: exception_handler_info_array_t, + old_behaviors: exception_behavior_array_t, + old_flavors: exception_flavor_array_t, + ) -> kern_return_t; + pub fn task_test_sync_upcall(task: task_t, port: mach_port_t) -> kern_return_t; + pub fn task_set_corpse_forking_behavior( + task: task_t, + behavior: task_corpse_forking_behavior_t, + ) -> kern_return_t; + pub fn task_test_async_upcall_propagation( + task: task_t, + port: mach_port_t, + qos: c_int, + iotier: c_int, + ) -> kern_return_t; + pub fn task_map_kcdata_object_64( + task: task_t, + kcdata_object: kcdata_object_t, + kcd_addr_begin: *mut mach_vm_address_t, + kcd_size: *mut mach_vm_size_t, + ) -> kern_return_t; + pub fn task_register_hardened_exception_handler( + task: task_t, + signed_pc_key: u32, + exceptions_allowed: exception_mask_t, + behaviors_allowed: exception_behavior_t, + flavors_allowed: thread_state_flavor_t, + new_exception_port: mach_port_t, + ) -> kern_return_t; +} + +#[repr(C, packed(4))] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_create_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub ledgers: mach_msg_ool_ports_descriptor_t, + pub NDR: NDR_record_t, + pub ledgersCnt: mach_msg_type_number_t, + pub inherit_memory: boolean_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_terminate_t { + pub Head: mach_msg_header_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_threads_t { + pub Head: mach_msg_header_t, +} + +#[repr(C, packed(4))] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__mach_ports_register_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub init_port_set: mach_msg_ool_ports_descriptor_t, + pub NDR: NDR_record_t, + pub init_port_setCnt: mach_msg_type_number_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__mach_ports_lookup_t { + pub Head: mach_msg_header_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_info_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub flavor: task_flavor_t, + pub task_info_outCnt: mach_msg_type_number_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_set_info_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub flavor: task_flavor_t, + pub task_info_inCnt: mach_msg_type_number_t, + pub task_info_in: [integer_t; 94], +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_suspend_t { + pub Head: mach_msg_header_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_resume_t { + pub Head: mach_msg_header_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_get_special_port_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub which_port: task_special_port_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_set_special_port_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub special_port: mach_msg_port_descriptor_t, + pub NDR: NDR_record_t, + pub which_port: task_special_port_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__thread_create_t { + pub Head: mach_msg_header_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__thread_create_running_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub flavor: thread_state_flavor_t, + pub new_stateCnt: mach_msg_type_number_t, + pub new_state: [natural_t; 1296], +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_set_exception_ports_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub new_port: mach_msg_port_descriptor_t, + pub NDR: NDR_record_t, + pub exception_mask: exception_mask_t, + pub behavior: exception_behavior_t, + pub new_flavor: thread_state_flavor_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_get_exception_ports_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub exception_mask: exception_mask_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_swap_exception_ports_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub new_port: mach_msg_port_descriptor_t, + pub NDR: NDR_record_t, + pub exception_mask: exception_mask_t, + pub behavior: exception_behavior_t, + pub new_flavor: thread_state_flavor_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__lock_set_create_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub n_ulocks: c_int, + pub policy: c_int, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__lock_set_destroy_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub lock_set: mach_msg_port_descriptor_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__semaphore_create_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub policy: c_int, + pub value: c_int, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_policy_set_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub flavor: task_policy_flavor_t, + pub policy_infoCnt: mach_msg_type_number_t, + pub policy_info: [integer_t; 16], +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_policy_get_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub flavor: task_policy_flavor_t, + pub policy_infoCnt: mach_msg_type_number_t, + pub get_default: boolean_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_sample_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub reply: mach_msg_port_descriptor_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_policy_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub policy: policy_t, + pub baseCnt: mach_msg_type_number_t, + pub base: [integer_t; 5], + pub set_limit: boolean_t, + pub change: boolean_t, +} + +#[repr(C, packed(4))] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_set_emulation_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub routine_entry_pt: vm_address_t, + pub routine_number: c_int, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_get_emulation_vector_t { + pub Head: mach_msg_header_t, +} + +#[repr(C, packed(4))] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_set_emulation_vector_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub emulation_vector: mach_msg_ool_descriptor_t, + pub NDR: NDR_record_t, + pub vector_start: c_int, + pub emulation_vectorCnt: mach_msg_type_number_t, +} + +#[repr(C, packed(4))] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_set_ras_pc_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub basepc: vm_address_t, + pub boundspc: vm_address_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_assign_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub new_set: mach_msg_port_descriptor_t, + pub NDR: NDR_record_t, + pub assign_threads: boolean_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_assign_default_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub assign_threads: boolean_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_get_assignment_t { + pub Head: mach_msg_header_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_set_policy_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub pset: mach_msg_port_descriptor_t, + pub NDR: NDR_record_t, + pub policy: policy_t, + pub baseCnt: mach_msg_type_number_t, + pub base: [integer_t; 5], + pub limitCnt: mach_msg_type_number_t, + pub limit: [integer_t; 1], + pub change: boolean_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_get_state_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub flavor: thread_state_flavor_t, + pub old_stateCnt: mach_msg_type_number_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Request__task_set_state_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub flavor: thread_state_flavor_t, + pub new_stateCnt: mach_msg_type_number_t, + pub new_state: [natural_t; 1296], +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_create_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub child_task: mach_msg_port_descriptor_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_terminate_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C, packed(4))] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_threads_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub act_list: mach_msg_ool_ports_descriptor_t, + pub NDR: NDR_record_t, + pub act_listCnt: mach_msg_type_number_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__mach_ports_register_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C, packed(4))] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__mach_ports_lookup_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub init_port_set: mach_msg_ool_ports_descriptor_t, + pub NDR: NDR_record_t, + pub init_port_setCnt: mach_msg_type_number_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_info_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, + pub task_info_outCnt: mach_msg_type_number_t, + pub task_info_out: [integer_t; 94], +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_set_info_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_suspend_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_resume_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_get_special_port_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub special_port: mach_msg_port_descriptor_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_set_special_port_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__thread_create_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub child_act: mach_msg_port_descriptor_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__thread_create_running_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub child_act: mach_msg_port_descriptor_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_set_exception_ports_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_get_exception_ports_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub old_handlers: [mach_msg_port_descriptor_t; 32], + pub NDR: NDR_record_t, + pub masksCnt: mach_msg_type_number_t, + pub masks: [exception_mask_t; 32], + pub old_behaviors: [exception_behavior_t; 32], + pub old_flavors: [thread_state_flavor_t; 32], +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_swap_exception_ports_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub old_handlers: [mach_msg_port_descriptor_t; 32], + pub NDR: NDR_record_t, + pub masksCnt: mach_msg_type_number_t, + pub masks: [exception_mask_t; 32], + pub old_behaviors: [exception_behavior_t; 32], + pub old_flavors: [thread_state_flavor_t; 32], +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__lock_set_create_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub new_lock_set: mach_msg_port_descriptor_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__lock_set_destroy_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__semaphore_create_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub semaphore: mach_msg_port_descriptor_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_policy_set_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_policy_get_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, + pub policy_infoCnt: mach_msg_type_number_t, + pub policy_info: [integer_t; 16], + pub get_default: boolean_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_sample_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_policy_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_set_emulation_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C, packed(4))] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_get_emulation_vector_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub emulation_vector: mach_msg_ool_descriptor_t, + pub NDR: NDR_record_t, + pub vector_start: c_int, + pub emulation_vectorCnt: mach_msg_type_number_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_set_emulation_vector_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_set_ras_pc_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_assign_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_assign_default_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_get_assignment_t { + pub Head: mach_msg_header_t, + pub msgh_body: mach_msg_body_t, + pub assigned_set: mach_msg_port_descriptor_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_set_policy_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_get_state_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, + pub old_stateCnt: mach_msg_type_number_t, + pub old_state: [natural_t; 1296], +} + +#[repr(C)] +#[allow(dead_code, non_snake_case)] +#[derive(Copy, Clone, Debug)] +pub struct __Reply__task_set_state_t { + pub Head: mach_msg_header_t, + pub NDR: NDR_record_t, + pub RetCode: kern_return_t, } diff --git a/third_party/rust/mach2/src/task_info.rs b/third_party/rust/mach2/src/task_info.rs index 4a3b8ed710e3..9ed37e5116eb 100644 --- a/third_party/rust/mach2/src/task_info.rs +++ b/third_party/rust/mach2/src/task_info.rs @@ -1,40 +1,158 @@ //! This module roughly corresponds to `mach/task_info.h`. -use vm_types::{integer_t, mach_vm_address_t, mach_vm_size_t, natural_t}; +use crate::message::{audit_token_t, security_token_t}; +use crate::policy::policy_t; +use crate::time_value::time_value_t; +use crate::vm_statistics::{vm_extmod_statistics_data_t, vm_purgeable_info}; +use crate::vm_types::{integer_t, mach_vm_address_t, mach_vm_size_t, natural_t, vm_size_t}; +use core::ffi::{c_uchar, c_uint}; +use core::mem; -pub const TASK_INFO_MAX: ::libc::c_uint = 1024; -pub const TASK_BASIC_INFO_32: ::libc::c_uint = 4; -pub const TASK_BASIC2_INFO_32: ::libc::c_uint = 6; -pub const TASK_BASIC_INFO_64: ::libc::c_uint = 5; +pub const TASK_INFO_MAX: c_uint = 1024; +pub const TASK_BASIC_INFO_32: c_uint = 4; +pub const TASK_BASIC2_INFO_32: c_uint = 6; #[cfg(target_arch = "x86_64")] -pub const TASK_BASIC_INFO: ::libc::c_uint = 5; +pub const TASK_BASIC_INFO_64: c_uint = 5; +#[cfg(target_arch = "aarch64")] +pub const TASK_BASIC_INFO_64: c_uint = 18; +#[cfg(target_arch = "x86_64")] +pub const TASK_BASIC_INFO: c_uint = 5; +#[cfg(target_arch = "aarch64")] +pub const TASK_BASIC_INFO: c_uint = 18; #[cfg(target_arch = "x86")] -pub const TASK_BASIC_INFO: ::libc::c_uint = 4; -pub const TASK_EVENTS_INFO: ::libc::c_uint = 2; -pub const TASK_THREAD_TIMES_INFO: ::libc::c_uint = 3; -pub const TASK_ABSOLUTETIME_INFO: ::libc::c_uint = 1; -pub const TASK_KERNELMEMORY_INFO: ::libc::c_uint = 7; -pub const TASK_SECURITY_TOKEN: ::libc::c_uint = 13; -pub const TASK_AUDIT_TOKEN: ::libc::c_uint = 15; -pub const TASK_AFFINITY_TAG_INFO: ::libc::c_uint = 16; -pub const TASK_DYLD_INFO: ::libc::c_uint = 17; -pub const TASK_DYLD_ALL_IMAGE_INFO_32: ::libc::c_uint = 0; -pub const TASK_DYLD_ALL_IMAGE_INFO_64: ::libc::c_uint = 1; -pub const TASK_EXTMOD_INFO: ::libc::c_uint = 19; -pub const MACH_TASK_BASIC_INFO: ::libc::c_uint = 20; -pub const TASK_POWER_INFO: ::libc::c_uint = 21; -pub const TASK_VM_INFO: ::libc::c_uint = 22; -pub const TASK_VM_INFO_PURGEABLE: ::libc::c_uint = 23; -pub const TASK_TRACE_MEMORY_INFO: ::libc::c_uint = 24; -pub const TASK_WAIT_STATE_INFO: ::libc::c_uint = 25; -pub const TASK_POWER_INFO_V2: ::libc::c_uint = 26; -pub const TASK_VM_INFO_PURGEABLE_ACCOUNT: ::libc::c_uint = 27; -pub const TASK_FLAGS_INFO: ::libc::c_uint = 28; -pub const TASK_DEBUG_INFO_INTERNAL: ::libc::c_uint = 29; +pub const TASK_BASIC_INFO: c_uint = 4; +pub const TASK_EVENTS_INFO: c_uint = 2; +pub const TASK_THREAD_TIMES_INFO: c_uint = 3; +pub const TASK_ABSOLUTETIME_INFO: c_uint = 1; +pub const TASK_KERNELMEMORY_INFO: c_uint = 7; +pub const TASK_SECURITY_TOKEN: c_uint = 13; +pub const TASK_AUDIT_TOKEN: c_uint = 15; +pub const TASK_AFFINITY_TAG_INFO: c_uint = 16; +pub const TASK_DYLD_INFO: c_uint = 17; +pub const TASK_DYLD_ALL_IMAGE_INFO_32: c_uint = 0; +pub const TASK_DYLD_ALL_IMAGE_INFO_64: c_uint = 1; +pub const TASK_EXTMOD_INFO: c_uint = 19; +pub const MACH_TASK_BASIC_INFO: c_uint = 20; +pub const TASK_POWER_INFO: c_uint = 21; +pub const TASK_VM_INFO: c_uint = 22; +pub const TASK_VM_INFO_PURGEABLE: c_uint = 23; +pub const TASK_TRACE_MEMORY_INFO: c_uint = 24; +pub const TASK_WAIT_STATE_INFO: c_uint = 25; +pub const TASK_POWER_INFO_V2: c_uint = 26; +pub const TASK_VM_INFO_PURGEABLE_ACCOUNT: c_uint = 27; +pub const TASK_FLAGS_INFO: c_uint = 28; +pub const TASK_DEBUG_INFO_INTERNAL: c_uint = 29; pub type task_flavor_t = natural_t; pub type task_info_t = *mut integer_t; +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_basic_info_32 { + pub suspend_count: integer_t, + pub virtual_size: natural_t, + pub resident_size: natural_t, + pub user_time: time_value_t, + pub system_time: time_value_t, + pub policy: policy_t, +} + +pub const TASK_BASIC_INFO_32_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_basic_info_64 { + pub suspend_count: integer_t, + pub virtual_size: mach_vm_size_t, + pub resident_size: mach_vm_size_t, + pub user_time: time_value_t, + pub system_time: time_value_t, + pub policy: policy_t, +} + +pub const TASK_BASIC_INFO_64_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_basic_info { + pub suspend_count: integer_t, + pub virtual_size: vm_size_t, + pub resident_size: vm_size_t, + pub user_time: time_value_t, + pub system_time: time_value_t, + pub policy: policy_t, +} + +pub const TASK_BASIC_INFO_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_events_info { + pub faults: integer_t, + pub pageins: integer_t, + pub cow_faults: integer_t, + pub messages_sent: integer_t, + pub messages_received: integer_t, + pub syscalls_mach: integer_t, + pub syscalls_unix: integer_t, + pub csw: integer_t, +} + +pub const TASK_EVENTS_INFO_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_thread_times_info { + pub user_time: time_value_t, + pub system_time: time_value_t, +} + +pub const TASK_THREAD_TIMES_INFO_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_absolutetime_info { + pub total_user: u64, + pub total_system: u64, + pub threads_user: u64, + pub threads_system: u64, +} + +pub const TASK_ABSOLUTETIME_INFO_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_kernelmemory_info { + pub total_palloc: u64, + pub total_pfree: u64, + pub total_salloc: u64, + pub total_sfree: u64, +} + +pub const TASK_KERNELMEMORY_INFO_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +pub const TASK_SECURITY_TOKEN_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +pub const TASK_AUDIT_TOKEN_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_affinity_tag_info { + pub set_count: integer_t, + pub min: integer_t, + pub max: integer_t, + pub task_count: integer_t, +} + #[repr(C, packed(4))] #[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] pub struct task_dyld_info { @@ -42,3 +160,161 @@ pub struct task_dyld_info { pub all_image_info_size: mach_vm_size_t, pub all_image_info_format: integer_t, } + +pub const TASK_DYLD_INFO_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_extmod_info { + pub task_uuid: [c_uchar; 16usize], + pub extmod_statistics: vm_extmod_statistics_data_t, +} + +pub const TASK_EXTMOD_INFO_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_power_info { + pub total_user: u64, + pub total_system: u64, + pub task_interrupt_wakeups: u64, + pub task_platform_idle_wakeups: u64, + pub task_timer_wakeups_bin_1: u64, + pub task_timer_wakeups_bin_2: u64, +} + +pub const TASK_POWER_INFO_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_vm_info { + pub virtual_size: mach_vm_size_t, + pub region_count: integer_t, + pub page_size: integer_t, + pub resident_size: mach_vm_size_t, + pub resident_size_peak: mach_vm_size_t, + pub device: mach_vm_size_t, + pub device_peak: mach_vm_size_t, + pub internal: mach_vm_size_t, + pub internal_peak: mach_vm_size_t, + pub external: mach_vm_size_t, + pub external_peak: mach_vm_size_t, + pub reusable: mach_vm_size_t, + pub reusable_peak: mach_vm_size_t, + pub purgeable_volatile_pmap: mach_vm_size_t, + pub purgeable_volatile_resident: mach_vm_size_t, + pub purgeable_volatile_virtual: mach_vm_size_t, + pub compressed: mach_vm_size_t, + pub compressed_peak: mach_vm_size_t, + pub compressed_lifetime: mach_vm_size_t, + pub phys_footprint: mach_vm_size_t, + pub min_address: mach_vm_address_t, + pub max_address: mach_vm_address_t, + pub ledger_phys_footprint_peak: i64, + pub ledger_purgeable_nonvolatile: i64, + pub ledger_purgeable_novolatile_compressed: i64, + pub ledger_purgeable_volatile: i64, + pub ledger_purgeable_volatile_compressed: i64, + pub ledger_tag_network_nonvolatile: i64, + pub ledger_tag_network_nonvolatile_compressed: i64, + pub ledger_tag_network_volatile: i64, + pub ledger_tag_network_volatile_compressed: i64, + pub ledger_tag_media_footprint: i64, + pub ledger_tag_media_footprint_compressed: i64, + pub ledger_tag_media_nofootprint: i64, + pub ledger_tag_media_nofootprint_compressed: i64, + pub ledger_tag_graphics_footprint: i64, + pub ledger_tag_graphics_footprint_compressed: i64, + pub ledger_tag_graphics_nofootprint: i64, + pub ledger_tag_graphics_nofootprint_compressed: i64, + pub ledger_tag_neural_footprint: i64, + pub ledger_tag_neural_footprint_compressed: i64, + pub ledger_tag_neural_nofootprint: i64, + pub ledger_tag_neural_nofootprint_compressed: i64, + pub limit_bytes_remaining: u64, + pub decompressions: integer_t, + pub ledger_swapins: i64, + pub ledger_tag_neural_nofootprint_total: i64, + pub ledger_tag_neural_nofootprint_peak: i64, +} + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct mach_task_basic_info { + pub virtual_size: mach_vm_size_t, + pub resident_size: mach_vm_size_t, + pub resident_size_max: mach_vm_size_t, + pub user_time: time_value_t, + pub system_time: time_value_t, + pub policy: policy_t, + pub suspend_count: integer_t, +} + +pub const MACH_TASK_BASIC_INFO_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_trace_memory_info { + pub user_memory_address: u64, + pub buffer_size: u64, + pub mailbox_array_size: u64, +} + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_wait_state_info { + pub total_wait_state_time: u64, + pub total_wait_sfi_state_time: u64, + pub _reserved: [u32; 4], +} + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct gpu_energy_data { + pub task_gpu_utilisation: u64, + pub task_gpu_stat_reserved0: u64, + pub task_gpu_stat_reserved1: u64, + pub task_gpu_stat_reserved2: u64, +} + +#[cfg(any(target_arch = "arm", target_arch = "aarch64"))] +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_power_info_v2 { + pub cpu_energy: task_power_info, + pub gpu_energy: gpu_energy_data, + pub task_energy: u64, + pub task_ptime: u64, + pub task_pset_switches: u64, +} + +#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))] +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_power_info_v2 { + pub cpu_energy: task_power_info, + pub gpu_energy: gpu_energy_data, + pub task_ptime: u64, + pub task_pset_switches: u64, +} + +pub const TASK_POWER_INFO_V2_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +pub type task_purgable_info_t = vm_purgeable_info; + +pub type task_exc_guard_behavior_t = u32; +pub type task_corpse_forking_behavior_t = u32; + +#[repr(C, packed(4))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_flags_info { + pub flags: u32, +} + +pub const TASK_FLAGS_INFO_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; diff --git a/third_party/rust/mach2/src/task_inspect.rs b/third_party/rust/mach2/src/task_inspect.rs new file mode 100644 index 000000000000..d44e19e3b4f9 --- /dev/null +++ b/third_party/rust/mach2/src/task_inspect.rs @@ -0,0 +1,21 @@ +//! This module corresponds to `mach/task_inspect.h`. + +use crate::vm_types::{integer_t, natural_t}; +use core::mem; + +pub type task_inspect_flavor_t = natural_t; +pub const TASK_INSPECT_BASIC_COUNTS: task_inspect_flavor_t = 1; +pub const TASK_INSPECT_BASIC_COUNTS_COUNT: u32 = + (mem::size_of::() / mem::size_of::()) as u32; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct task_inspect_basic_counts { + pub instructions: u64, + pub cycles: u64, +} + +pub type task_inspect_basic_counts_data_t = task_inspect_basic_counts; +pub type task_inspect_basic_counts_t = *mut task_inspect_basic_counts; + +pub type task_inspect_info_t = *mut integer_t; diff --git a/third_party/rust/mach2/src/task_special_ports.rs b/third_party/rust/mach2/src/task_special_ports.rs new file mode 100644 index 000000000000..ce0904a28d6f --- /dev/null +++ b/third_party/rust/mach2/src/task_special_ports.rs @@ -0,0 +1,80 @@ +//! This module corresponds to `mach/task_special_ports.h`. + +use crate::kern_return::kern_return_t; +use crate::mach_types::task_t; +use crate::port::mach_port_t; +use core::ffi::c_int; + +pub type task_special_port_t = c_int; + +pub const TASK_KERNEL_PORT: task_special_port_t = 1; +pub const TASK_HOST_PORT: task_special_port_t = 2; +pub const TASK_NAME_PORT: task_special_port_t = 3; +pub const TASK_BOOTSTRAP_PORT: task_special_port_t = 4; +pub const TASK_INSPECT_PORT: task_special_port_t = 5; +pub const TASK_READ_PORT: task_special_port_t = 6; +pub const TASK_ACCESS_PORT: task_special_port_t = 9; +pub const TASK_DEBUG_CONTROL_PORT: task_special_port_t = 10; +pub const TASK_RESOURCE_NOTIFY_PORT: task_special_port_t = 11; + +pub const TASK_MAX_SPECIAL_PORT: task_special_port_t = TASK_RESOURCE_NOTIFY_PORT; + +#[inline] +#[allow(clippy::missing_safety_doc)] +pub unsafe fn task_get_kernel_port(task: task_t, port: *mut mach_port_t) -> kern_return_t { + unsafe { crate::task::task_get_special_port(task, TASK_KERNEL_PORT, port) } +} + +#[inline] +#[allow(clippy::missing_safety_doc)] +pub unsafe fn task_set_kernel_port(task: task_t, port: mach_port_t) -> kern_return_t { + unsafe { crate::task::task_set_special_port(task, TASK_KERNEL_PORT, port) } +} + +#[inline] +#[allow(clippy::missing_safety_doc)] +pub unsafe fn task_get_host_port(task: task_t, port: *mut mach_port_t) -> kern_return_t { + unsafe { crate::task::task_get_special_port(task, TASK_HOST_PORT, port) } +} + +#[inline] +#[allow(clippy::missing_safety_doc)] +pub unsafe fn task_set_host_port(task: task_t, port: mach_port_t) -> kern_return_t { + unsafe { crate::task::task_set_special_port(task, TASK_HOST_PORT, port) } +} + +#[inline] +#[allow(clippy::missing_safety_doc)] +pub unsafe fn task_get_bootstrap_port(task: task_t, port: *mut mach_port_t) -> kern_return_t { + unsafe { crate::task::task_get_special_port(task, TASK_BOOTSTRAP_PORT, port) } +} + +#[inline] +#[allow(clippy::missing_safety_doc)] +pub unsafe fn task_set_bootstrap_port(task: task_t, port: mach_port_t) -> kern_return_t { + unsafe { crate::task::task_set_special_port(task, TASK_BOOTSTRAP_PORT, port) } +} + +#[inline] +#[allow(clippy::missing_safety_doc)] +pub unsafe fn task_get_debug_control_port(task: task_t, port: *mut mach_port_t) -> kern_return_t { + unsafe { crate::task::task_get_special_port(task, TASK_DEBUG_CONTROL_PORT, port) } +} + +#[inline] +#[allow(clippy::missing_safety_doc)] +pub unsafe fn task_set_task_debug_control_port(task: task_t, port: mach_port_t) -> kern_return_t { + unsafe { crate::task::task_set_special_port(task, TASK_DEBUG_CONTROL_PORT, port) } +} + +#[inline] +#[allow(clippy::missing_safety_doc)] +pub unsafe fn task_get_task_access_port(task: task_t, port: *mut mach_port_t) -> kern_return_t { + unsafe { crate::task::task_get_special_port(task, TASK_ACCESS_PORT, port) } +} + +#[inline] +#[allow(clippy::missing_safety_doc)] +pub unsafe fn task_set_task_access_port(task: task_t, port: mach_port_t) -> kern_return_t { + unsafe { crate::task::task_set_special_port(task, TASK_ACCESS_PORT, port) } +} diff --git a/third_party/rust/mach2/src/thread_act.rs b/third_party/rust/mach2/src/thread_act.rs index f2f9809a2b7e..c7378a41ff0a 100644 --- a/third_party/rust/mach2/src/thread_act.rs +++ b/third_party/rust/mach2/src/thread_act.rs @@ -1,23 +1,36 @@ //! This module corresponds to `mach/thread_act.defs`. -use kern_return::kern_return_t; -use mach_types::thread_act_t; -use message::mach_msg_type_number_t; -use thread_status::{thread_state_flavor_t, thread_state_t}; +use crate::exception_types::{exception_behavior_t, exception_mask_t}; +use crate::kern_return::kern_return_t; +use crate::mach_types::{thread_act_t, thread_port_t}; +use crate::message::mach_msg_type_number_t; +use crate::port::mach_port_t; +use crate::thread_status::{thread_state_flavor_t, thread_state_t}; -extern "C" { +unsafe extern "C" { pub fn thread_get_state( target_act: thread_act_t, flavor: thread_state_flavor_t, + old_state: thread_state_t, + old_state_count: *mut mach_msg_type_number_t, + ) -> kern_return_t; + + pub fn thread_set_state( + target_act: thread_port_t, + flavor: thread_state_flavor_t, new_state: thread_state_t, - new_state_count: *mut mach_msg_type_number_t, + new_stateCnt: mach_msg_type_number_t, + ) -> kern_return_t; + + pub fn thread_set_exception_ports( + thread: thread_port_t, + exception_mask: exception_mask_t, + new_port: mach_port_t, + behavior: exception_behavior_t, + new_flavor: thread_state_flavor_t, ) -> kern_return_t; -} -extern "C" { pub fn thread_suspend(target_act: thread_act_t) -> kern_return_t; -} -extern "C" { pub fn thread_resume(target_act: thread_act_t) -> kern_return_t; } diff --git a/third_party/rust/mach2/src/thread_policy.rs b/third_party/rust/mach2/src/thread_policy.rs index aa17e6ea3141..8adebd020a0e 100644 --- a/third_party/rust/mach2/src/thread_policy.rs +++ b/third_party/rust/mach2/src/thread_policy.rs @@ -1,11 +1,12 @@ //! This module corresponds to `mach/thread_policy.h`. -use boolean::boolean_t; -use kern_return::kern_return_t; -use libc::thread_policy_t; -use mach_types::thread_t; -use message::mach_msg_type_number_t; -use vm_types::{integer_t, natural_t}; +use crate::boolean::boolean_t; +use crate::kern_return::kern_return_t; +use crate::mach_types::thread_t; +use crate::message::mach_msg_type_number_t; +use crate::vm_types::{integer_t, natural_t}; + +pub type thread_policy_t = *mut integer_t; pub type thread_policy_flavor_t = natural_t; @@ -101,16 +102,14 @@ pub const THREAD_LATENCY_QOS_POLICY_COUNT: mach_msg_type_number_t = pub const THREAD_THROUGHPUT_QOS_POLICY_COUNT: mach_msg_type_number_t = (core::mem::size_of::() / core::mem::size_of::()) as _; -extern "C" { +unsafe extern "C" { pub fn thread_policy_set( thread: thread_t, flavor: thread_policy_flavor_t, policy_info: thread_policy_t, count: mach_msg_type_number_t, ) -> kern_return_t; -} -extern "C" { pub fn thread_policy_get( thread: thread_t, flavor: thread_policy_flavor_t, diff --git a/third_party/rust/mach2/src/thread_special_ports.rs b/third_party/rust/mach2/src/thread_special_ports.rs new file mode 100644 index 000000000000..53357a461e47 --- /dev/null +++ b/third_party/rust/mach2/src/thread_special_ports.rs @@ -0,0 +1,7 @@ +//! This module corresponds to `mach/thread_special_ports.h`. +use core::ffi::c_int; + +pub const THREAD_KERNEL_PORT: c_int = 1; +pub const THREAD_INSPECT_PORT: c_int = 2; +pub const THREAD_READ_PORT: c_int = 3; +pub const THREAD_MAX_SPECIAL_PORT: c_int = THREAD_READ_PORT; diff --git a/third_party/rust/mach2/src/thread_state.rs b/third_party/rust/mach2/src/thread_state.rs new file mode 100644 index 000000000000..1d304229a457 --- /dev/null +++ b/third_party/rust/mach2/src/thread_state.rs @@ -0,0 +1,13 @@ +//! This module corresponds to `mach/thread_state.h`. + +use crate::kern_return::kern_return_t; +use crate::mach_types::thread_t; + +unsafe extern "C" { + pub fn thread_get_register_pointer_values( + thread: thread_t, + sp: *mut usize, + length: *mut usize, + values: *mut usize, + ) -> kern_return_t; +} diff --git a/third_party/rust/mach2/src/thread_status.rs b/third_party/rust/mach2/src/thread_status.rs index 951256622cd4..d50a9a020ac5 100644 --- a/third_party/rust/mach2/src/thread_status.rs +++ b/third_party/rust/mach2/src/thread_status.rs @@ -1,23 +1,54 @@ //! This module corresponds to `mach/thread_status.h`. -use vm_types::natural_t; +use crate::vm_types::natural_t; +use core::ffi::c_int; pub type thread_state_t = *mut natural_t; -pub type thread_state_flavor_t = ::libc::c_int; +pub type thread_state_flavor_t = c_int; -pub static x86_THREAD_STATE32: thread_state_flavor_t = 1; -pub static x86_FLOAT_STATE32: thread_state_flavor_t = 2; -pub static x86_EXCEPTION_STATE32: thread_state_flavor_t = 3; -pub static x86_THREAD_STATE64: thread_state_flavor_t = 4; -pub static x86_FLOAT_STATE64: thread_state_flavor_t = 5; -pub static x86_EXCEPTION_STATE64: thread_state_flavor_t = 6; -pub static x86_THREAD_STATE: thread_state_flavor_t = 7; -pub static x86_FLOAT_STATE: thread_state_flavor_t = 8; -pub static x86_EXCEPTION_STATE: thread_state_flavor_t = 9; -pub static x86_DEBUG_STATE32: thread_state_flavor_t = 10; -pub static x86_DEBUG_STATE64: thread_state_flavor_t = 11; -pub static x86_DEBUG_STATE: thread_state_flavor_t = 12; -pub static THREAD_STATE_NONE: thread_state_flavor_t = 13; -pub static x86_AVX_STATE32: thread_state_flavor_t = 16; -pub static x86_AVX_STATE64: thread_state_flavor_t = 17; -pub static x86_AVX_STATE: thread_state_flavor_t = 18; +#[cfg(target_arch = "aarch64")] +mod aarch64 { + use super::thread_state_flavor_t; + + pub static ARM_THREAD_STATE: thread_state_flavor_t = 1; + pub static ARM_UNIFIED_THREAD_STATE: thread_state_flavor_t = ARM_THREAD_STATE; + pub static ARM_VFP_STATE: thread_state_flavor_t = 2; + pub static ARM_EXCEPTION_STATE: thread_state_flavor_t = 3; + pub static ARM_DEBUG_STATE: thread_state_flavor_t = 4; + pub static THREAD_STATE_NONE: thread_state_flavor_t = 5; + pub static ARM_THREAD_STATE64: thread_state_flavor_t = 6; + pub static ARM_EXCEPTION_STATE64: thread_state_flavor_t = 7; + pub static ARM_DEBUG_STATE32: thread_state_flavor_t = 14; + pub static ARM_DEBUG_STATE64: thread_state_flavor_t = 15; + pub static ARM_NEON_STATE: thread_state_flavor_t = 16; + pub static ARM_NEON_STATE64: thread_state_flavor_t = 17; + pub static ARM_CPMU_STATE64: thread_state_flavor_t = 18; +} + +#[cfg(target_arch = "aarch64")] +pub use self::aarch64::*; + +#[cfg(target_arch = "x86_64")] +mod x86_64 { + use super::thread_state_flavor_t; + + pub static x86_THREAD_STATE32: thread_state_flavor_t = 1; + pub static x86_FLOAT_STATE32: thread_state_flavor_t = 2; + pub static x86_EXCEPTION_STATE32: thread_state_flavor_t = 3; + pub static x86_THREAD_STATE64: thread_state_flavor_t = 4; + pub static x86_FLOAT_STATE64: thread_state_flavor_t = 5; + pub static x86_EXCEPTION_STATE64: thread_state_flavor_t = 6; + pub static x86_THREAD_STATE: thread_state_flavor_t = 7; + pub static x86_FLOAT_STATE: thread_state_flavor_t = 8; + pub static x86_EXCEPTION_STATE: thread_state_flavor_t = 9; + pub static x86_DEBUG_STATE32: thread_state_flavor_t = 10; + pub static x86_DEBUG_STATE64: thread_state_flavor_t = 11; + pub static x86_DEBUG_STATE: thread_state_flavor_t = 12; + pub static THREAD_STATE_NONE: thread_state_flavor_t = 13; + pub static x86_AVX_STATE32: thread_state_flavor_t = 16; + pub static x86_AVX_STATE64: thread_state_flavor_t = 17; + pub static x86_AVX_STATE: thread_state_flavor_t = 18; +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +pub use self::x86_64::*; diff --git a/third_party/rust/mach2/src/thread_switch.rs b/third_party/rust/mach2/src/thread_switch.rs new file mode 100644 index 000000000000..a0b91d278d74 --- /dev/null +++ b/third_party/rust/mach2/src/thread_switch.rs @@ -0,0 +1,6 @@ +//! This module corresponds to `mach/thread_switch.h`. +use core::ffi::c_int; + +pub const SWITCH_OPTION_NONE: c_int = 0; +pub const SWITCH_OPTION_DEPRESS: c_int = 1; +pub const SWITCH_OPTION_WAIT: c_int = 2; diff --git a/third_party/rust/mach2/src/time_value.rs b/third_party/rust/mach2/src/time_value.rs new file mode 100644 index 000000000000..480cb0ba6707 --- /dev/null +++ b/third_party/rust/mach2/src/time_value.rs @@ -0,0 +1,11 @@ +use crate::vm_types::integer_t; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct time_value { + pub seconds: integer_t, + pub microseconds: integer_t, +} +pub type time_value_t = time_value; + +pub const TIME_MICROS_MAX: integer_t = 1000000; diff --git a/third_party/rust/mach2/src/traps.rs b/third_party/rust/mach2/src/traps.rs index 1d3bb93ea355..f2f360aa158e 100644 --- a/third_party/rust/mach2/src/traps.rs +++ b/third_party/rust/mach2/src/traps.rs @@ -1,30 +1,31 @@ //! This module corresponds to `mach/mach_traps.h`. -use kern_return::kern_return_t; -use port::{mach_port_name_t, mach_port_t}; +use crate::kern_return::kern_return_t; +use crate::port::{mach_port_name_t, mach_port_t}; +use core::ffi::c_int; -extern "C" { +unsafe extern "C" { static mach_task_self_: mach_port_t; pub fn task_for_pid( target_tport: mach_port_name_t, - pid: ::libc::c_int, + pid: c_int, tn: *mut mach_port_name_t, ) -> kern_return_t; } #[allow(clippy::missing_safety_doc)] // FIXME pub unsafe fn mach_task_self() -> mach_port_t { - mach_task_self_ + unsafe { mach_task_self_ } } #[allow(clippy::missing_safety_doc)] // FIXME pub unsafe fn current_task() -> mach_port_t { - mach_task_self() + unsafe { mach_task_self() } } #[cfg(test)] mod tests { - use port::*; - use traps::*; + use crate::port::*; + use crate::traps::*; #[test] fn mach_task_self_sanity() { diff --git a/third_party/rust/mach2/src/vm.rs b/third_party/rust/mach2/src/vm.rs index d0bf6f23abef..c94defee7e7d 100644 --- a/third_party/rust/mach2/src/vm.rs +++ b/third_party/rust/mach2/src/vm.rs @@ -1,33 +1,34 @@ //! This module roughly corresponds to `mach/mach_vm.defs`. -use boolean::boolean_t; -use kern_return::kern_return_t; -use mach_types::{mem_entry_name_port_t, vm_task_entry_t}; -use memory_object_types::{memory_object_offset_t, memory_object_size_t}; -use message::mach_msg_type_number_t; -use port::mach_port_t; -use vm_attributes::{vm_machine_attribute_t, vm_machine_attribute_val_t}; -use vm_behavior::vm_behavior_t; -use vm_inherit::vm_inherit_t; -use vm_prot::vm_prot_t; -use vm_purgable::vm_purgable_t; -use vm_region::mach_vm_read_entry_t; -use vm_region::{ +use crate::boolean::boolean_t; +use crate::kern_return::kern_return_t; +use crate::mach_types::{mem_entry_name_port_t, vm_task_entry_t}; +use crate::memory_object_types::{memory_object_offset_t, memory_object_size_t}; +use crate::message::mach_msg_type_number_t; +use crate::port::mach_port_t; +use crate::vm_attributes::{vm_machine_attribute_t, vm_machine_attribute_val_t}; +use crate::vm_behavior::vm_behavior_t; +use crate::vm_inherit::vm_inherit_t; +use crate::vm_prot::vm_prot_t; +use crate::vm_purgable::vm_purgable_t; +use crate::vm_region::mach_vm_read_entry_t; +use crate::vm_region::{ vm_page_info_flavor_t, vm_page_info_t, vm_region_flavor_t, vm_region_info_t, vm_region_recurse_info_t, }; -use vm_sync::vm_sync_t; -use vm_types::{ +use crate::vm_sync::vm_sync_t; +use crate::vm_types::{ integer_t, mach_vm_address_t, mach_vm_offset_t, mach_vm_size_t, natural_t, vm_map_t, vm_offset_t, vm_size_t, }; +use core::ffi::c_int; -extern "C" { +unsafe extern "C" { pub fn mach_vm_allocate( target: vm_task_entry_t, address: *mut mach_vm_address_t, size: mach_vm_size_t, - flags: ::libc::c_int, + flags: c_int, ) -> kern_return_t; pub fn mach_vm_deallocate( @@ -107,7 +108,7 @@ extern "C" { inout: *mut mach_vm_address_t, size: mach_vm_size_t, mask: mach_vm_offset_t, - flags: ::libc::c_int, + flags: c_int, object: mem_entry_name_port_t, offset: memory_object_offset_t, copy: boolean_t, @@ -129,7 +130,7 @@ extern "C" { target_address: *mut mach_vm_address_t, size: mach_vm_size_t, mask: mach_vm_offset_t, - flags: ::libc::c_int, + flags: c_int, src_task: vm_task_entry_t, src_address: mach_vm_address_t, copy: boolean_t, @@ -186,7 +187,7 @@ extern "C" { target_task: vm_task_entry_t, address: mach_vm_address_t, control: vm_purgable_t, - state: *mut ::libc::c_int, + state: *mut c_int, ) -> kern_return_t; pub fn mach_vm_page_info( @@ -201,9 +202,9 @@ extern "C" { #[cfg(test)] mod tests { use super::*; - use kern_return::KERN_SUCCESS; - use traps::mach_task_self; - use vm_statistics::VM_FLAGS_ANYWHERE; + use crate::kern_return::KERN_SUCCESS; + use crate::traps::mach_task_self; + use crate::vm_statistics::VM_FLAGS_ANYWHERE; #[test] fn mach_vm_allocate_sanity() { @@ -222,9 +223,9 @@ mod tests { #[test] fn mach_vm_region_sanity() { - use mem; - use vm_prot::{VM_PROT_EXECUTE, VM_PROT_READ}; - use vm_region::{vm_region_basic_info_64, VM_REGION_BASIC_INFO_64}; + use crate::vm_prot::{VM_PROT_EXECUTE, VM_PROT_READ}; + use crate::vm_region::{VM_REGION_BASIC_INFO_64, vm_region_basic_info_64}; + use core::mem; unsafe { let mut size = 0x10; let mut object_name = 0; diff --git a/third_party/rust/mach2/src/vm_attributes.rs b/third_party/rust/mach2/src/vm_attributes.rs index ba3b0d3c70de..641fea09e840 100644 --- a/third_party/rust/mach2/src/vm_attributes.rs +++ b/third_party/rust/mach2/src/vm_attributes.rs @@ -1,12 +1,13 @@ //! This module corresponds to `mach/vm_attributes.h`. +use core::ffi::{c_int, c_uint}; -pub type vm_machine_attribute_t = ::libc::c_uint; +pub type vm_machine_attribute_t = c_uint; pub const MATTR_CACHE: vm_machine_attribute_t = 1; pub const MATTR_MIGRATE: vm_machine_attribute_t = 1 << 1; pub const MATTR_REPLICATE: vm_machine_attribute_t = 1 << 2; -pub type vm_machine_attribute_val_t = ::libc::c_int; +pub type vm_machine_attribute_val_t = c_int; pub const MATTR_VAL_OFF: vm_machine_attribute_val_t = 0; pub const MATTR_VAL_ON: vm_machine_attribute_val_t = 1; diff --git a/third_party/rust/mach2/src/vm_behavior.rs b/third_party/rust/mach2/src/vm_behavior.rs index 8ab692e550e9..52f616e87975 100644 --- a/third_party/rust/mach2/src/vm_behavior.rs +++ b/third_party/rust/mach2/src/vm_behavior.rs @@ -1,6 +1,7 @@ //! This module corresponds to `mach/vm_behavior.h`. +use core::ffi::c_int; -pub type vm_behavior_t = ::libc::c_int; +pub type vm_behavior_t = c_int; pub const VM_BEHAVIOR_DEFAULT: vm_behavior_t = 0; pub const VM_BEHAVIOR_RANDOM: vm_behavior_t = 1; @@ -13,3 +14,6 @@ pub const VM_BEHAVIOR_ZERO_WIRED_PAGES: vm_behavior_t = 7; pub const VM_BEHAVIOR_REUSABLE: vm_behavior_t = 8; pub const VM_BEHAVIOR_REUSE: vm_behavior_t = 9; pub const VM_BEHAVIOR_CAN_REUSE: vm_behavior_t = 10; +pub const VM_BEHAVIOR_PAGEOUT: vm_behavior_t = 11; +pub const VM_BEHAVIOR_ZERO: vm_behavior_t = 12; +pub const VM_BEHAVIOR_LAST_VALID: vm_behavior_t = VM_BEHAVIOR_ZERO; diff --git a/third_party/rust/mach2/src/vm_inherit.rs b/third_party/rust/mach2/src/vm_inherit.rs index 4f4c9e5ef734..1d3bc51f3a72 100644 --- a/third_party/rust/mach2/src/vm_inherit.rs +++ b/third_party/rust/mach2/src/vm_inherit.rs @@ -1,6 +1,7 @@ //! This module corresponds to `mach/vm_inherit.h`. +use core::ffi::c_uint; -pub type vm_inherit_t = ::libc::c_uint; +pub type vm_inherit_t = c_uint; pub const VM_INHERIT_SHARE: vm_inherit_t = 0; pub const VM_INHERIT_COPY: vm_inherit_t = 1; diff --git a/third_party/rust/mach2/src/vm_page_size.rs b/third_party/rust/mach2/src/vm_page_size.rs index f1ab37fcb427..1e309cd66320 100644 --- a/third_party/rust/mach2/src/vm_page_size.rs +++ b/third_party/rust/mach2/src/vm_page_size.rs @@ -1,27 +1,40 @@ //! This module roughly corresponds to `mach/vm_page_size.h` +use crate::vm_types::{mach_vm_offset_t, mach_vm_size_t, vm_size_t}; +use core::ffi::c_int; -use vm_types::{mach_vm_offset_t, mach_vm_size_t, vm_size_t}; - -extern "C" { +unsafe extern "C" { pub static vm_page_size: vm_size_t; pub static vm_page_mask: vm_size_t; - pub static vm_page_shift: ::libc::c_int; + pub static vm_page_shift: c_int; + pub static vm_kernel_page_size: vm_size_t; + pub static vm_kernel_page_mask: vm_size_t; + pub static vm_kernel_page_shift: c_int; +} + +#[allow(clippy::missing_safety_doc)] // FIXME +pub unsafe fn vm_trunc_page(x: vm_size_t) -> vm_size_t { + unsafe { x & !(vm_page_size - 1) } +} + +#[allow(clippy::missing_safety_doc)] // FIXME +pub unsafe fn vm_round_page(x: vm_size_t) -> vm_size_t { + unsafe { vm_trunc_page(x + (vm_page_size - 1)) } } #[allow(clippy::missing_safety_doc)] // FIXME pub unsafe fn mach_vm_trunc_page(x: mach_vm_offset_t) -> mach_vm_offset_t { - x & !(vm_page_mask as mach_vm_size_t) + unsafe { x & !(vm_page_mask as mach_vm_size_t) } } #[allow(clippy::missing_safety_doc)] // FIXME pub unsafe fn mach_vm_round_page(x: mach_vm_offset_t) -> mach_vm_offset_t { - (x + vm_page_mask as mach_vm_size_t) & !(vm_page_mask as mach_vm_size_t) + unsafe { (x + vm_page_mask as mach_vm_size_t) & !(vm_page_mask as mach_vm_size_t) } } #[cfg(test)] mod tests { - use vm_page_size::*; - use vm_types::mach_vm_size_t; + use crate::vm_page_size::*; + use crate::vm_types::mach_vm_size_t; #[test] fn page_size() { @@ -38,3 +51,13 @@ mod tests { } } } + +#[allow(clippy::missing_safety_doc)] // FIXME +pub unsafe fn trunc_page_kernel(x: vm_size_t) -> vm_size_t { + unsafe { x & !vm_kernel_page_mask } +} + +#[allow(clippy::missing_safety_doc)] // FIXME +pub unsafe fn round_page_kernel(x: vm_size_t) -> vm_size_t { + unsafe { trunc_page_kernel(x + vm_kernel_page_mask) } +} diff --git a/third_party/rust/mach2/src/vm_prot.rs b/third_party/rust/mach2/src/vm_prot.rs index 0397d25a1d21..f760faa6b8e1 100644 --- a/third_party/rust/mach2/src/vm_prot.rs +++ b/third_party/rust/mach2/src/vm_prot.rs @@ -1,13 +1,25 @@ //! This module corresponds to `mach/vm_prot.h`. +use core::ffi::c_int; -pub type vm_prot_t = ::libc::c_int; +pub type vm_prot_t = c_int; pub const VM_PROT_NONE: vm_prot_t = 0; pub const VM_PROT_READ: vm_prot_t = 1; pub const VM_PROT_WRITE: vm_prot_t = 1 << 1; pub const VM_PROT_EXECUTE: vm_prot_t = 1 << 2; -pub const VM_PROT_NO_CHANGE: vm_prot_t = 1 << 3; -pub const VM_PROT_COPY: vm_prot_t = 1 << 4; -pub const VM_PROT_WANTS_COPY: vm_prot_t = 1 << 4; +pub const VM_PROT_NO_CHANGE_LEGACY: vm_prot_t = 0x08; +pub const VM_PROT_NO_CHANGE: vm_prot_t = 0x0100_0000; +pub const VM_PROT_COPY: vm_prot_t = 0x10; +pub const VM_PROT_WANTS_COPY: vm_prot_t = VM_PROT_COPY; pub const VM_PROT_DEFAULT: vm_prot_t = VM_PROT_READ | VM_PROT_WRITE; pub const VM_PROT_ALL: vm_prot_t = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE; +pub const VM_PROT_IS_MASK: vm_prot_t = 0x40; +pub const VM_PROT_STRIP_READ: vm_prot_t = 0x80; +pub const VM_PROT_EXECUTE_ONLY: vm_prot_t = VM_PROT_EXECUTE | VM_PROT_STRIP_READ; +pub const VM_PROT_TPRO: vm_prot_t = 0x200; +#[cfg(target_arch = "x86_64")] +pub const VM_PROT_UEXEC: vm_prot_t = 0x8; +#[cfg(target_arch = "x86_64")] +pub const VM_PROT_ALLEXEC: vm_prot_t = VM_PROT_EXECUTE | VM_PROT_UEXEC; +#[cfg(not(target_arch = "x86_64"))] +pub const VM_PROT_ALLEXEC: vm_prot_t = VM_PROT_EXECUTE; diff --git a/third_party/rust/mach2/src/vm_purgable.rs b/third_party/rust/mach2/src/vm_purgable.rs index 79fc297cb042..bb319bf9a881 100644 --- a/third_party/rust/mach2/src/vm_purgable.rs +++ b/third_party/rust/mach2/src/vm_purgable.rs @@ -1,42 +1,61 @@ //! This module corresponds to `mach/vm_purgable.h`. +use core::ffi::c_int; -pub type vm_purgable_t = ::libc::c_int; +pub type vm_purgable_t = c_int; pub const VM_PURGABLE_SET_STATE: vm_purgable_t = 0; pub const VM_PURGABLE_GET_STATE: vm_purgable_t = 1; +pub const VM_PURGABLE_PURGE_ALL: vm_purgable_t = 2; +pub const VM_PURGABLE_SET_STATE_FROM_KERNEL: vm_purgable_t = 3; -pub const VM_VOLATILE_GROUP_SHIFT: ::libc::c_int = 8; -pub const VM_VOLATILE_GROUP_MASK: ::libc::c_int = 7 << VM_VOLATILE_GROUP_SHIFT; -pub const VM_VOLATILE_GROUP_DEFAULT: ::libc::c_int = VM_VOLATILE_GROUP_0; +pub const VM_PURGABLE_NO_AGING_SHIFT: c_int = 16; +pub const VM_PURGABLE_NO_AGING_MASK: c_int = 1 << VM_PURGABLE_NO_AGING_SHIFT; +pub const VM_PURGABLE_NO_AGING: c_int = 1 << VM_PURGABLE_NO_AGING_SHIFT; -pub const VM_VOLATILE_GROUP_0: ::libc::c_int = 0 << VM_VOLATILE_GROUP_SHIFT; -pub const VM_VOLATILE_GROUP_1: ::libc::c_int = 1 << VM_VOLATILE_GROUP_SHIFT; -pub const VM_VOLATILE_GROUP_2: ::libc::c_int = 2 << VM_VOLATILE_GROUP_SHIFT; -pub const VM_VOLATILE_GROUP_3: ::libc::c_int = 3 << VM_VOLATILE_GROUP_SHIFT; -pub const VM_VOLATILE_GROUP_4: ::libc::c_int = 4 << VM_VOLATILE_GROUP_SHIFT; -pub const VM_VOLATILE_GROUP_5: ::libc::c_int = 5 << VM_VOLATILE_GROUP_SHIFT; -pub const VM_VOLATILE_GROUP_6: ::libc::c_int = 6 << VM_VOLATILE_GROUP_SHIFT; -pub const VM_VOLATILE_GROUP_7: ::libc::c_int = 7 << VM_VOLATILE_GROUP_SHIFT; +pub const VM_PURGABLE_DEBUG_SHIFT: c_int = 12; +pub const VM_PURGABLE_DEBUG_MASK: c_int = 0x3 << VM_PURGABLE_DEBUG_SHIFT; +pub const VM_PURGABLE_DEBUG_EMPTY: c_int = 0x1 << VM_PURGABLE_DEBUG_SHIFT; +pub const VM_PURGABLE_DEBUG_FAULT: c_int = 0x2 << VM_PURGABLE_DEBUG_SHIFT; -pub const VM_PURGABLE_BEHAVIOR_SHIFT: ::libc::c_int = 6; -pub const VM_PURGABLE_BEHAVIOR_MASK: ::libc::c_int = 1 << VM_PURGABLE_BEHAVIOR_SHIFT; -pub const VM_PURGABLE_BEHAVIOR_FIFO: ::libc::c_int = 0 << VM_PURGABLE_BEHAVIOR_SHIFT; -pub const VM_PURGABLE_BEHAVIOR_LIFO: ::libc::c_int = 1 << VM_PURGABLE_BEHAVIOR_SHIFT; +pub const VM_VOLATILE_GROUP_SHIFT: c_int = 8; +pub const VM_VOLATILE_GROUP_MASK: c_int = 7 << VM_VOLATILE_GROUP_SHIFT; +pub const VM_VOLATILE_GROUP_DEFAULT: c_int = VM_VOLATILE_GROUP_0; -pub const VM_PURGABLE_ORDERING_SHIFT: ::libc::c_int = 5; -pub const VM_PURGABLE_ORDERING_MASK: ::libc::c_int = 1 << VM_PURGABLE_ORDERING_SHIFT; -pub const VM_PURGABLE_ORDERING_OBSOLETE: ::libc::c_int = 1 << VM_PURGABLE_ORDERING_SHIFT; -pub const VM_PURGABLE_ORDERING_NORMAL: ::libc::c_int = 0 << VM_PURGABLE_ORDERING_SHIFT; +pub const VM_VOLATILE_GROUP_0: c_int = 0 << VM_VOLATILE_GROUP_SHIFT; +pub const VM_VOLATILE_GROUP_1: c_int = 1 << VM_VOLATILE_GROUP_SHIFT; +pub const VM_VOLATILE_GROUP_2: c_int = 2 << VM_VOLATILE_GROUP_SHIFT; +pub const VM_VOLATILE_GROUP_3: c_int = 3 << VM_VOLATILE_GROUP_SHIFT; +pub const VM_VOLATILE_GROUP_4: c_int = 4 << VM_VOLATILE_GROUP_SHIFT; +pub const VM_VOLATILE_GROUP_5: c_int = 5 << VM_VOLATILE_GROUP_SHIFT; +pub const VM_VOLATILE_GROUP_6: c_int = 6 << VM_VOLATILE_GROUP_SHIFT; +pub const VM_VOLATILE_GROUP_7: c_int = 7 << VM_VOLATILE_GROUP_SHIFT; -pub const VM_VOLATILE_ORDER_SHIFT: ::libc::c_int = 4; -pub const VM_VOLATILE_ORDER_MASK: ::libc::c_int = 1 << VM_VOLATILE_ORDER_SHIFT; -pub const VM_VOLATILE_MAKE_FIRST_IN_GROUP: ::libc::c_int = 1 << VM_VOLATILE_ORDER_SHIFT; -pub const VM_VOLATILE_MAKE_LAST_IN_GROUP: ::libc::c_int = 0 << VM_VOLATILE_ORDER_SHIFT; +pub const VM_PURGABLE_BEHAVIOR_SHIFT: c_int = 6; +pub const VM_PURGABLE_BEHAVIOR_MASK: c_int = 1 << VM_PURGABLE_BEHAVIOR_SHIFT; +pub const VM_PURGABLE_BEHAVIOR_FIFO: c_int = 0 << VM_PURGABLE_BEHAVIOR_SHIFT; +pub const VM_PURGABLE_BEHAVIOR_LIFO: c_int = 1 << VM_PURGABLE_BEHAVIOR_SHIFT; -pub const VM_PURGABLE_STATE_MIN: ::libc::c_int = 0; -pub const VM_PURGABLE_STATE_MAX: ::libc::c_int = 3; -pub const VM_PURGABLE_STATE_MASK: ::libc::c_int = 3; -pub const VM_PURGABLE_NONVOLATILE: ::libc::c_int = 0; -pub const VM_PURGABLE_VOLATILE: ::libc::c_int = 1; -pub const VM_PURGABLE_EMPTY: ::libc::c_int = 2; -pub const VM_PURGABLE_DENY: ::libc::c_int = 3; +pub const VM_PURGABLE_ORDERING_SHIFT: c_int = 5; +pub const VM_PURGABLE_ORDERING_MASK: c_int = 1 << VM_PURGABLE_ORDERING_SHIFT; +pub const VM_PURGABLE_ORDERING_OBSOLETE: c_int = 1 << VM_PURGABLE_ORDERING_SHIFT; +pub const VM_PURGABLE_ORDERING_NORMAL: c_int = 0 << VM_PURGABLE_ORDERING_SHIFT; + +pub const VM_VOLATILE_ORDER_SHIFT: c_int = 4; +pub const VM_VOLATILE_ORDER_MASK: c_int = 1 << VM_VOLATILE_ORDER_SHIFT; +pub const VM_VOLATILE_MAKE_FIRST_IN_GROUP: c_int = 1 << VM_VOLATILE_ORDER_SHIFT; +pub const VM_VOLATILE_MAKE_LAST_IN_GROUP: c_int = 0 << VM_VOLATILE_ORDER_SHIFT; + +pub const VM_PURGABLE_STATE_MIN: c_int = 0; +pub const VM_PURGABLE_STATE_MAX: c_int = 3; +pub const VM_PURGABLE_STATE_MASK: c_int = 3; +pub const VM_PURGABLE_NONVOLATILE: c_int = 0; +pub const VM_PURGABLE_VOLATILE: c_int = 1; +pub const VM_PURGABLE_EMPTY: c_int = 2; +pub const VM_PURGABLE_DENY: c_int = 3; +pub const VM_PURGABLE_ALL_MASKS: c_int = VM_PURGABLE_STATE_MASK + | VM_VOLATILE_ORDER_MASK + | VM_PURGABLE_ORDERING_MASK + | VM_PURGABLE_BEHAVIOR_MASK + | VM_VOLATILE_GROUP_MASK + | VM_PURGABLE_DEBUG_MASK + | VM_PURGABLE_NO_AGING_MASK; diff --git a/third_party/rust/mach2/src/vm_region.rs b/third_party/rust/mach2/src/vm_region.rs index b88b59fc56cf..2a53c2250631 100644 --- a/third_party/rust/mach2/src/vm_region.rs +++ b/third_party/rust/mach2/src/vm_region.rs @@ -1,45 +1,69 @@ //! This module roughly corresponds to `mach/vm_region.h`. -use boolean::boolean_t; -use mem; -use memory_object_types::{memory_object_offset_t, vm_object_id_t}; -use message::mach_msg_type_number_t; -use vm_behavior::vm_behavior_t; -use vm_inherit::vm_inherit_t; -use vm_prot::vm_prot_t; -use vm_types::{mach_vm_address_t, mach_vm_size_t}; +use crate::boolean::boolean_t; +use crate::memory_object_types::{memory_object_offset_t, vm_object_id_t}; +use crate::message::mach_msg_type_number_t; +use crate::vm_behavior::vm_behavior_t; +use crate::vm_inherit::vm_inherit_t; +use crate::vm_prot::vm_prot_t; +use crate::vm_types::{mach_vm_address_t, mach_vm_size_t, natural_t}; +use core::ffi::{c_int, c_uchar, c_uint, c_ushort}; +use core::mem; pub type vm32_object_id_t = u32; -pub type vm_region_info_t = *mut ::libc::c_int; -pub type vm_region_info_64_t = *mut ::libc::c_int; -pub type vm_region_recurse_info_t = *mut ::libc::c_int; -pub type vm_region_recurse_info_64_t = *mut ::libc::c_int; -pub type vm_region_flavor_t = ::libc::c_int; -pub type vm_region_info_data_t = [::libc::c_int; VM_REGION_INFO_MAX as usize]; +pub type vm_region_info_t = *mut c_int; +pub type vm_region_info_64_t = *mut c_int; +pub type vm_region_recurse_info_t = *mut c_int; +pub type vm_region_recurse_info_64_t = *mut c_int; +pub type vm_region_flavor_t = c_int; +pub type vm_region_info_data_t = [c_int; VM_REGION_INFO_MAX as usize]; pub type vm_region_basic_info_64_t = *mut vm_region_basic_info_64; pub type vm_region_basic_info_data_64_t = vm_region_basic_info_64; pub type vm_region_basic_info_t = *mut vm_region_basic_info; pub type vm_region_basic_info_data_t = vm_region_basic_info; +pub const VM_REGION_BASIC_INFO_COUNT_64: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; +pub const VM_REGION_BASIC_INFO_COUNT: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; pub type vm_region_extended_info_t = *mut vm_region_extended_info; pub type vm_region_extended_info_data_t = vm_region_extended_info; pub type vm_region_top_info_t = *mut vm_region_top_info; pub type vm_region_top_info_data_t = vm_region_top_info; +pub const VM_REGION_EXTENDED_INFO_COUNT: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; +pub const VM_REGION_TOP_INFO_COUNT: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; pub type vm_region_submap_info_t = *mut vm_region_submap_info; pub type vm_region_submap_info_data_t = vm_region_submap_info; pub type vm_region_submap_info_64_t = *mut vm_region_submap_info_64; pub type vm_region_submap_info_data_64_t = vm_region_submap_info_64; pub type vm_region_submap_short_info_64_t = *mut vm_region_submap_short_info_64; pub type vm_region_submap_short_info_data_64_t = vm_region_submap_short_info_64; -pub type vm_page_info_t = *mut ::libc::c_int; -pub type vm_page_info_flavor_t = ::libc::c_int; +pub type vm_page_info_t = *mut c_int; +pub type vm_page_info_flavor_t = c_int; pub type vm_page_info_basic_t = *mut vm_page_info_basic; pub type vm_page_info_basic_data_t = vm_page_info_basic; pub type mach_vm_read_entry_t = [mach_vm_read_entry; VM_MAP_ENTRY_MAX as usize]; +pub const VM_REGION_SUBMAP_INFO_COUNT: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; +pub const VM_REGION_SUBMAP_SHORT_INFO_COUNT_64: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; +pub const VM_PAGE_INFO_BASIC_COUNT: mach_msg_type_number_t = + (mem::size_of::() / mem::size_of::()) + as mach_msg_type_number_t; +pub const VM_REGION_FLAG_JIT_ENABLED: c_ushort = 0x1; +pub const VM_REGION_FLAG_TPRO_ENABLED: c_ushort = 0x2; -pub const VM_REGION_INFO_MAX: ::libc::c_int = 1 << 10; -pub const VM_MAP_ENTRY_MAX: ::libc::c_int = 1 << 8; +pub const VM_REGION_INFO_MAX: c_int = 1 << 10; +pub const VM_MAP_ENTRY_MAX: c_int = 1 << 8; pub const VM_PAGE_INFO_BASIC: vm_page_info_flavor_t = 1; @@ -48,13 +72,14 @@ pub const VM_REGION_BASIC_INFO: vm_region_flavor_t = 10; pub const VM_REGION_EXTENDED_INFO: vm_region_flavor_t = 13; pub const VM_REGION_TOP_INFO: vm_region_flavor_t = 12; -pub const SM_COW: ::libc::c_uchar = 1; -pub const SM_PRIVATE: ::libc::c_uchar = 2; -pub const SM_EMPTY: ::libc::c_uchar = 3; -pub const SM_SHARED: ::libc::c_uchar = 4; -pub const SM_TRUESHARED: ::libc::c_uchar = 5; -pub const SM_PRIVATE_ALIASED: ::libc::c_uchar = 6; -pub const SM_SHARED_ALIASED: ::libc::c_uchar = 7; +pub const SM_COW: c_uchar = 1; +pub const SM_PRIVATE: c_uchar = 2; +pub const SM_EMPTY: c_uchar = 3; +pub const SM_SHARED: c_uchar = 4; +pub const SM_TRUESHARED: c_uchar = 5; +pub const SM_PRIVATE_ALIASED: c_uchar = 6; +pub const SM_SHARED_ALIASED: c_uchar = 7; +pub const SM_LARGE_PAGE: c_uchar = 8; #[repr(C, packed(4))] #[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] @@ -66,12 +91,12 @@ pub struct vm_region_basic_info_64 { pub reserved: boolean_t, pub offset: memory_object_offset_t, pub behavior: vm_behavior_t, - pub user_wired_count: ::libc::c_ushort, + pub user_wired_count: c_ushort, } impl vm_region_basic_info_64 { pub fn count() -> mach_msg_type_number_t { - (mem::size_of::() / mem::size_of::<::libc::c_int>()) as mach_msg_type_number_t + (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t } } @@ -85,12 +110,12 @@ pub struct vm_region_basic_info { pub reserved: boolean_t, pub offset: u32, pub behavior: vm_behavior_t, - pub user_wired_count: ::libc::c_ushort, + pub user_wired_count: c_ushort, } impl vm_region_basic_info { pub fn count() -> mach_msg_type_number_t { - (mem::size_of::() / mem::size_of::<::libc::c_int>()) as mach_msg_type_number_t + (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t } } @@ -98,37 +123,37 @@ impl vm_region_basic_info { #[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] pub struct vm_region_extended_info { pub protection: vm_prot_t, - pub user_tag: ::libc::c_uint, - pub pages_resident: ::libc::c_uint, - pub pages_shared_now_private: ::libc::c_uint, - pub pages_swapped_out: ::libc::c_uint, - pub pages_dirtied: ::libc::c_uint, - pub ref_count: ::libc::c_uint, - pub shadow_depth: ::libc::c_ushort, - pub external_pager: ::libc::c_uchar, - pub share_mode: ::libc::c_uchar, - pub pages_reusable: ::libc::c_uint, + pub user_tag: c_uint, + pub pages_resident: c_uint, + pub pages_shared_now_private: c_uint, + pub pages_swapped_out: c_uint, + pub pages_dirtied: c_uint, + pub ref_count: c_uint, + pub shadow_depth: c_ushort, + pub external_pager: c_uchar, + pub share_mode: c_uchar, + pub pages_reusable: c_uint, } impl vm_region_extended_info { pub fn count() -> mach_msg_type_number_t { - (mem::size_of::() / mem::size_of::<::libc::c_int>()) as mach_msg_type_number_t + (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t } } #[repr(C)] #[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] pub struct vm_region_top_info { - pub obj_id: ::libc::c_uint, - pub ref_count: ::libc::c_uint, - pub private_pages_resident: ::libc::c_uint, - pub shared_pages_resident: ::libc::c_uint, - pub share_mode: ::libc::c_uchar, + pub obj_id: c_uint, + pub ref_count: c_uint, + pub private_pages_resident: c_uint, + pub shared_pages_resident: c_uint, + pub share_mode: c_uchar, } impl vm_region_top_info { pub fn count() -> mach_msg_type_number_t { - (mem::size_of::() / mem::size_of::<::libc::c_int>()) as mach_msg_type_number_t + (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t } } @@ -139,24 +164,24 @@ pub struct vm_region_submap_info { pub max_protection: vm_prot_t, pub inheritance: vm_inherit_t, pub offset: u32, - pub user_tag: ::libc::c_uint, - pub pages_resident: ::libc::c_uint, - pub pages_shared_now_private: ::libc::c_uint, - pub pages_swapped_out: ::libc::c_uint, - pub pages_dirtied: ::libc::c_uint, - pub ref_count: ::libc::c_uint, - pub shadow_depth: ::libc::c_ushort, - pub external_pager: ::libc::c_uchar, - pub share_mode: ::libc::c_uchar, + pub user_tag: c_uint, + pub pages_resident: c_uint, + pub pages_shared_now_private: c_uint, + pub pages_swapped_out: c_uint, + pub pages_dirtied: c_uint, + pub ref_count: c_uint, + pub shadow_depth: c_ushort, + pub external_pager: c_uchar, + pub share_mode: c_uchar, pub is_submap: boolean_t, pub behavior: vm_behavior_t, pub object_id: vm32_object_id_t, - pub user_wired_count: ::libc::c_ushort, + pub user_wired_count: c_ushort, } impl vm_region_submap_info { pub fn count() -> mach_msg_type_number_t { - (mem::size_of::() / mem::size_of::<::libc::c_int>()) as mach_msg_type_number_t + (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t } } @@ -167,25 +192,27 @@ pub struct vm_region_submap_info_64 { pub max_protection: vm_prot_t, pub inheritance: vm_inherit_t, pub offset: memory_object_offset_t, - pub user_tag: ::libc::c_uint, - pub pages_resident: ::libc::c_uint, - pub pages_shared_now_private: ::libc::c_uint, - pub pages_swapped_out: ::libc::c_uint, - pub pages_dirtied: ::libc::c_uint, - pub ref_count: ::libc::c_uint, - pub shadow_depth: ::libc::c_ushort, - pub external_pager: ::libc::c_uchar, - pub share_mode: ::libc::c_uchar, + pub user_tag: c_uint, + pub pages_resident: c_uint, + pub pages_shared_now_private: c_uint, + pub pages_swapped_out: c_uint, + pub pages_dirtied: c_uint, + pub ref_count: c_uint, + pub shadow_depth: c_ushort, + pub external_pager: c_uchar, + pub share_mode: c_uchar, pub is_submap: boolean_t, pub behavior: vm_behavior_t, pub object_id: vm32_object_id_t, - pub user_wired_count: ::libc::c_ushort, - pub pages_reusable: ::libc::c_uint, + pub user_wired_count: c_ushort, + pub flags: c_ushort, + pub pages_reusable: c_uint, + pub object_id_full: vm_object_id_t, } impl vm_region_submap_info_64 { pub fn count() -> mach_msg_type_number_t { - (mem::size_of::() / mem::size_of::<::libc::c_int>()) as mach_msg_type_number_t + (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t } } @@ -196,37 +223,38 @@ pub struct vm_region_submap_short_info_64 { pub max_protection: vm_prot_t, pub inheritance: vm_inherit_t, pub offset: memory_object_offset_t, - pub user_tag: ::libc::c_uint, - pub ref_count: ::libc::c_uint, - pub shadow_depth: ::libc::c_ushort, - pub external_pager: ::libc::c_uchar, - pub share_mode: ::libc::c_uchar, + pub user_tag: c_uint, + pub ref_count: c_uint, + pub shadow_depth: c_ushort, + pub external_pager: c_uchar, + pub share_mode: c_uchar, pub is_submap: boolean_t, pub behavior: vm_behavior_t, pub object_id: vm32_object_id_t, - pub user_wired_count: ::libc::c_ushort, + pub user_wired_count: c_ushort, + pub flags: c_ushort, } impl vm_region_submap_short_info_64 { pub fn count() -> mach_msg_type_number_t { - (mem::size_of::() / mem::size_of::<::libc::c_int>()) as mach_msg_type_number_t + (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t } } #[repr(C)] #[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] pub struct vm_page_info_basic { - pub disposition: ::libc::c_int, - pub ref_count: ::libc::c_int, + pub disposition: c_int, + pub ref_count: c_int, pub object_id: vm_object_id_t, pub offset: memory_object_offset_t, - pub depth: ::libc::c_int, - pub __pad: ::libc::c_int, + pub depth: c_int, + pub __pad: c_int, } impl vm_page_info_basic { pub fn count() -> mach_msg_type_number_t { - (mem::size_of::() / mem::size_of::<::libc::c_int>()) as mach_msg_type_number_t + (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t } } diff --git a/third_party/rust/mach2/src/vm_statistics.rs b/third_party/rust/mach2/src/vm_statistics.rs index bd138ca044a2..38adb88b3334 100644 --- a/third_party/rust/mach2/src/vm_statistics.rs +++ b/third_party/rust/mach2/src/vm_statistics.rs @@ -1,41 +1,256 @@ //! This module roughly corresponds to `mach/vm_statistics.h` -use vm_types::{integer_t, natural_t}; +use crate::vm_types::{integer_t, natural_t}; +use core::ffi::{c_int, c_uint}; pub type vm_statistics_t = *mut vm_statistics; pub type vm_statistics_data_t = vm_statistics; +pub type vm_statistics64_t = *mut vm_statistics64; +pub type vm_statistics64_data_t = vm_statistics64; +pub type vm_extmod_statistics_t = *mut vm_extmod_statistics; +pub type vm_extmod_statistics_data_t = vm_extmod_statistics; +pub type vm_purgeable_stat_t = vm_purgeable_stat; +pub type vm_purgeable_info_t = *mut vm_purgeable_info; pub const VM_PAGE_QUERY_PAGE_PRESENT: integer_t = 1; pub const VM_PAGE_QUERY_PAGE_FICTITIOUS: integer_t = 1 << 1; pub const VM_PAGE_QUERY_PAGE_REF: integer_t = 1 << 2; pub const VM_PAGE_QUERY_PAGE_DIRTY: integer_t = 1 << 3; +pub const VM_PAGE_QUERY_PAGE_PAGED_OUT: integer_t = 1 << 4; +pub const VM_PAGE_QUERY_PAGE_COPIED: integer_t = 1 << 5; +pub const VM_PAGE_QUERY_PAGE_SPECULATIVE: integer_t = 1 << 6; +pub const VM_PAGE_QUERY_PAGE_EXTERNAL: integer_t = 1 << 7; +pub const VM_PAGE_QUERY_PAGE_CS_VALIDATED: integer_t = 1 << 8; +pub const VM_PAGE_QUERY_PAGE_CS_TAINTED: integer_t = 1 << 9; +pub const VM_PAGE_QUERY_PAGE_CS_NX: integer_t = 1 << 10; +pub const VM_PAGE_QUERY_PAGE_REUSABLE: integer_t = 1 << 11; -pub const VM_MEMORY_MALLOC: ::libc::c_uint = 1; -pub const VM_MEMORY_MALLOC_SMALL: ::libc::c_uint = 2; -pub const VM_MEMORY_MALLOC_LARGE: ::libc::c_uint = 3; -pub const VM_MEMORY_MALLOC_HUGE: ::libc::c_uint = 4; -pub const VM_MEMORY_SBRK: ::libc::c_uint = 5; -pub const VM_MEMORY_ANALYSIS_TOOL: ::libc::c_uint = 10; -pub const VM_MEMORY_MACH_MSG: ::libc::c_uint = 20; -pub const VM_MEMORY_IOKIT: ::libc::c_uint = 21; -pub const VM_MEMORY_STACK: ::libc::c_uint = 30; -pub const VM_MEMORY_GUARD: ::libc::c_uint = 31; -pub const VM_MEMORY_SHARED_PMAP: ::libc::c_uint = 32; -pub const VM_MEMORY_DYLIB: ::libc::c_uint = 33; -pub const VM_MEMORY_APPKIT: ::libc::c_uint = 40; -pub const VM_MEMORY_FOUNDATION: ::libc::c_uint = 41; -pub const VM_MEMORY_COREGRAPHICS: ::libc::c_uint = 42; -pub const VM_MEMORY_CARBON: ::libc::c_uint = 43; -pub const VM_MEMORY_JAVA: ::libc::c_uint = 44; -pub const VM_MEMORY_ATS: ::libc::c_uint = 50; -pub const VM_MEMORY_DYLD: ::libc::c_uint = 60; -pub const VM_MEMORY_DYLD_MALLOC: ::libc::c_uint = 61; -pub const VM_MEMORY_APPLICATION_SPECIFIC_1: ::libc::c_uint = 240; -pub const VM_MEMORY_APPLICATION_SPECIFIC_16: ::libc::c_uint = 255; +pub const VM_MEMORY_MALLOC: c_uint = 1; +pub const VM_MEMORY_MALLOC_SMALL: c_uint = 2; +pub const VM_MEMORY_MALLOC_LARGE: c_uint = 3; +pub const VM_MEMORY_MALLOC_HUGE: c_uint = 4; +pub const VM_MEMORY_SBRK: c_uint = 5; +pub const VM_MEMORY_REALLOC: c_uint = 6; +pub const VM_MEMORY_MALLOC_TINY: c_uint = 7; +pub const VM_MEMORY_MALLOC_LARGE_REUSABLE: c_uint = 8; +pub const VM_MEMORY_MALLOC_LARGE_REUSED: c_uint = 9; +pub const VM_MEMORY_ANALYSIS_TOOL: c_uint = 10; +pub const VM_MEMORY_MALLOC_NANO: c_uint = 11; +pub const VM_MEMORY_MALLOC_MEDIUM: c_uint = 12; +pub const VM_MEMORY_MALLOC_PROB_GUARD: c_uint = 13; +pub const VM_MEMORY_MACH_MSG: c_uint = 20; +pub const VM_MEMORY_IOKIT: c_uint = 21; +pub const VM_MEMORY_STACK: c_uint = 30; +pub const VM_MEMORY_GUARD: c_uint = 31; +pub const VM_MEMORY_SHARED_PMAP: c_uint = 32; +pub const VM_MEMORY_DYLIB: c_uint = 33; +pub const VM_MEMORY_OBJC_DISPATCHERS: c_uint = 34; +pub const VM_MEMORY_UNSHARED_PMAP: c_uint = 35; +pub const VM_MEMORY_LIBCHANNEL: c_uint = 36; +pub const VM_MEMORY_APPKIT: c_uint = 40; +pub const VM_MEMORY_FOUNDATION: c_uint = 41; +pub const VM_MEMORY_COREGRAPHICS: c_uint = 42; +pub const VM_MEMORY_CORESERVICES: c_uint = 43; +pub const VM_MEMORY_CARBON: c_uint = VM_MEMORY_CORESERVICES; +pub const VM_MEMORY_JAVA: c_uint = 44; +pub const VM_MEMORY_COREDATA: c_uint = 45; +pub const VM_MEMORY_COREDATA_OBJECTIDS: c_uint = 46; +pub const VM_MEMORY_ATS: c_uint = 50; +pub const VM_MEMORY_LAYERKIT: c_uint = 51; +pub const VM_MEMORY_CGIMAGE: c_uint = 52; +pub const VM_MEMORY_TCMALLOC: c_uint = 53; +pub const VM_MEMORY_COREGRAPHICS_DATA: c_uint = 54; +pub const VM_MEMORY_COREGRAPHICS_SHARED: c_uint = 55; +pub const VM_MEMORY_COREGRAPHICS_FRAMEBUFFERS: c_uint = 56; +pub const VM_MEMORY_COREGRAPHICS_BACKINGSTORES: c_uint = 57; +pub const VM_MEMORY_COREGRAPHICS_XALLOC: c_uint = 58; +pub const VM_MEMORY_COREGRAPHICS_MISC: c_uint = VM_MEMORY_COREGRAPHICS; +pub const VM_MEMORY_DYLD: c_uint = 60; +pub const VM_MEMORY_DYLD_MALLOC: c_uint = 61; +pub const VM_MEMORY_SQLITE: c_uint = 62; +pub const VM_MEMORY_JAVASCRIPT_CORE: c_uint = 63; +pub const VM_MEMORY_WEBASSEMBLY: c_uint = VM_MEMORY_JAVASCRIPT_CORE; +pub const VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR: c_uint = 64; +pub const VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE: c_uint = 65; +pub const VM_MEMORY_GLSL: c_uint = 66; +pub const VM_MEMORY_OPENCL: c_uint = 67; +pub const VM_MEMORY_COREIMAGE: c_uint = 68; +pub const VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS: c_uint = 69; +pub const VM_MEMORY_IMAGEIO: c_uint = 70; +pub const VM_MEMORY_COREPROFILE: c_uint = 71; +pub const VM_MEMORY_ASSETSD: c_uint = 72; +pub const VM_MEMORY_OS_ALLOC_ONCE: c_uint = 73; +pub const VM_MEMORY_LIBDISPATCH: c_uint = 74; +pub const VM_MEMORY_ACCELERATE: c_uint = 75; +pub const VM_MEMORY_COREUI: c_uint = 76; +pub const VM_MEMORY_COREUIFILE: c_uint = 77; +pub const VM_MEMORY_GENEALOGY: c_uint = 78; +pub const VM_MEMORY_RAWCAMERA: c_uint = 79; +pub const VM_MEMORY_CORPSEINFO: c_uint = 80; +pub const VM_MEMORY_ASL: c_uint = 81; +pub const VM_MEMORY_SWIFT_RUNTIME: c_uint = 82; +pub const VM_MEMORY_SWIFT_METADATA: c_uint = 83; +pub const VM_MEMORY_DHMM: c_uint = 84; +pub const VM_MEMORY_DFR: c_uint = 85; +pub const VM_MEMORY_SCENEKIT: c_uint = 86; +pub const VM_MEMORY_SKYWALK: c_uint = 87; +pub const VM_MEMORY_IOSURFACE: c_uint = 88; +pub const VM_MEMORY_LIBNETWORK: c_uint = 89; +pub const VM_MEMORY_AUDIO: c_uint = 90; +pub const VM_MEMORY_VIDEOBITSTREAM: c_uint = 91; +pub const VM_MEMORY_CM_XPC: c_uint = 92; +pub const VM_MEMORY_CM_RPC: c_uint = 93; +pub const VM_MEMORY_CM_MEMORYPOOL: c_uint = 94; +pub const VM_MEMORY_CM_READCACHE: c_uint = 95; +pub const VM_MEMORY_CM_CRABS: c_uint = 96; +pub const VM_MEMORY_QUICKLOOK_THUMBNAILS: c_uint = 97; +pub const VM_MEMORY_ACCOUNTS: c_uint = 98; +pub const VM_MEMORY_SANITIZER: c_uint = 99; +pub const VM_MEMORY_IOACCELERATOR: c_uint = 100; +pub const VM_MEMORY_CM_REGWARP: c_uint = 101; +pub const VM_MEMORY_EAR_DECODER: c_uint = 102; +pub const VM_MEMORY_COREUI_CACHED_IMAGE_DATA: c_uint = 103; +pub const VM_MEMORY_COLORSYNC: c_uint = 104; +pub const VM_MEMORY_BTINFO: c_uint = 105; +pub const VM_MEMORY_CM_HLS: c_uint = 106; +pub const VM_MEMORY_COMPOSITOR_SERVICES: c_uint = 107; +pub const VM_MEMORY_ROSETTA: c_uint = 230; +pub const VM_MEMORY_ROSETTA_THREAD_CONTEXT: c_uint = 231; +pub const VM_MEMORY_ROSETTA_INDIRECT_BRANCH_MAP: c_uint = 232; +pub const VM_MEMORY_ROSETTA_RETURN_STACK: c_uint = 233; +pub const VM_MEMORY_ROSETTA_EXECUTABLE_HEAP: c_uint = 234; +pub const VM_MEMORY_ROSETTA_USER_LDT: c_uint = 235; +pub const VM_MEMORY_ROSETTA_ARENA: c_uint = 236; +pub const VM_MEMORY_ROSETTA_10: c_uint = 239; +pub const VM_MEMORY_APPLICATION_SPECIFIC_1: c_uint = 240; +pub const VM_MEMORY_APPLICATION_SPECIFIC_2: c_uint = 241; +pub const VM_MEMORY_APPLICATION_SPECIFIC_3: c_uint = 242; +pub const VM_MEMORY_APPLICATION_SPECIFIC_4: c_uint = 243; +pub const VM_MEMORY_APPLICATION_SPECIFIC_5: c_uint = 244; +pub const VM_MEMORY_APPLICATION_SPECIFIC_6: c_uint = 245; +pub const VM_MEMORY_APPLICATION_SPECIFIC_7: c_uint = 246; +pub const VM_MEMORY_APPLICATION_SPECIFIC_8: c_uint = 247; +pub const VM_MEMORY_APPLICATION_SPECIFIC_9: c_uint = 248; +pub const VM_MEMORY_APPLICATION_SPECIFIC_10: c_uint = 249; +pub const VM_MEMORY_APPLICATION_SPECIFIC_11: c_uint = 250; +pub const VM_MEMORY_APPLICATION_SPECIFIC_12: c_uint = 251; +pub const VM_MEMORY_APPLICATION_SPECIFIC_13: c_uint = 252; +pub const VM_MEMORY_APPLICATION_SPECIFIC_14: c_uint = 253; +pub const VM_MEMORY_APPLICATION_SPECIFIC_15: c_uint = 254; +pub const VM_MEMORY_APPLICATION_SPECIFIC_16: c_uint = 255; +pub const VM_MEMORY_COUNT: c_uint = 256; -pub const VM_FLAGS_FIXED: ::libc::c_int = 0x0; -pub const VM_FLAGS_ANYWHERE: ::libc::c_int = 0x1; -pub const VM_FLAGS_OVERWRITE: ::libc::c_int = 0x4000; +#[inline] +pub const fn vm_make_tag(tag: c_uint) -> c_int { + (tag as c_int) << 24 +} + +pub const VM_FLAGS_FIXED: c_int = 0x0; +pub const VM_FLAGS_ANYWHERE: c_int = 0x1; +pub const VM_FLAGS_PURGABLE: c_int = 0x2; +pub const VM_FLAGS_4GB_CHUNK: c_int = 0x4; +pub const VM_FLAGS_RANDOM_ADDR: c_int = 0x8; +pub const VM_FLAGS_NO_CACHE: c_int = 0x10; +pub const VM_FLAGS_RESILIENT_CODESIGN: c_int = 0x20; +pub const VM_FLAGS_RESILIENT_MEDIA: c_int = 0x40; +pub const VM_FLAGS_PERMANENT: c_int = 0x80; +pub const VM_FLAGS_TPRO: c_int = 0x1000; +pub const VM_FLAGS_MTE: c_int = 0x2000; +pub const VM_FLAGS_OVERWRITE: c_int = 0x4000; +pub const VM_FLAGS_SUPERPAGE_MASK: c_int = 0x0007_0000; +pub const VM_FLAGS_RETURN_DATA_ADDR: c_int = 0x0010_0000; +pub const VM_FLAGS_RETURN_4K_DATA_ADDR: c_int = 0x0080_0000; +pub const VM_FLAGS_ALIAS_MASK: c_int = -16_777_216; // 0xFF000000 + +pub const VM_FLAGS_HW: c_int = VM_FLAGS_TPRO | VM_FLAGS_MTE; + +pub const VM_FLAGS_USER_ALLOCATE: c_int = VM_FLAGS_FIXED + | VM_FLAGS_ANYWHERE + | VM_FLAGS_PURGABLE + | VM_FLAGS_4GB_CHUNK + | VM_FLAGS_RANDOM_ADDR + | VM_FLAGS_NO_CACHE + | VM_FLAGS_PERMANENT + | VM_FLAGS_OVERWRITE + | VM_FLAGS_SUPERPAGE_MASK + | VM_FLAGS_HW + | VM_FLAGS_ALIAS_MASK; +pub const VM_FLAGS_USER_MAP: c_int = + VM_FLAGS_USER_ALLOCATE | VM_FLAGS_RETURN_4K_DATA_ADDR | VM_FLAGS_RETURN_DATA_ADDR; +pub const VM_FLAGS_USER_REMAP: c_int = VM_FLAGS_FIXED + | VM_FLAGS_ANYWHERE + | VM_FLAGS_RANDOM_ADDR + | VM_FLAGS_OVERWRITE + | VM_FLAGS_RETURN_DATA_ADDR + | VM_FLAGS_RESILIENT_CODESIGN + | VM_FLAGS_RESILIENT_MEDIA; + +pub const VM_FLAGS_SUPERPAGE_SHIFT: c_int = 16; +pub const SUPERPAGE_NONE: c_int = 0; +pub const SUPERPAGE_SIZE_ANY: c_int = 1; +pub const VM_FLAGS_SUPERPAGE_NONE: c_int = SUPERPAGE_NONE << VM_FLAGS_SUPERPAGE_SHIFT; +pub const VM_FLAGS_SUPERPAGE_SIZE_ANY: c_int = SUPERPAGE_SIZE_ANY << VM_FLAGS_SUPERPAGE_SHIFT; +#[cfg(target_arch = "x86_64")] +pub const SUPERPAGE_SIZE_2MB: c_int = 2; +#[cfg(target_arch = "x86_64")] +pub const VM_FLAGS_SUPERPAGE_SIZE_2MB: c_int = SUPERPAGE_SIZE_2MB << VM_FLAGS_SUPERPAGE_SHIFT; + +pub const GUARD_TYPE_VIRT_MEMORY: u32 = 5; + +pub type virtual_memory_guard_exception_code_t = u32; +pub const kGUARD_EXC_DEALLOC_GAP: u32 = 1; +pub const kGUARD_EXC_RECLAIM_COPYIO_FAILURE: u32 = 2; +pub const kGUARD_EXC_RECLAIM_INDEX_FAILURE: u32 = 4; +pub const kGUARD_EXC_RECLAIM_DEALLOCATE_FAILURE: u32 = 8; +pub const kGUARD_EXC_RECLAIM_ACCOUNTING_FAILURE: u32 = 9; +pub const kGUARD_EXC_SEC_IOPL_ON_EXEC_PAGE: u32 = 10; +pub const kGUARD_EXC_SEC_EXEC_ON_IOPL_PAGE: u32 = 11; +pub const kGUARD_EXC_SEC_UPL_WRITE_ON_EXEC_REGION: u32 = 12; + +pub const kGUARD_EXC_SEC_ACCESS_FAULT: u32 = 98; +pub const kGUARD_EXC_SEC_ASYNC_ACCESS_FAULT: u32 = 99; +pub const kGUARD_EXC_SEC_COPY_DENIED: u32 = 100; +pub const kGUARD_EXC_SEC_SHARING_DENIED: u32 = 101; +pub const kGUARD_EXC_MTE_SYNC_FAULT: u32 = 200; +pub const kGUARD_EXC_MTE_ASYNC_USER_FAULT: u32 = 201; +pub const kGUARD_EXC_MTE_ASYNC_KERN_FAULT: u32 = 202; + +pub const kGUARD_EXC_MTE_SOFT_MODE: u32 = 0x100000; + +pub const __VM_LEDGER_ACCOUNTING_POSTMARK: u64 = 2_019_032_600; +pub const VM_LEDGER_TAG_NONE: c_int = 0x0000_0000; +pub const VM_LEDGER_TAG_DEFAULT: c_int = 0x0000_0001; +pub const VM_LEDGER_TAG_NETWORK: c_int = 0x0000_0002; +pub const VM_LEDGER_TAG_MEDIA: c_int = 0x0000_0003; +pub const VM_LEDGER_TAG_GRAPHICS: c_int = 0x0000_0004; +pub const VM_LEDGER_TAG_NEURAL: c_int = 0x0000_0005; +pub const VM_LEDGER_TAG_MAX: c_int = VM_LEDGER_TAG_NEURAL; +pub const VM_LEDGER_TAG_UNCHANGED: c_int = -1; +pub const VM_LEDGER_FLAG_NO_FOOTPRINT: c_int = 1 << 0; +pub const VM_LEDGER_FLAG_NO_FOOTPRINT_FOR_DEBUG: c_int = 1 << 1; +pub const VM_LEDGER_FLAG_FROM_KERNEL: c_int = 1 << 2; +pub const VM_LEDGER_FLAGS_USER: c_int = + VM_LEDGER_FLAG_NO_FOOTPRINT | VM_LEDGER_FLAG_NO_FOOTPRINT_FOR_DEBUG; +pub const VM_LEDGER_FLAGS_ALL: c_int = VM_LEDGER_FLAGS_USER | VM_LEDGER_FLAG_FROM_KERNEL; + +#[inline] +pub fn vm_statistics_truncate_to_32_bit(value: u64) -> u32 { + if value > u32::MAX as u64 { + u32::MAX + } else { + value as u32 + } +} + +#[inline] +pub fn vm_get_flags_alias(flags: c_int) -> u8 { + ((flags >> 24) & 0xff) as u8 +} + +#[inline] +pub fn vm_set_flags_alias(flags: &mut c_int, alias: u8) { + *flags = (*flags & !VM_FLAGS_ALIAS_MASK) | ((alias as c_int) << 24); +} #[repr(C)] #[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] @@ -56,3 +271,59 @@ pub struct vm_statistics { pub purges: natural_t, pub speculative_count: natural_t, } + +#[repr(C, packed(8))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct vm_statistics64 { + pub free_count: natural_t, + pub active_count: natural_t, + pub inactive_count: natural_t, + pub wire_count: natural_t, + pub zero_fill_count: u64, + pub reactivations: u64, + pub pageins: u64, + pub pageouts: u64, + pub faults: u64, + pub cow_faults: u64, + pub lookups: u64, + pub hits: u64, + pub purges: u64, + pub purgeable_count: natural_t, + pub speculative_count: natural_t, + pub decompressions: u64, + pub compressions: u64, + pub swapins: u64, + pub swapouts: u64, + pub compressor_page_count: natural_t, + pub throttled_count: natural_t, + pub external_page_count: natural_t, + pub internal_page_count: natural_t, + pub total_uncompressed_pages_in_compressor: u64, + pub swapped_count: u64, +} + +#[repr(C, packed(8))] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct vm_extmod_statistics { + pub task_for_pid_count: i64, + pub task_for_pid_caller_count: i64, + pub thread_creation_count: i64, + pub thread_creation_caller_count: i64, + pub thread_set_state_count: i64, + pub thread_set_state_caller_count: i64, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct vm_purgeable_stat { + pub count: u64, + pub size: u64, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)] +pub struct vm_purgeable_info { + pub fifo_data: [vm_purgeable_stat_t; 8usize], + pub obsolete_data: vm_purgeable_stat_t, + pub lifo_data: [vm_purgeable_stat_t; 8usize], +} diff --git a/third_party/rust/mach2/src/vm_sync.rs b/third_party/rust/mach2/src/vm_sync.rs index c562397358b8..aeed505b7dcd 100644 --- a/third_party/rust/mach2/src/vm_sync.rs +++ b/third_party/rust/mach2/src/vm_sync.rs @@ -1,6 +1,7 @@ //! This module corresponds to `mach/vm_sync.h`. +use core::ffi::c_uint; -pub type vm_sync_t = ::libc::c_uint; +pub type vm_sync_t = c_uint; pub const VM_SYNC_ASYNCHRONOUS: vm_sync_t = 1; pub const VM_SYNC_SYNCHRONOUS: vm_sync_t = 1 << 1; diff --git a/third_party/rust/mach2/src/vm_types.rs b/third_party/rust/mach2/src/vm_types.rs index e37b9804c4bc..0725230f226f 100644 --- a/third_party/rust/mach2/src/vm_types.rs +++ b/third_party/rust/mach2/src/vm_types.rs @@ -1,7 +1,8 @@ -//! This module roughly corresponds to `mach/i386/vm_types.h`. +//! This module roughly corresponds to `mach/i386/vm_types.h` and `mach/arm/vm_types.h` on aarch64. +use core::ffi::{c_int, c_uint}; -pub type natural_t = ::libc::c_uint; -pub type integer_t = ::libc::c_int; +pub type natural_t = c_uint; +pub type integer_t = c_int; pub type user_addr_t = u64; @@ -11,9 +12,9 @@ pub type mach_vm_size_t = u64; pub type vm_map_offset_t = u64; pub type vm_map_address_t = u64; pub type vm_map_size_t = u64; -pub type vm_map_t = ::port::mach_port_t; -pub type vm_offset_t = ::libc::uintptr_t; -pub type vm_size_t = ::libc::uintptr_t; +pub type vm_map_t = crate::port::mach_port_t; +pub type vm_offset_t = usize; +pub type vm_size_t = usize; pub type vm_address_t = vm_offset_t; pub type mach_port_context_t = mach_vm_address_t; diff --git a/third_party/rust/minidump-writer/.cargo-checksum.json b/third_party/rust/minidump-writer/.cargo-checksum.json index 22f5cbda4eb6..e9ad7ce2ce60 100644 --- a/third_party/rust/minidump-writer/.cargo-checksum.json +++ b/third_party/rust/minidump-writer/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo/android-runner.sh":"ab3bbf893efd6ec7ad262ffbd0b0172036dacc51f7b6ba634688454dbc5a3127",".cargo/config.toml":"a38182719a06427f6a84318a67418bf73e58053d47c6cda8983e4682f4696313",".github/CODEOWNERS":"ea38cb1cb80482d2f0d0327c8d84d94e55b2171d5a6ed9b9656c6e8ce2938d50",".github/workflows/audit.yml":"19ad888251cbf88d2484d5eecc6e9e47470de20e53cf53e9e6ef5783e6f43483",".github/workflows/ci.yml":"54db6735ed5cc7be01973bd555dbd1484eb535526e02a325e10549988ff936ac","CHANGELOG.md":"202a08b3d7ba93d02e7729bb03b18b8f19d4e019f493eb304254f764601e0f5b","Cargo.lock":"f49c06a0a2c0f3396fc4b5a8d36b4f87f8b68830c7a3f5c088339949e85114b9","Cargo.toml":"65df35d3b0b0fa79f31a12556315243072d500f1c90a1c83c99400aea7f632b6","LICENSE":"1ecdd8e8977af83c07c5f97bec87b47d27059b7ea323ca3160fbfa2314f5d99c","README.md":"8eb9643e0b9fbc85cd15c64427239f8012b4f734696aa155ba1d9db6eb0736d6","build.rs":"689cd32a441f5011f694a9f86bc03bc27c2a09bcb4130f47e04fe00bb069b1b5","deny.toml":"764229c5a5619e336675a4c512b0a2830e2173681c7026d376980ebd75569d04","examples/synthetic.rs":"03374726bb805f2b0e258348a280c2e36df5edfddb121a3e771aaad504694aec","release.toml":"f554067378aec602383b96e5fa63427136533a7dd00137fd0664b279fb8fcc56","src/bin/test.rs":"6d566637dcb06290310030a3902572cb8b4aa7c8922ddfe6e0f940e18c72578e","src/dir_section.rs":"5386b73683fda9a3bf19fc656071d3ec7b4248284dc26ca3b8cbfdfc61d3726a","src/lib.rs":"298379d060cdc74f1b9745bb0cd452b70d24a35fe7e0ea1e22d232f446db5d42","src/linux/android.rs":"8d78677abbd08681068829e6c1262c893997beeb8be8bfefdbf64455d100e347","src/linux/app_memory.rs":"5f093e4ed0aecc6086366a9c09658761fdd3b0e6e9ff2111690719e56612df64","src/linux/auxv/mod.rs":"6999b8fcc5d470922c8012c478ad753f8cc6ebd9698b41fd631d01c3dd3d65e9","src/linux/auxv/reader.rs":"dd82dbdebb46737c95af7e97543f8af4bf3a92b184905a81104e796e000fda87","src/linux/crash_context/aarch64.rs":"97f21fef9db0d0719170e51812903b4bcc9b7802de106404f9929a2fe3f2d02a","src/linux/crash_context/arm.rs":"2274b5af43346491018c21bf01af984719623cc5a365d39424f94dd63aa1ce39","src/linux/crash_context/mod.rs":"0fa80c43990eced7a27cb377fce84afb8b9eddf58863923006d414be6a5a2d9f","src/linux/crash_context/x86.rs":"389be4a28fce3b1f9c5b8b0a1145a0df9de52b9d26b039d022f69c6e7e697710","src/linux/crash_context/x86_64.rs":"81670712b7929e75c38054ada3f016ac3a17e0a152cdd93d58e9c710b11489e1","src/linux/dso_debug.rs":"96b56a3a171a8329abded6d51cad6eccc914c06c525c0dec0e497a4fc5069c18","src/linux/dumper_cpu_info/arm.rs":"a23e00f93d9816c21bd1328b9a08182605f2d783218c4e67604c70ddb70434b1","src/linux/dumper_cpu_info/mod.rs":"f381727faeec2d208f7018dbb22f7d93fa1910f660f329c4ff9f48f2270bb8d7","src/linux/dumper_cpu_info/x86.rs":"571c8eafd3e1835e98102914732f649545fe9684a99cd379f665351d62473403","src/linux/maps_reader.rs":"2ebefd74f67cf212fb1904045a0b330114130ca5f22eeae5cd313ad1d2f16ff5","src/linux/minidump_writer/app_memory.rs":"b3d07c61ede6027794c1ba406d1e3e7b88416141b825ab8d6a8ed375311d30c4","src/linux/minidump_writer/errors.rs":"9a306171fded7aa56fe3e3618b324df9c6dc7ef170abb59ddb1b87b95bb23754","src/linux/minidump_writer/exception_stream.rs":"1e714647a5b62917cb8595219d924928a319aa79e726f68c815d1f64fb54858c","src/linux/minidump_writer/handle_data_stream.rs":"72f4dbd4fdb6aebb5fca589e62a13eab7d319c96de665735c71e8162b1630658","src/linux/minidump_writer/mappings.rs":"a941283b59915e5eb8f2e8630782a410ea9e3b98ec5f4c3355d3f0cf9b478ac5","src/linux/minidump_writer/memory_info_list_stream.rs":"3c77d8b6f0856136590f0bbd70755df8241a23ae382e0a121cfd13f4a8d9ffb1","src/linux/minidump_writer/memory_list_stream.rs":"6ec99cee760afa323502fde6a07f0314d994c4fcae7170a6ea18dfe4be7ab628","src/linux/minidump_writer/mod.rs":"65774851784848c621e87a952b7e36d6bd13e44f2d8ef1a033aba9798913e35b","src/linux/minidump_writer/systeminfo_stream.rs":"40995fd9dd2c09db2c1314171b0cbf60923fcf1b497f6e5c4d763329bd33b85b","src/linux/minidump_writer/thread_list_stream.rs":"8c002247e9143f112baaca5cdc19e91d9b7bbf83ed4e8d66b809aa9a2b8aba63","src/linux/minidump_writer/thread_names_stream.rs":"d5cc4e6e009628805ad32b6762acf94657c9873e9579ecb01fb0f5b2319e5508","src/linux/mod.rs":"a44e1308a8d50415d8cf7afbfdfc06690d59e99ea621e92a81c3356f5b19081c","src/linux/module_reader.rs":"5c0750b338d4e656d3a8b319a9ba91b715c6a7e79e4480585851a090d4431919","src/linux/process_inspection/mod.rs":"1750418f9d8ccf08f655020b9b5c4f07e63552da37282440982c411ec744ff28","src/linux/process_inspection/process_reader.rs":"4d6300b7a38c544c143540634eff8c43966389ea4a837e9bca1e15ec975b82e8","src/linux/serializers.rs":"2ceb04935be0576c282095b3e9e9b656a2adfcf0feef4e046d9c8828b1fe1e38","src/linux/thread_info/aarch64.rs":"1d4841b6a32ffd67cd6a2489feb9a765d2150592371d4d24c7d12d6fdb19feef","src/linux/thread_info/arm.rs":"579c44936d77549810c08c6f2946e71f3fdf65f10fd4148fd0f3a744cc13a559","src/linux/thread_info/mod.rs":"d5da77e4f4d0e5613e3302c464529af68f78bffcabef53261cf03881535f0103","src/linux/thread_info/x86.rs":"b3e1b743a0678ce0c873dc208ca62997c8ba40ed6c92830a81af8f26bcea28c7","src/mac/errors.rs":"6ad50e4da9e5df8b0e9b471086c40c8e5f22ca1d1269a12b5d9cdacd35a07066","src/mac/mach.rs":"ee6f7d9c8715cd191f894ce73913ce299a9a1faebd87bb9cdfad032b26e032ab","src/mac/minidump_writer.rs":"5cc9e83042df41488792c86eaecd311d1bd1ea2990bee990028837f512874166","src/mac/mod.rs":"304094bad42d894f34cc7b792ed59122d98579ffea0e40c31cbc84363df686e0","src/mac/module_reader.rs":"f75841afb2e2cd53d9380869889905e9aceafce0acbff2acf731797f81fa77d1","src/mac/process_reader.rs":"41bc958342a82711c6975377c6591e7645bab2e974b12d832320effb09a50b44","src/mac/streams/breakpad_info.rs":"3971ef91bd0d20fbe34ef3d0138d30dc1e34605c953fb2fd8bf623b7deb9586d","src/mac/streams/exception.rs":"ed8ff9b24279e7597b1e0e5ff150e19d455bf071aec3f45a208833fce8cfca7a","src/mac/streams/memory_list.rs":"e507a1ada858ef535e3e211d91195901e9976ba0ff6cf601919d7cacb48c5e9f","src/mac/streams/misc_info.rs":"22839b0ec1fc1c151831e186793521f1db4c4f237ad8997d844b66ee4743da56","src/mac/streams/mod.rs":"6f650ce6e8141061fbae6446d67951e3acc19f7fb401cb9fddba8296ac85e657","src/mac/streams/module_list.rs":"83f91f0cabcc1adc0db8d12249a52c71f799dab4d3453e15353770900865f9b9","src/mac/streams/system_info.rs":"8032a05568b5bc0a40d61a3353d4fb7b4e567253977e805622d8454cf41e246e","src/mac/streams/thread_list.rs":"0931c4640b657dbfa537f21823300d98a12b5b61553ed19d26331104a6cb9bb7","src/mac/streams/thread_names.rs":"881574c8deda6cbeac039efbbbb9682cd7fa98ff8710aba3ee0c6a218f372c48","src/mac/task_dumper.rs":"69b24681cf9ba2ffeb91ba82a6fbad329510d6814711785beff9b799381ef346","src/mem_writer.rs":"49995b0fca6cc48a8bf47dc8d738d5ee5afbcedea926b0dcba331e6a2b976eb9","src/minidump_cpu.rs":"428bad960ec2319235ca4959d011a1603754ba86c8a565044ac2e77fb157c815","src/minidump_format.rs":"2f96a0efc6b52b1d8af6f0281f6153f4f5f1bcb1816c1c8398cf030613cfcea9","src/module_reader.rs":"29caae7dd615fb542bad368a90fa72cf666da2832eea0980d792b241071c8b07","src/process_reader.rs":"bcd935fada0e449eea2ac6378b985f722f025b497f71df4a19652c72c810e6eb","src/serializers.rs":"aa5713c1739a87eb3cdc21f88d2da5c266ac83e18125f3f4b531badf5d32dec2","src/windows/errors.rs":"9b8752122784417ed48b9c3fccc9bdabc6c4e6285cdb77c79723cba56cb0de82","src/windows/ffi.rs":"784eff570da0668d4fe5671022bb03106db1af71a6fe48cbf62a4f80d3d9b76a","src/windows/minidump_writer.rs":"4e3a2b23dc6701dc74490873fb73d542c4c0dcf5f05b40ad82f38e460c019c82","src/windows/mod.rs":"d40550a4cb5a8e99e2bbe281d48e41583be9a8d2398d0f1664bf5a3fcd361ef3","src/windows/module_reader.rs":"929dd6bca70d772294a899f63cf8eb49ae258cb1033e8e292dc1c9768c71acf3","src/windows/process_reader.rs":"162e39188c8f059118a59440e6532369dc2cdeb6d53b6b8582c0b959b5283cf0","tests/common/mod.rs":"429f3ba584e97a858f4390221f120c7724944b91255059b507d9c2d29af8e598","tests/linux_minidump_writer.rs":"764f9802e331fa8a3a7a3a3566af35acf51e6ca02baa2e24bcdb54bd7b01f025","tests/linux_minidump_writer_soft_error.rs":"09991199a685651cfc40a94fe88bf6b84ef72d4f67e520355f7dde28bfbfeafd","tests/linux_module_reader.rs":"03299789005456d8ee5f185f625ba952acedd2a21dacfa3936b8878f9b25f552","tests/mac_minidump_writer.rs":"2c3f8ee0d546eb696a5c8ab6630061238399758457ecf316136c92a4925c5ddf","tests/ptrace_dumper.rs":"3cfb7073b1a401a4691c6ec8d9722c815d8431e850a5789304f3502eb8c1a248","tests/task_dumper.rs":"16af34e70259c00a22f3001e5b2e13c9e990cc07db2722c98ba80e16de686c1d","tests/tiny.elf":"9ccd1d7a8b4d4347f623081ad4a74fade764fa7c8f76495b010bc302fb66e69f","tests/windows_minidump_writer.rs":"f503b424493f4ca73b7c92b6a58f225545169d8909a60a85a9c7cfba6975655a"},"package":null} \ No newline at end of file +{"files":{".cargo/android-runner.sh":"11989fd58a281496b0f11442a94fce235d4f374c14464513802ab6f821021480",".cargo/config.toml":"bbab35dd20d1344ac324cdd3e51712769caf310471cc241a65738dc44d571756",".github/CODEOWNERS":"e94277dbe720151221c67d5b64dd342366220b548f5286f2d3de15e2cf1a486d",".github/workflows/audit.yml":"19ad888251cbf88d2484d5eecc6e9e47470de20e53cf53e9e6ef5783e6f43483",".github/workflows/ci.yml":"8315177abc4dfcd12c2f1e63a0f0463b9d01f812004986f6f6d347f099f44781","CHANGELOG.md":"f458f74add551bf336e2c9ca2c891fd199d9079b725a751d25315aec681f4abf","Cargo.lock":"f25bef79e60cd8ab650fcf3538799f51df1c398a0deb7a6dddd465aece3153cd","Cargo.toml":"ea1612172848ab5a0dd770c32cf811453d0e7f102427b594e69c3698246defc0","LICENSE":"1ecdd8e8977af83c07c5f97bec87b47d27059b7ea323ca3160fbfa2314f5d99c","README.md":"8eb9643e0b9fbc85cd15c64427239f8012b4f734696aa155ba1d9db6eb0736d6","build.rs":"689cd32a441f5011f694a9f86bc03bc27c2a09bcb4130f47e04fe00bb069b1b5","deny.toml":"ac9eb96510b4b01ff7e63615e41c89ad610c6e8ff366a55d06e8387ff99e0d28","examples/synthetic.rs":"03374726bb805f2b0e258348a280c2e36df5edfddb121a3e771aaad504694aec","release.toml":"7b254e9a27a9d9925fca91d173e4be19ca30105e246ad1e9406ffc82ee73ad0b","src/bin/test.rs":"a81a006c5be44a7e303da10db57010c98e09202d0eb0add06f33d9f0a12d76e2","src/dir_section.rs":"5386b73683fda9a3bf19fc656071d3ec7b4248284dc26ca3b8cbfdfc61d3726a","src/lib.rs":"12584dd4889c85822d90a7577d8782d9edd67c14481010e6b04122f95a6f0d28","src/linux/android.rs":"15b10298b383ee826251ef000253db22ded82836895d453c13ac5ef97f4e396c","src/linux/app_memory.rs":"5f093e4ed0aecc6086366a9c09658761fdd3b0e6e9ff2111690719e56612df64","src/linux/auxv/mod.rs":"3f16aa6492847968c91a3378e1fd5487c8471bd0c66b6a4f81c71a7c9e9a9e06","src/linux/auxv/reader.rs":"dd82dbdebb46737c95af7e97543f8af4bf3a92b184905a81104e796e000fda87","src/linux/crash_context_ext/aarch64.rs":"e7e105dc15e838e551f01ec8f2c909f7501813e396afe42e3270495b0c0d605c","src/linux/crash_context_ext/arm.rs":"f745fe4851ccc07c2f22791a80b504a8af953c72c25a248cf8270221d10515e6","src/linux/crash_context_ext/mod.rs":"939c755ccb5072de3aa84c61597f95018a8c4b9600737124f7bd886b1b0ba82d","src/linux/crash_context_ext/x86.rs":"3e54462fda65693ba4f773418a85b39848c9c82e60b15b60bacc75acc8f7a6ff","src/linux/crash_context_ext/x86_64.rs":"12fd3774b4a245b22eeacb9f702b135677a81656d5ad5a2d6cdff6d964cc0564","src/linux/dso_debug.rs":"bcca0d1ef03dd7970908c7abc57df1184c084a394c86786f4974b9a3ba3d6fd1","src/linux/dumper_cpu_info/arm.rs":"0c2ac56b94125a47e42398639131a302dc56b037c9f69f9779ae0ee06e82233c","src/linux/dumper_cpu_info/mod.rs":"f381727faeec2d208f7018dbb22f7d93fa1910f660f329c4ff9f48f2270bb8d7","src/linux/dumper_cpu_info/x86.rs":"f81dd2cf95c8ea46598112024db2236f615cc19d926cf7d18736a22c2cb0d56a","src/linux/maps_reader.rs":"2aff6dd85c46ec22bb34185423ff8c2acfb605e494f76337aeb3f5e7a3ca9f6e","src/linux/minidump_writer/app_memory.rs":"aa3d84d3e06d6d7663802969a9fa38301d988341754f8cf84b14edac16090b5c","src/linux/minidump_writer/errors.rs":"a5e7ed8676eda9fc5829cdf167da75f9e675ee38a83424a03c324c4c9be8c080","src/linux/minidump_writer/exception_stream.rs":"1e714647a5b62917cb8595219d924928a319aa79e726f68c815d1f64fb54858c","src/linux/minidump_writer/handle_data_stream.rs":"93f7470d7abb02efbc64ae0524099390555dc04502dacf6e50895baa9915c166","src/linux/minidump_writer/mappings.rs":"260a61893e509ef0219a62c7acd34ce26f3a1e09afe2834da0d97d9aae173826","src/linux/minidump_writer/memory_info_list_stream.rs":"7bc4bef25324d2e324004d03686fa862f9e2ffc24bf361a511d4131d0ed8473c","src/linux/minidump_writer/memory_list_stream.rs":"6ec99cee760afa323502fde6a07f0314d994c4fcae7170a6ea18dfe4be7ab628","src/linux/minidump_writer/mod.rs":"bb499964bd00a29bf2aac36730a538fb14ce475661af6f0a8f7d4fe68b639122","src/linux/minidump_writer/systeminfo_stream.rs":"624ac20115deb730c4f411f61db0910320631869f40d0fd774cb60919c70a3d0","src/linux/minidump_writer/thread_list_stream.rs":"4d3435c96ff5c7b4dbaa5105a78f0cc4f57a3f7216e9ea0c2d019c64b9771587","src/linux/minidump_writer/thread_names_stream.rs":"d5cc4e6e009628805ad32b6762acf94657c9873e9579ecb01fb0f5b2319e5508","src/linux/mod.rs":"d78a4e7113ec43b4ec6f0d9ab7260218b91ec0619c31306dd538ddf29778eafa","src/linux/module_list.rs":"4e6bef375597dcc8d587a9d0bdfa5f8347faf059eed111cdef7231a3091c81fd","src/linux/module_reader.rs":"3108b33057054f2995adc30f82049d6f43e64c178fc56da757df61b18197c21e","src/linux/process_inspection/mod.rs":"37d2c22a4f3c208ec05ee1870400f0436216efe3de1cf1504742816a3c9367ee","src/linux/process_inspection/process_reader.rs":"560c021a0ba7fb90726a758eb88e998f3cedb5ed860d4dcff242a7b48757e95e","src/linux/serializers.rs":"2ceb04935be0576c282095b3e9e9b656a2adfcf0feef4e046d9c8828b1fe1e38","src/linux/thread_info/aarch64.rs":"3615b3556df3c48df9fe69735bcfc18f60bc4535842aa0efb74d5d45ce9b55d3","src/linux/thread_info/arm.rs":"9e31ac0dac59de2d208ae3ed83ece15d0cf7819b60213195dbc7e04e7ff22fb2","src/linux/thread_info/mod.rs":"e0a9b17cce5b6d34554baade2a0372699b50d27bdce49a53cb545a8a35d29726","src/linux/thread_info/x86.rs":"b0f7391a7e819a51c11d6c807f6f9839e0f17e4aaeafb5fd86d2e12ab67937fc","src/mac/errors.rs":"6ad50e4da9e5df8b0e9b471086c40c8e5f22ca1d1269a12b5d9cdacd35a07066","src/mac/mach.rs":"7909afc83a2c0c682f876a93dc7d2a2a768d9acb8d03c038098146e2f2403a96","src/mac/minidump_writer.rs":"5cc9e83042df41488792c86eaecd311d1bd1ea2990bee990028837f512874166","src/mac/mod.rs":"304094bad42d894f34cc7b792ed59122d98579ffea0e40c31cbc84363df686e0","src/mac/module_reader.rs":"f75841afb2e2cd53d9380869889905e9aceafce0acbff2acf731797f81fa77d1","src/mac/process_reader.rs":"41bc958342a82711c6975377c6591e7645bab2e974b12d832320effb09a50b44","src/mac/streams/breakpad_info.rs":"3971ef91bd0d20fbe34ef3d0138d30dc1e34605c953fb2fd8bf623b7deb9586d","src/mac/streams/exception.rs":"8d2ba0944d531c210254cc0c3743c784db2a5fdeeb3e8028218c462ebb2cf93a","src/mac/streams/memory_list.rs":"89ac051f9cbae28e2ddcda65563772e0f6fcd33b2248a59cb6029be740ac097b","src/mac/streams/misc_info.rs":"22839b0ec1fc1c151831e186793521f1db4c4f237ad8997d844b66ee4743da56","src/mac/streams/mod.rs":"6f650ce6e8141061fbae6446d67951e3acc19f7fb401cb9fddba8296ac85e657","src/mac/streams/module_list.rs":"2cc4a29cf0a68a46decc11c3f1539221e736dc87be2f1be7e5d874657228f511","src/mac/streams/system_info.rs":"8032a05568b5bc0a40d61a3353d4fb7b4e567253977e805622d8454cf41e246e","src/mac/streams/thread_list.rs":"0931c4640b657dbfa537f21823300d98a12b5b61553ed19d26331104a6cb9bb7","src/mac/streams/thread_names.rs":"881574c8deda6cbeac039efbbbb9682cd7fa98ff8710aba3ee0c6a218f372c48","src/mac/task_dumper.rs":"69b24681cf9ba2ffeb91ba82a6fbad329510d6814711785beff9b799381ef346","src/mem_writer.rs":"49995b0fca6cc48a8bf47dc8d738d5ee5afbcedea926b0dcba331e6a2b976eb9","src/minidump_cpu.rs":"428bad960ec2319235ca4959d011a1603754ba86c8a565044ac2e77fb157c815","src/minidump_format.rs":"2f96a0efc6b52b1d8af6f0281f6153f4f5f1bcb1816c1c8398cf030613cfcea9","src/module_reader.rs":"29caae7dd615fb542bad368a90fa72cf666da2832eea0980d792b241071c8b07","src/process_reader.rs":"bcd935fada0e449eea2ac6378b985f722f025b497f71df4a19652c72c810e6eb","src/serializers.rs":"aa5713c1739a87eb3cdc21f88d2da5c266ac83e18125f3f4b531badf5d32dec2","src/windows/errors.rs":"9b8752122784417ed48b9c3fccc9bdabc6c4e6285cdb77c79723cba56cb0de82","src/windows/ffi.rs":"784eff570da0668d4fe5671022bb03106db1af71a6fe48cbf62a4f80d3d9b76a","src/windows/minidump_writer.rs":"4e3a2b23dc6701dc74490873fb73d542c4c0dcf5f05b40ad82f38e460c019c82","src/windows/mod.rs":"d40550a4cb5a8e99e2bbe281d48e41583be9a8d2398d0f1664bf5a3fcd361ef3","src/windows/module_reader.rs":"929dd6bca70d772294a899f63cf8eb49ae258cb1033e8e292dc1c9768c71acf3","src/windows/process_reader.rs":"162e39188c8f059118a59440e6532369dc2cdeb6d53b6b8582c0b959b5283cf0","tests/common/mod.rs":"86d460c5f5c86a752096d4b1545b2960ea4162defc17a957681d8d4ff638187b","tests/linux_minidump_writer.rs":"8cd7bac754fbd0104eacf6486491845e2f076fb2e7d7ca415ed3854e3a252bec","tests/linux_minidump_writer_soft_error.rs":"b0e88fc8bac7986aff482a73aa120e05569ebc31170203077c6b1a0bc9e343ec","tests/linux_module_reader.rs":"03299789005456d8ee5f185f625ba952acedd2a21dacfa3936b8878f9b25f552","tests/mac_minidump_writer.rs":"195ab8d767417cc5e99b7403f73ca01395e622f5d5e910dee8958c7507378c13","tests/ptrace_dumper.rs":"531382d8c7b4ba38b07d407ef8499da311527541d0f37ff0d816cc1519b0acac","tests/task_dumper.rs":"16af34e70259c00a22f3001e5b2e13c9e990cc07db2722c98ba80e16de686c1d","tests/tiny.elf":"9ccd1d7a8b4d4347f623081ad4a74fade764fa7c8f76495b010bc302fb66e69f","tests/windows_minidump_writer.rs":"bcb0629aa2727f510103a71fd81bfd236d6a31978e00855c92f91d05914ff835"},"package":null} \ No newline at end of file diff --git a/third_party/rust/minidump-writer/.cargo/android-runner.sh b/third_party/rust/minidump-writer/.cargo/android-runner.sh index c1fd439c926d..23b55b85511a 100755 --- a/third_party/rust/minidump-writer/.cargo/android-runner.sh +++ b/third_party/rust/minidump-writer/.cargo/android-runner.sh @@ -3,7 +3,11 @@ BINARY=$1 shift +# Cargo doesn't expose the target triple to the runner, so derive it from the +# binary path (.../target//...). +TARGET=$(printf '%s' "$BINARY" | sed -E 's#(.*/)?target/([^/]+)/.*#\2#') + # Make sure to run the following to copy the test helper binary over. -# cargo run --target x86_64-linux-android --bin test +# cargo run --target "$TARGET" --bin test adb push "$BINARY" "/data/local/$BINARY" -adb shell "chmod 777 /data/local/$BINARY && env TEST_HELPER=/data/local/target/x86_64-linux-android/debug/test /data/local/$BINARY" "$@" +adb shell "chmod 777 /data/local/$BINARY && env RUST_BACKTRACE='$RUST_BACKTRACE' TEST_HELPER=/data/local/target/$TARGET/debug/test /data/local/$BINARY" "$@" diff --git a/third_party/rust/minidump-writer/.cargo/config.toml b/third_party/rust/minidump-writer/.cargo/config.toml index e32d5cfdfa30..a5bdfea5c0bf 100644 --- a/third_party/rust/minidump-writer/.cargo/config.toml +++ b/third_party/rust/minidump-writer/.cargo/config.toml @@ -14,3 +14,9 @@ linker = "x86_64-linux-android30-clang" # By default the linker _doesn't_ generate a build-id, however we want one for our tests. rustflags = ["-C", "link-args=-Wl,--build-id=sha1"] runner = [".cargo/android-runner.sh"] + +[target.aarch64-linux-android] +linker = "aarch64-linux-android30-clang" +# By default the linker _doesn't_ generate a build-id, however we want one for our tests. +rustflags = ["-C", "link-args=-Wl,--build-id=sha1"] +runner = [".cargo/android-runner.sh"] diff --git a/third_party/rust/minidump-writer/.github/CODEOWNERS b/third_party/rust/minidump-writer/.github/CODEOWNERS index f4fd57b22114..96ee8ecc12b5 100644 --- a/third_party/rust/minidump-writer/.github/CODEOWNERS +++ b/third_party/rust/minidump-writer/.github/CODEOWNERS @@ -1 +1 @@ -* @Jake-Shadle @gabrielesvelto +* @gabrielesvelto diff --git a/third_party/rust/minidump-writer/.github/workflows/ci.yml b/third_party/rust/minidump-writer/.github/workflows/ci.yml index cf8e7f7c5b67..3b410280db0f 100644 --- a/third_party/rust/minidump-writer/.github/workflows/ci.yml +++ b/third_party/rust/minidump-writer/.github/workflows/ci.yml @@ -34,6 +34,7 @@ jobs: job: - { os: ubuntu-24.04, target: x86_64-unknown-linux-gnu, release: true } - { os: ubuntu-24.04, target: x86_64-unknown-linux-musl } + - { os: ubuntu-24.04-arm, target: aarch64-unknown-linux-gnu } - { os: windows-2025, target: x86_64-pc-windows-msvc } - { os: macos-15-intel, target: x86_64-apple-darwin } - { os: macos-15, target: aarch64-apple-darwin } @@ -43,10 +44,13 @@ jobs: uses: dtolnay/rust-toolchain@stable with: target: ${{ matrix.job.target }} + components: clippy - name: Fetch run: cargo fetch --target ${{ matrix.job.target }} - name: Build run: cargo test --target ${{ matrix.job.target }} --no-run + - name: Clippy + run: cargo clippy --all-features --all-targets --target ${{ matrix.job.target }} -- -D warnings - name: Test run: cargo test --target ${{ matrix.job.target }} - name: Release test @@ -79,7 +83,6 @@ jobs: matrix: job: - target: i686-unknown-linux-gnu - - target: aarch64-unknown-linux-gnu - target: aarch64-unknown-linux-musl - target: arm-unknown-linux-gnueabi - target: arm-unknown-linux-musleabi @@ -137,6 +140,7 @@ jobs: cargo run --target x86_64-linux-android --bin test -- nop # Build and run tests cargo test --target x86_64-linux-android + cargo clippy --all-features --all-targets --target x86_64-linux-android -- -D warnings deny-check: runs-on: ubuntu-24.04 diff --git a/third_party/rust/minidump-writer/CHANGELOG.md b/third_party/rust/minidump-writer/CHANGELOG.md index 745cbbe61475..f37788b5eb1e 100644 --- a/third_party/rust/minidump-writer/CHANGELOG.md +++ b/third_party/rust/minidump-writer/CHANGELOG.md @@ -8,6 +8,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - ReleaseDate +## [0.13.0] - 2026-07-20 +### Changed +- [PR#174](https://github.com/rust-minidump/minidump-writer/pull/174) and [PR#175](https://github.com/rust-minidump/minidump-writer/pull/175) refactored `src/linux/thread_info`. +- [PR#181](https://github.com/rust-minidump/minidump-writer/pull/181) refactored `src/linux/maps_reader` and `src/linux/module_reader`. +- [PR#185](https://github.com/rust-minidump/minidump-writer/pull/185) refactored the backend functions to use `libc`. +- [PR#186](https://github.com/rust-minidump/minidump-writer/pull/186) removed the `nix` dependency. +- [deb17c2](https://github.com/rust-minidump/minidump-writer/commit/deb17c272daa0a20c9327e42526537910bd97882) updated `crash-context` to 0.8, adding `loongarch64`, `riscv`, and `s390x` support, though none of those targets have an implementation in `minidump-writer` itself as of yet. + +### Fixed +- [PR#188](https://github.com/rust-minidump/minidump-writer/pull/188) fixed the process reader API that was broken by [PR#181](https://github.com/rust-minidump/minidump-writer/pull/181). + +### Added +- [PR#184](https://github.com/rust-minidump/minidump-writer/pull/184) added a `libc` backend. + +### Removed +- [PR#177](https://github.com/rust-minidump/minidump-writer/pull/177) and [PR#178](https://github.com/rust-minidump/minidump-writer/pull/178) removed dead/legacy code. + ## [0.12.0] - 2026-05-07 ### Changed - [PR#169](https://github.com/rust-minidump/minidump-writer/pull/169) updated the crate to edition 2024 and an MSRV of 1.85.0. @@ -186,7 +203,8 @@ 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` -[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/0.12.0...HEAD +[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/0.13.0...HEAD +[0.13.0]: https://github.com/rust-minidump/minidump-writer/compare/0.12.0...0.13.0 [0.12.0]: https://github.com/rust-minidump/minidump-writer/compare/0.11.0...0.12.0 [0.11.0]: https://github.com/rust-minidump/minidump-writer/compare/0.10.2...0.11.0 [0.10.2]: https://github.com/rust-minidump/minidump-writer/compare/0.10.1...0.10.2 diff --git a/third_party/rust/minidump-writer/Cargo.lock b/third_party/rust/minidump-writer/Cargo.lock index f9a4015357fa..59a43810029c 100644 --- a/third_party/rust/minidump-writer/Cargo.lock +++ b/third_party/rust/minidump-writer/Cargo.lock @@ -35,9 +35,9 @@ checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" dependencies = [ "alloc-no-stdlib", ] @@ -50,21 +50,21 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] name = "async-compression" -version = "0.4.37" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d10e4f991a553474232bc0a31799f6d24b034a84c0971d80d2e2f78b2e576e40" +checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac" dependencies = [ "compression-codecs", "compression-core", @@ -75,13 +75,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.89" +version = "0.1.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.2", ] [[package]] @@ -92,9 +92,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "base64" @@ -116,9 +116,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" dependencies = [ "serde_core", ] @@ -146,15 +146,15 @@ dependencies = [ "minidump-common", "nom", "range-map", - "thiserror 2.0.18", + "thiserror 2.0.19", "tracing", ] [[package]] name = "brotli" -version = "8.0.2" +version = "8.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" +checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -163,9 +163,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "5.0.0" +version = "5.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" +checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -182,20 +182,20 @@ dependencies = [ [[package]] name = "bstr" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +checksum = "1f7dc094d718f2e1c1559ad110e27eeaae14a5465d3d56dd6dbd793079fbd530" dependencies = [ "memchr", "regex-automata", - "serde", + "serde_core", ] [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "byteorder" @@ -205,9 +205,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cab" @@ -229,9 +229,9 @@ checksum = "68ccbd3153aa153b2f5eff557537ffce81e4dd6c50ae0eddc41dc8d0c388436f" [[package]] name = "cc" -version = "1.2.53" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755d2fce177175ffca841e9a06afdb2c4ab0f593d53b4dee48147dfaade85932" +checksum = "c89588d05638b5b4594a3348a2d6c20277e43a7f5c5202b05cc56888475a47b8" dependencies = [ "find-msvc-tools", "jobserver", @@ -247,9 +247,20 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + +[[package]] +name = "chacha20" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core", +] [[package]] name = "circular" @@ -259,9 +270,9 @@ checksum = "b0fc239e0f6cb375d2402d48afb92f76f5404fd1df208a41930ec81eda078bea" [[package]] name = "compression-codecs" -version = "0.4.36" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00828ba6fd27b45a448e57dbfe84f1029d4c9f26b368157e9a448a5f49a2ec2a" +checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf" dependencies = [ "brotli", "compression-core", @@ -271,9 +282,9 @@ dependencies = [ [[package]] name = "compression-core" -version = "0.4.31" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75984efb6ed102a0d42db99afb6c1948f0380d1d91808d5529916e6c08b49d8d" +checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" [[package]] name = "console" @@ -322,10 +333,17 @@ dependencies = [ ] [[package]] -name = "crash-context" -version = "0.6.3" +name = "cpufeatures" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031ed29858d90cfdf27fe49fae28028a1f20466db97962fa2f4ea34809aeebf3" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crash-context" +version = "0.8.0" dependencies = [ "cfg-if", "libc", @@ -343,9 +361,9 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" [[package]] name = "crc32fast" @@ -371,18 +389,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -390,27 +408,27 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-queue" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crypto-common" @@ -440,12 +458,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" -dependencies = [ - "powerfmt", -] +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" [[package]] name = "digest" @@ -475,18 +490,18 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -496,7 +511,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80c7fb163d4350f0527285b3e48ee7d4905ebd94a4a78f836408902944fc0f1a" dependencies = [ "anyhow", - "bitflags 2.10.0", + "bitflags 2.13.1", "cab", "crossbeam", "dirs", @@ -517,9 +532,9 @@ dependencies = [ [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "elementtree" @@ -567,7 +582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -602,15 +617,15 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fastrand" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "find-msvc-tools" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "flagset" @@ -620,9 +635,9 @@ checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" [[package]] name = "flate2" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", @@ -670,9 +685,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.31" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "a88cf1f829d945f548cf8fec32c61b1f202b6d93b45848602fc02af4b12ad218" dependencies = [ "futures-channel", "futures-core", @@ -685,9 +700,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" dependencies = [ "futures-core", "futures-sink", @@ -695,15 +710,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458" dependencies = [ "futures-core", "futures-task", @@ -712,38 +727,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" dependencies = [ "futures-channel", "futures-core", @@ -753,7 +768,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -782,15 +796,15 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", - "wasip2", + "rand_core", "wasm-bindgen", ] @@ -850,9 +864,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "hermit-abi" @@ -868,9 +882,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" dependencies = [ "bytes", "itoa", @@ -878,9 +892,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" dependencies = [ "bytes", "http", @@ -888,9 +902,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" dependencies = [ "bytes", "futures-core", @@ -907,9 +921,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.8.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ "atomic-waker", "bytes", @@ -920,7 +934,6 @@ dependencies = [ "httparse", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -928,15 +941,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http", "hyper", "hyper-util", "rustls", - "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", @@ -945,14 +957,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64", "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -969,12 +980,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -982,9 +994,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -995,9 +1007,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -1009,15 +1021,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ "icu_collections", "icu_locale_core", @@ -1029,15 +1041,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -1061,9 +1073,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -1077,12 +1089,12 @@ checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -1098,19 +1110,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" -dependencies = [ - "memchr", - "serde", -] +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "itertools" @@ -1123,17 +1125,17 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jobserver" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.3", "libc", ] @@ -1145,19 +1147,20 @@ checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ - "once_cell", + "cfg-if", + "futures-util", "wasm-bindgen", ] [[package]] name = "leb128" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" +checksum = "c83bff1d572d6b9aeef67ddfc8448e4a3737909cb28e81f97c791b9018703e52" [[package]] name = "libc" @@ -1167,11 +1170,10 @@ checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libredox" -version = "0.1.12" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ - "bitflags 2.10.0", "libc", ] @@ -1193,7 +1195,7 @@ dependencies = [ "memchr", "prost", "prost-derive", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -1202,23 +1204,23 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa8fc7e83909ea3b9e2784591655637d3401f2f16014f9d8d6e23ccd138e665f" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.1", "byteorder", "memchr", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" @@ -1231,9 +1233,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.29" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "lru-slab" @@ -1253,18 +1255,15 @@ dependencies = [ [[package]] name = "lzxd" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b29dffab797218e12e4df08ef5d15ab9efca2504038b1b32b9b32fc844b39c9" +checksum = "c17f346186eccb574ba5581acefc514f0c70a642db4f96e245034a0a158a7168" [[package]] name = "mach2" -version = "0.4.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" -dependencies = [ - "libc", -] +checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" [[package]] name = "macho-unwind-info" @@ -1272,7 +1271,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb4bdc8b0ce69932332cf76d24af69c3a155242af95c226b2ab6c2e371ed1149" dependencies = [ - "thiserror 2.0.18", + "thiserror 2.0.19", "zerocopy", "zerocopy-derive", ] @@ -1285,15 +1284,15 @@ checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "memmap2" -version = "0.9.9" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" dependencies = [ "libc", ] @@ -1313,7 +1312,7 @@ dependencies = [ "prost", "range-map", "scroll 0.12.0", - "thiserror 2.0.18", + "thiserror 2.0.19", "time", "tracing", "uuid", @@ -1325,7 +1324,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e16d10087ae9e375bad7a40e8ef5504bc08e808ccc6019067ff9de42a84570f" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.1", "debugid", "num-derive", "num-traits", @@ -1356,9 +1355,9 @@ dependencies = [ [[package]] name = "minidump-writer" -version = "0.12.0" +version = "0.13.0" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.1", "byteorder", "cfg-if", "crash-context", @@ -1375,6 +1374,7 @@ dependencies = [ "minidump", "minidump-common", "minidump-unwind", + "plain", "process-backend", "procfs-core 0.18.0", "scroll 0.12.0", @@ -1382,7 +1382,7 @@ dependencies = [ "serde_json", "similar-asserts", "tempfile", - "thiserror 2.0.18", + "thiserror 2.0.19", "uuid", ] @@ -1404,9 +1404,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" dependencies = [ "libc", "wasi", @@ -1419,7 +1419,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbeff6bd154a309b2ada5639b2661ca6ae4599b34e8487dc276d2cd637da2d76" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.1", "itoa", ] @@ -1454,9 +1454,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-derive" @@ -1466,7 +1466,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -1501,9 +1501,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "option-ext" @@ -1565,12 +1565,12 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2a2e496e34cd96a1bb26f681e5adb11c98f1e5378e294e60c06c0cf04c526ba" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.1", "elsa", "maybe-owned", "pdb2", "range-collections 0.4.6", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -1591,8 +1591,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97f6fccfd2d9d2df765ca23ff85fe5cc437fb0e6d3e164e4d3cbe09d14780c93" dependencies = [ "arrayvec", - "bitflags 2.10.0", - "thiserror 2.0.18", + "bitflags 2.13.1", + "thiserror 2.0.19", "zerocopy", "zerocopy-derive", ] @@ -1614,21 +1614,15 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plain" @@ -1638,9 +1632,9 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -1651,15 +1645,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "precomputed-hash" version = "0.1.1" @@ -1668,27 +1653,26 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro2" -version = "1.0.105" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "process-backend" -version = "0.0.0" +version = "0.1.0" dependencies = [ "libc", - "log", "process-reader", "serde", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] name = "process-reader" -version = "0.0.0" +version = "0.1.0" dependencies = [ "libc", "serde", @@ -1700,7 +1684,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "239df02d8349b06fc07398a3a1697b06418223b1c7725085e801e7c0fc6a12ec" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.1", "hex", ] @@ -1710,7 +1694,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6401bf7b6af22f78b563665d15a22e9aef27775b79b149a66ca022468a4e405" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.1", "hex", "serde", ] @@ -1735,14 +1719,14 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "quinn" -version = "0.11.9" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" dependencies = [ "bytes", "cfg_aliases", @@ -1752,7 +1736,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.18", + "thiserror 2.0.19", "tokio", "tracing", "web-time", @@ -1760,20 +1744,21 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.14" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" dependencies = [ "bytes", - "getrandom 0.3.4", + "getrandom 0.4.3", "lru-slab", "rand", + "rand_pcg", "ring", "rustc-hash", "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.18", + "thiserror 2.0.19", "tinyvec", "tracing", "web-time", @@ -1781,60 +1766,57 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" dependencies = [ "cfg_aliases", "libc", "once_cell", "socket2", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "quote" -version = "1.0.43" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.3.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.9.4" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", + "chacha20", + "getrandom 0.4.3", "rand_core", ] [[package]] name = "rand_core" -version = "0.9.5" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" dependencies = [ - "getrandom 0.3.4", + "rand_core", ] [[package]] @@ -1881,7 +1863,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.1", ] [[package]] @@ -1892,34 +1874,34 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] name = "ref-cast" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +checksum = "216e8f773d7923bcba9ceb86a86c93cabb3903a11872fc3f138c49630e50b96d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +checksum = "2c9283685feec7d69af75fb0e858d5e7378f33fe4fc699383b2916ab9273e03c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.2", ] [[package]] name = "regex" -version = "1.12.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -1929,9 +1911,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" dependencies = [ "aho-corasick", "memchr", @@ -1940,9 +1922,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" @@ -2001,34 +1983,34 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" +checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.1", "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.36" +version = "0.23.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" +checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138" dependencies = [ "once_cell", "ring", @@ -2040,9 +2022,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" dependencies = [ "web-time", "zeroize", @@ -2061,9 +2043,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "ruzstd" @@ -2076,9 +2058,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "samply-symbols" @@ -2087,7 +2069,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97e73d38bb04a373dba1260af91d4b0010e84cecd92d20b8e9949a910d5b9cbb" dependencies = [ "addr2line", - "bitflags 2.10.0", + "bitflags 2.13.1", "cpp_demangle", "crc32fast", "debugid", @@ -2106,7 +2088,7 @@ dependencies = [ "rustc-demangle", "scala-native-demangle", "srcsrv", - "thiserror 2.0.18", + "thiserror 2.0.19", "uuid", "yoke", "yoke-derive", @@ -2149,20 +2131,20 @@ checksum = "1783eabc414609e28a5ba76aee5ddd52199f7107a0b24c2e9746a1ecc34a683d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -2170,29 +2152,29 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.2", ] [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", @@ -2220,21 +2202,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest", ] [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "simd-adler32" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" [[package]] name = "similar" @@ -2258,21 +2240,21 @@ dependencies = [ [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "smart-default" @@ -2282,17 +2264,17 @@ checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2302,7 +2284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85cd3e3828fb4dd5ba0e7091777edb6c3db3cd2d6fc10547b29b40f6949a29be" dependencies = [ "memchr", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -2338,9 +2320,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "symbolic" -version = "12.18.2" +version = "12.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e832005e6261d508717815bac8e2c096161b33b713a032861b3a13ae4cd60ed" +checksum = "67c7526b00fdc496287b9ff5cd97c172686ae56183c2ed605d0777d28638a318" dependencies = [ "symbolic-cfi", "symbolic-common", @@ -2350,13 +2332,13 @@ dependencies = [ [[package]] name = "symbolic-cfi" -version = "12.18.2" +version = "12.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d7ae026fdd9ac37fa77d956aabb60d8cc306bd4f5a38eafc28ad2a003e14cf" +checksum = "49725178e1bbc274015f78346a29b9d6d7e0c25653bfaa9389f30dc5c58bc66d" dependencies = [ "symbolic-common", "symbolic-debuginfo", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -2373,9 +2355,9 @@ dependencies = [ [[package]] name = "symbolic-debuginfo" -version = "12.18.2" +version = "12.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e74486a57b6787aa1bfb15bf7c33860ca6a99e527f2f235bc5f56903e5eeb10" +checksum = "a2e38e9396ca549244e6da7e3ccbe9bf7650afcdd6e32538f2dc0c77d17ce89b" dependencies = [ "debugid", "elementtree", @@ -2384,6 +2366,7 @@ dependencies = [ "flate2", "gimli 0.32.3", "goblin 0.8.2", + "memchr", "nom", "nom-supreme", "once_cell", @@ -2397,7 +2380,7 @@ dependencies = [ "srcsrv", "symbolic-common", "symbolic-ppdb", - "thiserror 2.0.18", + "thiserror 2.0.19", "wasmparser", "zip", "zstd", @@ -2427,7 +2410,7 @@ dependencies = [ "serde", "serde_json", "symbolic-common", - "thiserror 2.0.18", + "thiserror 2.0.19", "uuid", "watto", ] @@ -2446,15 +2429,26 @@ dependencies = [ "http", "reqwest", "scopeguard", - "thiserror 2.0.18", + "thiserror 2.0.19", "tokio", ] [[package]] name = "syn" -version = "2.0.114" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a207d6d6a2b7fc470b80443726053f18a2481b7e1eee970597051596567987a3" dependencies = [ "proc-macro2", "quote", @@ -2478,20 +2472,20 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "tempfile" -version = "3.24.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2505,11 +2499,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" dependencies = [ - "thiserror-impl 2.0.18", + "thiserror-impl 2.0.19", ] [[package]] @@ -2520,28 +2514,27 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.2", ] [[package]] name = "time" -version = "0.3.47" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244" dependencies = [ "deranged", - "itoa", "num-conv", "powerfmt", "serde_core", @@ -2551,15 +2544,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.27" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" dependencies = [ "num-conv", "time-core", @@ -2567,9 +2560,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -2577,9 +2570,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" dependencies = [ "tinyvec_macros", ] @@ -2592,9 +2585,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.49.0" +version = "1.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "d988bcd52dbe076d3d46903332f58c912b87a2c49b1428419a5845154762ffee" dependencies = [ "bytes", "libc", @@ -2644,25 +2637,25 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "async-compression", - "bitflags 2.10.0", + "bitflags 2.13.1", "bytes", "futures-core", "futures-util", "http", "http-body", "http-body-util", - "iri-string", "pin-project-lite", "tokio", "tokio-util", "tower", "tower-layer", "tower-service", + "url", ] [[package]] @@ -2697,7 +2690,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -2733,21 +2726,21 @@ checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "untrusted" @@ -2775,9 +2768,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.19.0" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" dependencies = [ "js-sys", "wasm-bindgen", @@ -2804,20 +2797,11 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasip2" -version = "1.0.1+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" -dependencies = [ - "wit-bindgen", -] - [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -2828,23 +2812,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.58" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ - "cfg-if", - "futures-util", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2852,22 +2832,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.119", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] @@ -2891,7 +2871,7 @@ version = "0.243.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6d8db401b0528ec316dfbe579e6ab4152d61739cfe076706d2009127970159d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.1", "hashbrown 0.15.5", "indexmap", "semver", @@ -2906,14 +2886,14 @@ checksum = "bfbc1480663d640f8c9f7a1ac70922eea60ac16fea79df883177df3bc7bb8b49" dependencies = [ "hashbrown 0.15.5", "leb128", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] name = "web-sys" -version = "0.3.85" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -2931,9 +2911,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" +checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" dependencies = [ "rustls-pki-types", ] @@ -2959,7 +2939,7 @@ dependencies = [ "samply-symbols", "scopeguard", "symsrv", - "thiserror 2.0.18", + "thiserror 2.0.19", "tokio", "uuid", "yoke", @@ -2978,7 +2958,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -2987,16 +2967,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", + "windows-targets", ] [[package]] @@ -3014,31 +2985,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -3047,113 +3001,59 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - -[[package]] -name = "wit-bindgen" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" - [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -3162,68 +3062,68 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.33" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.33" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -3232,9 +3132,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -3243,13 +3143,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -3268,15 +3168,15 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" +checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5" [[package]] name = "zmij" -version = "1.0.15" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f63c051f4fe3c1509da62131a678643c5b6fbdc9273b2b79d4378ebda003d2" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" [[package]] name = "zopfli" diff --git a/third_party/rust/minidump-writer/Cargo.toml b/third_party/rust/minidump-writer/Cargo.toml index 7df1e68fc810..67d5e827032f 100644 --- a/third_party/rust/minidump-writer/Cargo.toml +++ b/third_party/rust/minidump-writer/Cargo.toml @@ -13,7 +13,7 @@ edition = "2024" rust-version = "1.88.0" name = "minidump-writer" -version = "0.12.0" +version = "0.13.0" authors = ["Martin Sirringhaus"] build = "build.rs" autolib = false @@ -69,14 +69,19 @@ path = "tests/windows_minidump_writer.rs" [dependencies] bitflags = "2.10" -cfg-if = "1.0" -crash-context = "0.6" failspot = "0.2.0" goblin = "0.9.2" minidump-common = "0.26" scroll = "0.12" serde_json = "1.0.116" +[dependencies.cfg-if] +version = "1.0" + +[dependencies.crash-context] +version = "0.8" +path = "crates/crash-context" + [dependencies.error-graph] version = "0.1.1" features = ["serde"] @@ -114,7 +119,12 @@ failspot = "0.2.0" version = "0.1.1" features = ["serde"] +[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies.plain] +version = "0.2.3" +default-features = false + [target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies.process-backend] +version = "0.1.0" path = "crates/linux/process-backend" features = ["testing"] @@ -123,8 +133,8 @@ version = "0.18" features = ["serde1"] default-features = false -[target.'cfg(target_os = "macos")'.dependencies] -mach2 = "0.4" +[target.'cfg(target_os = "macos")'.dependencies.mach2] +version = "0.6" [target.'cfg(target_os = "macos")'.dev-dependencies] similar-asserts = "1.6" @@ -146,11 +156,13 @@ memmap2 = "0.9" [target."cfg(unix)".dependencies.libc] version = "0.2" +default-features = false [workspace] members = [ - "crates/process-reader", + "crates/crash-context", "crates/linux/process-backend", + "crates/process-reader", ] resolver = "3" @@ -162,10 +174,15 @@ edition = "2024" rust-version = "1.88.0" [workspace.dependencies] -libc = "0.2" +cfg-if = "1.0" log = "0.4" +mach2 = "0.6" thiserror = "2.0" +[workspace.dependencies.libc] +version = "0.2" +default-features = false + [workspace.dependencies.serde] version = "1.0.208" features = ["derive"] diff --git a/third_party/rust/minidump-writer/deny.toml b/third_party/rust/minidump-writer/deny.toml index ed97463c016d..860fed11112e 100644 --- a/third_party/rust/minidump-writer/deny.toml +++ b/third_party/rust/minidump-writer/deny.toml @@ -1,12 +1,12 @@ [graph] targets = [ - { triple = "x86_64-unknown-linux-gnu" }, - { triple = "x86_64-unknown-linux-musl" }, - { triple = "x86_64-pc-windows-msvc" }, - { triple = "x86_64-apple-darwin" }, - { triple = "aarch64-apple-darwin" }, - { triple = "aarch64-linux-android" }, - { triple = "x86_64-linux-android" }, + "x86_64-unknown-linux-gnu", + "x86_64-unknown-linux-musl", + "x86_64-pc-windows-msvc", + "x86_64-apple-darwin", + "aarch64-apple-darwin", + "aarch64-linux-android", + "x86_64-linux-android", ] [advisories] @@ -17,6 +17,9 @@ multiple-versions = "deny" deny = [ { crate = "chrono", use-instead = "time", reason = "unneccessary dependency" }, ] +skip = [ + { crate = "syn:2.0", reason = "syn 3.0 was released, but naturally most crates will be on 2.0 for a while" }, +] skip-tree = [] [licenses] diff --git a/third_party/rust/minidump-writer/release.toml b/third_party/rust/minidump-writer/release.toml index 25de3f42d9b5..670427471c5f 100644 --- a/third_party/rust/minidump-writer/release.toml +++ b/third_party/rust/minidump-writer/release.toml @@ -1,6 +1,7 @@ pre-release-commit-message = "Release {{version}}" tag-message = "Release {{version}}" tag-name = "{{version}}" +consolidate-commits = false pre-release-replacements = [ { file = "CHANGELOG.md", search = "Unreleased", replace = "{{version}}" }, { file = "CHANGELOG.md", search = "\\.\\.\\.HEAD", replace = "...{{tag_name}}" }, diff --git a/third_party/rust/minidump-writer/src/bin/test.rs b/third_party/rust/minidump-writer/src/bin/test.rs index 4e6bb687569c..36721d3d6d94 100644 --- a/third_party/rust/minidump-writer/src/bin/test.rs +++ b/third_party/rust/minidump-writer/src/bin/test.rs @@ -10,7 +10,7 @@ mod linux { super::*, error_graph::ErrorList, minidump_writer::{ - LINUX_GATE_LIBRARY_NAME, + LINUX_GATE_LIBRARY_NAME, ProcessReaderKind, minidump_writer::{MinidumpWriter, MinidumpWriterConfig}, }, std::ptr, @@ -73,7 +73,7 @@ mod linux { use minidump_writer::process_reader::ProcessReader; let ppid = getppid(); - let dumper = fail_on_soft_error!( + let mut dumper = fail_on_soft_error!( soft_errors, MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)? ); @@ -99,25 +99,41 @@ mod linux { // virtual mem { - validate(ProcessReader::for_virtual_mem(&dumper.process_inspector)) + dumper + .process_inspector + .force_process_reader_kind(ProcessReaderKind::VirtualMem) + .unwrap(); + validate(dumper.process_inspector.process_reader()) .map_err(|err| format!("failed to validate memory: {err}"))?; } // file { - let reader = ProcessReader::for_file(&dumper.process_inspector) - .map_err(|err| format!("failed to open `/proc/{ppid}/mem`: {err}"))?; - validate(reader).map_err(|err| format!("failed to validate memory: {err}"))?; + dumper + .process_inspector + .force_process_reader_kind(ProcessReaderKind::File) + .unwrap(); + validate(dumper.process_inspector.process_reader()) + .map_err(|err| format!("failed to validate memory: {err}"))?; } // ptrace { - validate(ProcessReader::for_ptrace(&dumper.process_inspector)) + dumper + .process_inspector + .force_process_reader_kind(ProcessReaderKind::Ptrace) + .unwrap(); + validate(dumper.process_inspector.process_reader()) .map_err(|err| format!("failed to validate memory: {err}"))?; } + dumper + .process_inspector + .force_process_reader_kind(ProcessReaderKind::Unspecified) + .unwrap(); + let stack_res = MinidumpWriter::copy_from_process( - &dumper.process_inspector, + dumper.process_inspector.as_ref(), stack_var, std::mem::size_of::(), )?; @@ -125,7 +141,7 @@ mod linux { test!(stack_res == expected_stack, "stack var not correct"); let heap_res = MinidumpWriter::copy_from_process( - &dumper.process_inspector, + dumper.process_inspector.as_ref(), heap_var, std::mem::size_of::(), )?; @@ -161,20 +177,17 @@ mod linux { let exe_link = format!("/proc/{ppid}/exe"); let exe_name = std::fs::read_link(exe_link)?.into_os_string(); - let mut dumper = fail_on_soft_error!( + let dumper = fail_on_soft_error!( soft_errors, MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)? ); - 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) { - found_exe = Some(idx); - break; - } - } - let idx = found_exe.unwrap(); - let id = dumper.build_id_from_process_memory_for_index(idx)?; + let exe_mapping = dumper + .mappings + .iter() + .find(|mapping| mapping.name.as_ref().map(|x| x.into()).as_ref() == Some(&exe_name)) + .unwrap(); + let id = dumper.build_id_from_process_memory(exe_mapping.start_address)?; drop(dumper); @@ -210,24 +223,19 @@ mod linux { fn test_linux_gate_mapping_id() -> Result<()> { let ppid = getppid(); - let mut dumper = fail_on_soft_error!( + let dumper = fail_on_soft_error!( soft_errors, MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)? ); - let mut found_linux_gate = false; - for idx in 0..dumper.mappings.len() { - if dumper.mappings[idx].name == Some(LINUX_GATE_LIBRARY_NAME.into()) { - found_linux_gate = true; + let linux_gate = dumper + .mappings + .iter() + .find(|mapping| mapping.name == Some(LINUX_GATE_LIBRARY_NAME.into())); + test!(linux_gate.is_some(), "found no linux_gate"); - let id = dumper.build_id_from_process_memory_for_index(idx)?; - - test!(!id.is_empty(), "id-vec is empty"); - test!(id.iter().any(|&x| x > 0), "all id elements are 0"); - drop(dumper); - break; - } - } - test!(found_linux_gate, "found no linux_gate"); + let id = dumper.build_id_from_process_memory(linux_gate.unwrap().start_address)?; + test!(!id.is_empty(), "id-vec is empty"); + test!(id.iter().any(|&x| x > 0), "all id elements are 0"); Ok(()) } @@ -492,7 +500,7 @@ mod mac { #[inline(never)] pub(super) fn real_main(args: Vec) -> Result<()> { - let port_name = args.get(0).ok_or("mach port name not specified")?; + let port_name = args.first().ok_or("mach port name not specified")?; let exception: u32 = args.get(1).ok_or("exception code not specified")?.parse()?; let client = diff --git a/third_party/rust/minidump-writer/src/lib.rs b/third_party/rust/minidump-writer/src/lib.rs index f941625f1f86..9337b4cbf38c 100644 --- a/third_party/rust/minidump-writer/src/lib.rs +++ b/third_party/rust/minidump-writer/src/lib.rs @@ -9,6 +9,9 @@ cfg_if::cfg_if! { ThreadName, SuspendThreads, CpuInfoFileOpen, + StackPointerMapping, + ThreadStackCopy, + CrashingThreadIpCopy, } } @@ -32,3 +35,6 @@ pub mod module_reader; pub mod process_reader; mod serializers; + +/// Re-export of crash-context +pub use ::crash_context; diff --git a/third_party/rust/minidump-writer/src/linux/android.rs b/third_party/rust/minidump-writer/src/linux/android.rs index 2d9e70d5a8cd..c212689f9c88 100644 --- a/third_party/rust/minidump-writer/src/linux/android.rs +++ b/third_party/rust/minidump-writer/src/linux/android.rs @@ -1,7 +1,7 @@ use { super::{ - maps_reader::MappingInfo, minidump_writer::MinidumpWriter, - process_inspection::ProcessInspector, process_reader::CopyFromProcessError, + minidump_writer::MinidumpWriter, process_inspection::ProcessInspector, + process_reader::CopyFromProcessError, }, goblin::elf, }; @@ -49,7 +49,7 @@ struct DynVaddresses { } fn has_android_packed_relocations( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, load_bias: usize, vaddrs: DynVaddresses, ) -> Result<()> { @@ -71,7 +71,7 @@ fn has_android_packed_relocations( } fn get_effective_load_bias( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, ehdr: &elf_header::Header, address: usize, ) -> usize { @@ -91,7 +91,7 @@ fn get_effective_load_bias( } fn parse_loaded_elf_program_headers( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, ehdr: &elf_header::Header, address: usize, ) -> DynVaddresses { @@ -130,38 +130,26 @@ fn parse_loaded_elf_program_headers( } } -pub fn late_process_mappings( - process_inspector: &ProcessInspector, - mappings: &mut [MappingInfo], -) -> Result<()> { - // Only consider exec mappings that indicate a file path was mapped, and - // where the ELF header indicates a mapped shared library. - for map in mappings - .iter_mut() - .filter(|m| m.is_executable() && m.name_is_path()) - { - let ehdr_opt = MinidumpWriter::copy_from_process( - process_inspector, - map.start_address, - elf_header::SIZEOF_EHDR, - ) - .ok() - .and_then(|x| elf_header::Header::parse(&x).ok()); +/// Compute the effective load base of the ELF library pointed at by `elf_header_addr`. +/// In most cases it would be the same as that address, but libraries that use +/// Android packed relocations might need some tweaking. +pub fn effective_load_base( + process_inspector: &dyn ProcessInspector, + elf_header_addr: usize, +) -> usize { + let ehdr = MinidumpWriter::copy_from_process( + process_inspector, + elf_header_addr, + elf_header::SIZEOF_EHDR, + ) + .ok() + .and_then(|v| elf_header::Header::parse(&v).ok()); - if let Some(ehdr) = ehdr_opt { - if ehdr.e_type == elf_header::ET_DYN { - // Compute the effective load bias for this mapped library, and update - // the mapping to hold that rather than |start_addr|, at the same time - // adjusting |size| to account for the change in |start_addr|. Where - // the library does not contain Android packed relocations, - // GetEffectiveLoadBias() returns |start_addr| and the mapping entry - // is not changed. - let load_bias = - get_effective_load_bias(process_inspector, &ehdr, map.start_address); - map.size += map.start_address - load_bias; - map.start_address = load_bias; - } + match ehdr { + // Only a relocatable object can have been packed. + Some(ehdr) if ehdr.e_type == elf_header::ET_DYN => { + get_effective_load_bias(process_inspector, &ehdr, elf_header_addr) } + _ => elf_header_addr, } - Ok(()) } diff --git a/third_party/rust/minidump-writer/src/linux/auxv/mod.rs b/third_party/rust/minidump-writer/src/linux/auxv/mod.rs index 9eb0a897283d..a9d5d0708fe6 100644 --- a/third_party/rust/minidump-writer/src/linux/auxv/mod.rs +++ b/third_party/rust/minidump-writer/src/linux/auxv/mod.rs @@ -87,7 +87,7 @@ pub struct AuxvDumpInfo { impl AuxvDumpInfo { pub fn try_filling_missing_info( &mut self, - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, pid: Pid, mut soft_errors: impl WriteErrorList, ) -> Result<(), AuxvError> { @@ -97,7 +97,7 @@ impl AuxvDumpInfo { let auxv_path = format!("/proc/{pid}/auxv"); let auxv_file = process_inspector - .read_file(&auxv_path) + .read_file(auxv_path.clone().into()) .map_err(|e| AuxvError::OpenError(auxv_path, e))?; for pair_result in ProcfsAuxvIter::new(BufReader::new(auxv_file)) { diff --git a/third_party/rust/minidump-writer/src/linux/crash_context/aarch64.rs b/third_party/rust/minidump-writer/src/linux/crash_context_ext/aarch64.rs similarity index 77% rename from third_party/rust/minidump-writer/src/linux/crash_context/aarch64.rs rename to third_party/rust/minidump-writer/src/linux/crash_context_ext/aarch64.rs index 753a30dc84b0..c836a8866546 100644 --- a/third_party/rust/minidump-writer/src/linux/crash_context/aarch64.rs +++ b/third_party/rust/minidump-writer/src/linux/crash_context_ext/aarch64.rs @@ -1,12 +1,9 @@ -use { - super::CrashContext, - crate::{ - minidump_cpu::{FP_REG_COUNT, GP_REG_COUNT, RawContextCPU}, - minidump_format::format, - }, +use crate::{ + minidump_cpu::{FP_REG_COUNT, GP_REG_COUNT}, + minidump_format::format, }; -impl CrashContext { +impl super::CrashContextExt { pub fn get_instruction_pointer(&self) -> usize { self.inner.context.uc_mcontext.pc as usize } @@ -15,7 +12,7 @@ impl CrashContext { self.inner.context.uc_mcontext.sp as usize } - pub fn fill_cpu_context(&self, out: &mut RawContextCPU) { + pub fn fill_cpu_context(&self, out: &mut super::RawContextCPU) { out.context_flags = format::ContextFlagsArm64Old::CONTEXT_ARM64_OLD_FULL.bits() as u64; { diff --git a/third_party/rust/minidump-writer/src/linux/crash_context/arm.rs b/third_party/rust/minidump-writer/src/linux/crash_context_ext/arm.rs similarity index 90% rename from third_party/rust/minidump-writer/src/linux/crash_context/arm.rs rename to third_party/rust/minidump-writer/src/linux/crash_context_ext/arm.rs index 7cf830a71bdb..b07e38522074 100644 --- a/third_party/rust/minidump-writer/src/linux/crash_context/arm.rs +++ b/third_party/rust/minidump-writer/src/linux/crash_context_ext/arm.rs @@ -1,6 +1,4 @@ -use {super::CrashContext, crate::minidump_cpu::RawContextCPU}; - -impl CrashContext { +impl super::CrashContextExt { pub fn get_instruction_pointer(&self) -> usize { self.inner.context.uc_mcontext.arm_pc as usize } @@ -9,7 +7,7 @@ impl CrashContext { self.inner.context.uc_mcontext.arm_sp as usize } - pub fn fill_cpu_context(&self, out: &mut RawContextCPU) { + pub fn fill_cpu_context(&self, out: &mut super::RawContextCPU) { out.context_flags = crate::minidump_format::format::ContextFlagsArm::CONTEXT_ARM_FULL.bits(); diff --git a/third_party/rust/minidump-writer/src/linux/crash_context/mod.rs b/third_party/rust/minidump-writer/src/linux/crash_context_ext/mod.rs similarity index 83% rename from third_party/rust/minidump-writer/src/linux/crash_context/mod.rs rename to third_party/rust/minidump-writer/src/linux/crash_context_ext/mod.rs index 185ad769578a..dac52d712d0d 100644 --- a/third_party/rust/minidump-writer/src/linux/crash_context/mod.rs +++ b/third_party/rust/minidump-writer/src/linux/crash_context_ext/mod.rs @@ -2,13 +2,13 @@ //! structures which we get from the kernel. These are platform specific //! functions to juggle the `ucontext_t` and user structures into minidump format. -pub struct CrashContext { +pub struct CrashContextExt { pub inner: crash_context::CrashContext, } -impl std::fmt::Debug for CrashContext { +impl std::fmt::Debug for CrashContextExt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("CrashContext") + f.debug_struct("CrashContextExt") .field("siginfo", &self.inner.siginfo) .field("pid", &self.inner.pid) .field("tid", &self.inner.tid) @@ -16,6 +16,8 @@ impl std::fmt::Debug for CrashContext { } } +use crate::minidump_cpu::RawContextCPU; + cfg_if::cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; diff --git a/third_party/rust/minidump-writer/src/linux/crash_context/x86.rs b/third_party/rust/minidump-writer/src/linux/crash_context_ext/x86.rs similarity index 92% rename from third_party/rust/minidump-writer/src/linux/crash_context/x86.rs rename to third_party/rust/minidump-writer/src/linux/crash_context_ext/x86.rs index d8fb332265d1..4c7987c8050f 100644 --- a/third_party/rust/minidump-writer/src/linux/crash_context/x86.rs +++ b/third_party/rust/minidump-writer/src/linux/crash_context_ext/x86.rs @@ -1,12 +1,11 @@ use { - super::CrashContext, - crate::{minidump_cpu::RawContextCPU, minidump_format::format::ContextFlagsX86}, + crate::minidump_format::format::ContextFlagsX86, libc::{ REG_CS, REG_DS, REG_EAX, REG_EBP, REG_EBX, REG_ECX, REG_EDI, REG_EDX, REG_EFL, REG_EIP, REG_ES, REG_ESI, REG_ESP, REG_FS, REG_GS, REG_SS, REG_UESP, }, }; -impl CrashContext { +impl super::CrashContextExt { pub fn get_instruction_pointer(&self) -> usize { self.inner.context.uc_mcontext.gregs[REG_EIP as usize] as usize } @@ -15,7 +14,7 @@ impl CrashContext { self.inner.context.uc_mcontext.gregs[REG_ESP as usize] as usize } - pub fn fill_cpu_context(&self, out: &mut RawContextCPU) { + pub fn fill_cpu_context(&self, out: &mut super::RawContextCPU) { out.context_flags = ContextFlagsX86::CONTEXT_X86_FULL.bits() | ContextFlagsX86::CONTEXT_X86_FLOATING_POINT.bits(); diff --git a/third_party/rust/minidump-writer/src/linux/crash_context/x86_64.rs b/third_party/rust/minidump-writer/src/linux/crash_context_ext/x86_64.rs similarity index 92% rename from third_party/rust/minidump-writer/src/linux/crash_context/x86_64.rs rename to third_party/rust/minidump-writer/src/linux/crash_context_ext/x86_64.rs index 8fc5a66c11f5..30ae9bc35971 100644 --- a/third_party/rust/minidump-writer/src/linux/crash_context/x86_64.rs +++ b/third_party/rust/minidump-writer/src/linux/crash_context_ext/x86_64.rs @@ -1,6 +1,6 @@ use { - super::{super::thread_info::copy_u32_registers, CrashContext}, - crate::{minidump_cpu::RawContextCPU, minidump_format::format}, + super::super::thread_info::copy_u32_registers, + crate::minidump_format::format, libc::{ REG_CSGSFS, REG_EFL, REG_R8, REG_R9, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_RAX, REG_RBP, REG_RBX, REG_RCX, REG_RDI, REG_RDX, REG_RIP, REG_RSI, REG_RSP, @@ -8,7 +8,7 @@ use { scroll::Pwrite, }; -impl CrashContext { +impl super::CrashContextExt { pub fn get_instruction_pointer(&self) -> usize { self.inner.context.uc_mcontext.gregs[REG_RIP as usize] as usize } @@ -17,7 +17,7 @@ impl CrashContext { self.inner.context.uc_mcontext.gregs[REG_RSP as usize] as usize } - pub fn fill_cpu_context(&self, out: &mut RawContextCPU) { + pub fn fill_cpu_context(&self, out: &mut super::RawContextCPU) { out.context_flags = format::ContextFlagsAmd64::CONTEXT_AMD64_FULL.bits(); { diff --git a/third_party/rust/minidump-writer/src/linux/dso_debug.rs b/third_party/rust/minidump-writer/src/linux/dso_debug.rs index 011f61cb19eb..41ad58203df9 100644 --- a/third_party/rust/minidump-writer/src/linux/dso_debug.rs +++ b/third_party/rust/minidump-writer/src/linux/dso_debug.rs @@ -1,3 +1,8 @@ +//! The dynamic linker's debugger rendez-vous. +//! +//! This holds the `` structures the linker publishes for debuggers, and +//! the `MD_LINUX_DSO_DEBUG` stream that is written straight from them. + use { super::{ auxv::AuxvDumpInfo, minidump_writer::MinidumpWriter, process_inspection::ProcessInspector, @@ -9,10 +14,16 @@ use { }, minidump_format::*, }, + plain::Plain, }; type Result = std::result::Result; +#[cfg(not(target_pointer_width = "64"))] +use goblin::elf32 as elf; +#[cfg(target_pointer_width = "64")] +use goblin::elf64 as elf; + cfg_if::cfg_if! { if #[cfg(target_pointer_width = "32")] { use goblin::elf::program_header::program_header32::SIZEOF_PHDR; @@ -49,55 +60,76 @@ pub enum SectionDsoDebugError { ), } -// COPY from +/// Information for a single dynamically loaded module. +/// +/// This structure contains important information about a dynamically-loaded +/// module, like its name and virtual address. It is also a node in a +/// doubly-linked list of such modules. +/// +/// Only the leading members below are part of the protocol with the debugger — +/// the same format used in SVR4. The linker's own fields follow them, and we +/// never read those. +/// +/// #[derive(Debug, Clone, Default)] #[repr(C)] pub struct LinkMap { - /* These first few members are part of the protocol with the debugger. - This is the same format used in SVR4. */ - l_addr: ElfAddr, /* Difference between the address in the ELF - file and the addresses in memory. */ - l_name: usize, /* Absolute file name object was found in. WAS: `char*` */ - l_ld: usize, /* Dynamic section of the shared object. WAS: `ElfW(Dyn) *` */ - l_next: usize, /* Chain of loaded objects. WAS: `struct link_map *` */ - l_prev: usize, /* Chain of loaded objects. WAS: `struct link_map *` */ + /// Difference between the addresses in the ELF file and the addresses in + /// memory. + pub(crate) l_addr: ElfAddr, + /// Address of the absolute file name the object was found in. + /// WAS: `char *` + pub(crate) l_name: usize, + /// Address of the dynamic section of the shared object. + /// WAS: `ElfW(Dyn) *` + pub(crate) l_ld: usize, + /// Address of the next node in the chain of loaded objects. + /// WAS: `struct link_map *` + pub(crate) l_next: usize, + /// Address of the previous node in the chain of loaded objects. + /// WAS: `struct link_map *` + pub(crate) l_prev: usize, } -// COPY from -/// This state value describes the mapping change taking place when -/// the `r_brk' address is called. -#[derive(Debug, Clone, Default)] -#[allow(non_camel_case_types, unused)] -#[repr(C)] -enum RState { - /// Mapping change is complete. - #[default] - RT_CONSISTENT, - /// Beginning to add a new object. - RT_ADD, - /// Beginning to remove an object mapping. - RT_DELETE, -} - -// COPY from +/// Shared object loading information for the debugger. +/// +/// The Linux dynamic linker fills this in and points the main program's +/// `DT_DEBUG` dynamic entry at it. It is known as the "debugger rendez-vous" +/// point and is a legacy structure to assist debuggers in locating loaded +/// shared modules. +/// +/// (But we're going to use it for minidump generation purposes.) +/// +/// #[derive(Debug, Clone, Default)] #[repr(C)] pub struct RDebug { - r_version: libc::c_int, /* Version number for this protocol. */ - r_map: usize, /* Head of the chain of loaded objects. WAS: `struct link_map *` */ - - /* This is the address of a function internal to the run-time linker, - that will always be called when the linker begins to map in a - library or unmap it, and again when the mapping change is complete. - The debugger can set a breakpoint at this address if it wants to - notice shared object mapping changes. */ - r_brk: ElfAddr, - r_state: RState, - r_ldbase: ElfAddr, /* Base address the linker is loaded at. */ + /// Version number for this protocol. + pub(crate) r_version: libc::c_int, + /// Address of the head of the chain of loaded objects. + /// WAS: `struct link_map *` + pub(crate) r_map: usize, + /// Address of a function internal to the run-time linker, that will always + /// be called when the linker begins to map in a library or unmap it, and + /// again when the mapping change is complete. The debugger can set a + /// breakpoint at this address if it wants to notice shared object mapping + /// changes. + pub(crate) r_brk: ElfAddr, + /// Which mapping change is taking place when `r_brk` is called: 0 + /// (`RT_CONSISTENT`, the change is complete), 1 (`RT_ADD`, beginning to add + /// a new object) or 2 (`RT_DELETE`, beginning to remove an object mapping). + pub(crate) r_state: libc::c_int, + /// Base address the linker is loaded at. + pub(crate) r_ldbase: ElfAddr, } +// Safety: both are `repr(C)` aggregates of plain integers, so every bit pattern +// we could read out of the target process is a valid value. +unsafe impl Plain for LinkMap {} +unsafe impl Plain for RDebug {} + pub fn write_dso_debug_stream( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, buffer: &mut Buffer, auxv: &AuxvDumpInfo, ) -> Result { @@ -146,30 +178,24 @@ pub fn write_dso_debug_stream( dyn_addr += base as ElfAddr; - let dyn_size = std::mem::size_of::(); + let dyn_size = std::mem::size_of::(); let mut r_debug = 0usize; let mut dynamic_length = 0usize; + let memory_reader = process_inspector.process_reader(); // The dynamic linker makes information available that helps gdb find all // DSOs loaded into the program. If this information is indeed available, // dump it to a MD_LINUX_DSO_DEBUG stream. loop { - let dyn_data = MinidumpWriter::copy_from_process( - process_inspector, - dyn_addr as usize + dynamic_length, - dyn_size, - )?; + let dyn_struct: elf::dynamic::Dyn = + memory_reader.read_pod(dyn_addr as usize + dynamic_length)?; dynamic_length += dyn_size; - // goblin::elf::Dyn doesn't have padding bytes - let (head, body, _tail) = unsafe { dyn_data.align_to::() }; - assert!(head.is_empty(), "Data was not aligned"); - let dyn_struct = &body[0]; - - let debug_tag = goblin::elf::dynamic::DT_DEBUG; - if dyn_struct.d_tag == debug_tag { + #[allow(clippy::useless_conversion)] + let d_tag = u64::from(dyn_struct.d_tag); + if d_tag == goblin::elf::dynamic::DT_DEBUG { r_debug = dyn_struct.d_val as usize; - } else if dyn_struct.d_tag == goblin::elf::dynamic::DT_NULL { + } else if d_tag == goblin::elf::dynamic::DT_NULL { break; } } @@ -178,38 +204,18 @@ pub fn write_dso_debug_stream( // loaded DSOs. // Our list of DSOs potentially is different from the ones in the crashing // process. So, we have to be careful to never dereference pointers - // directly. Instead, we use CopyFromProcess() everywhere. + // directly. Instead, we copy every node out of the process. // See for a more detailed discussion of the how the dynamic // loader communicates with debuggers. - - let debug_entry_data = MinidumpWriter::copy_from_process( - process_inspector, - r_debug, - std::mem::size_of::(), - )?; - - // goblin::elf::Dyn doesn't have padding bytes - let (head, body, _tail) = unsafe { debug_entry_data.align_to::() }; - assert!(head.is_empty(), "Data was not aligned"); - let debug_entry = &body[0]; + let debug_entry: RDebug = memory_reader.read_pod(r_debug)?; // Count the number of loaded DSOs let mut dso_vec = Vec::new(); let mut curr_map = debug_entry.r_map; while curr_map != 0 { - let link_map_data = MinidumpWriter::copy_from_process( - process_inspector, - curr_map, - std::mem::size_of::(), - )?; - - // LinkMap is repr(C) and doesn't have padding bytes, so this should be safe - let (head, body, _tail) = unsafe { link_map_data.align_to::() }; - assert!(head.is_empty(), "Data was not aligned"); - let map = &body[0]; - + let map: LinkMap = memory_reader.read_pod(curr_map)?; curr_map = map.l_next; - dso_vec.push(map.clone()); + dso_vec.push(map); } let mut linkmap_rva = u32::MAX; diff --git a/third_party/rust/minidump-writer/src/linux/dumper_cpu_info/arm.rs b/third_party/rust/minidump-writer/src/linux/dumper_cpu_info/arm.rs index 1c54b40dddab..3fbcf16bc103 100644 --- a/third_party/rust/minidump-writer/src/linux/dumper_cpu_info/arm.rs +++ b/third_party/rust/minidump-writer/src/linux/dumper_cpu_info/arm.rs @@ -1,6 +1,7 @@ use { super::{CpuInfoError, ProcessInspector}, crate::minidump_format::*, + failspot::failspot, scroll::Pwrite, std::{ collections::HashSet, @@ -135,7 +136,7 @@ fn parse_features(_val: &str) -> u32 { } pub fn write_cpu_information( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, sys_info: &mut MDRawSystemInfo, ) -> Result<()> { // The CPUID value is broken up in several entries in /proc/cpuinfo. @@ -170,12 +171,14 @@ pub fn write_cpu_information( // because the content of /proc/cpuinfo will only mirror the number // of 'online' cores, and thus will vary with time. // See http://www.kernel.org/doc/Documentation/cputopology.txt - if let Ok(mut present_file) = process_inspector.read_file("/sys/devices/system/cpu/present") { + if let Ok(mut present_file) = + process_inspector.read_file("/sys/devices/system/cpu/present".into()) + { // Ignore unparsable content let cpus_present = parse_cpus_from_sysfile(&mut present_file).unwrap_or_default(); if let Ok(mut possible_file) = - process_inspector.read_file("/sys/devices/system/cpu/possible") + process_inspector.read_file("/sys/devices/system/cpu/possible".into()) { // Ignore unparsable content let cpus_possible = parse_cpus_from_sysfile(&mut possible_file).unwrap_or_default(); @@ -191,14 +194,13 @@ pub fn write_cpu_information( // readable from regular Android applications on later versions // (>= 4.1) of the Android platform. - let cpuinfo_file = match process_inspector.read_file("/proc/cpuinfo") { - Ok(x) => x, - Err(_) => { - // Do not return Error here to allow the minidump generation - // to happen properly. - return Ok(()); - } - }; + if failspot!(CpuInfoFileOpen) { + process_inspector.fail_one_syscall_with(libc::EPERM); + } + + let cpuinfo_file = process_inspector + .read_file("/proc/cpuinfo".into()) + .map_err(CpuInfoError::ReadFileError)?; let mut cpuid = 0; let mut elf_hwcaps = 0; @@ -273,10 +275,10 @@ pub fn write_cpu_information( } // Rebuild the ELF hwcaps from the 'Features' field. - if field == "Features" { - if let Some(val) = value { - elf_hwcaps = parse_features(val); - } + if field == "Features" + && let Some(val) = value + { + elf_hwcaps = parse_features(val); } } diff --git a/third_party/rust/minidump-writer/src/linux/dumper_cpu_info/x86.rs b/third_party/rust/minidump-writer/src/linux/dumper_cpu_info/x86.rs index 5bfb678dd33f..27843e7ccae3 100644 --- a/third_party/rust/minidump-writer/src/linux/dumper_cpu_info/x86.rs +++ b/third_party/rust/minidump-writer/src/linux/dumper_cpu_info/x86.rs @@ -24,7 +24,7 @@ impl CpuInfoEntry { } pub fn write_cpu_information( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, sys_info: &mut MDRawSystemInfo, ) -> Result<()> { let vendor_id_name = "vendor_id"; @@ -50,7 +50,7 @@ pub fn write_cpu_information( } let cpuinfo_file = process_inspector - .read_file("/proc/cpuinfo") + .read_file("/proc/cpuinfo".into()) .map_err(CpuInfoError::ReadFileError)?; let mut vendor_id = String::new(); diff --git a/third_party/rust/minidump-writer/src/linux/maps_reader.rs b/third_party/rust/minidump-writer/src/linux/maps_reader.rs index 57986db1bc0a..655a181ed7cd 100644 --- a/third_party/rust/minidump-writer/src/linux/maps_reader.rs +++ b/third_party/rust/minidump-writer/src/linux/maps_reader.rs @@ -15,7 +15,6 @@ use { ffi::{OsStr, OsString}, mem::size_of, os::unix::ffi::{OsStrExt, OsStringExt}, - path::{Path, PathBuf}, }, }; @@ -24,28 +23,12 @@ pub const DELETED_SUFFIX: &[u8] = b" (deleted)"; type Result = std::result::Result; -#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize)] -pub struct SystemMappingInfo { - pub start_address: usize, - pub end_address: usize, -} - // One of these is produced for each mapping in the process (i.e. line in // /proc/$x/maps). #[derive(Debug, PartialEq, Eq, Clone, serde::Serialize)] pub struct MappingInfo { - // On Android, relocation packing can mean that the reported start - // address of the mapping must be adjusted by a bias in order to - // compensate for the compression of the relocation section. The - // following two members hold (after LateInit) the adjusted mapping - // range. See crbug.com/606972 for more information. pub start_address: usize, pub size: usize, - // When Android relocation packing causes |start_addr| and |size| to - // be modified with a load bias, we need to remember the unbiased - // address range. The following structure holds the original mapping - // address range as reported by the operating system. - pub system_mapping_info: SystemMappingInfo, pub offset: usize, // offset into the backed file. pub permissions: MMPermissions, // read, write and execute permissions. pub name: Option, @@ -71,8 +54,6 @@ pub enum MapsReaderError { #[serde(serialize_with = "serialize_goblin_error")] goblin::error::Error, ), - #[error("error reading soname from file")] - ReadSoNameFromFileFailed(#[source] ModuleReaderError), #[error("failed to memory map file")] MemoryMapFileFailed(#[source] ModuleReaderError), #[error("No soname found (filename: {})", .0.to_string_lossy())] @@ -115,13 +96,25 @@ pub enum MapsReaderError { ), } -fn is_mapping_a_path(pathname: Option<&OsStr>) -> bool { +/// Return whether a `/proc//maps` pathname is a path (contains a `/`). +pub(crate) fn name_is_path(pathname: Option<&OsStr>) -> bool { match pathname { Some(x) => x.as_bytes().contains(&b'/'), None => false, } } +/// Quick helper to convert a `/proc//maps` excerpt into mapping data. +#[cfg(test)] +#[cfg(target_pointer_width = "64")] // All tests are 64-bit +pub(crate) fn get_mappings_for(map: &str, linux_gate_loc: u64) -> Vec { + MappingInfo::aggregate( + MemoryMaps::from_read(map.as_bytes()).expect("failed to read mapping info"), + Some(linux_gate_loc), + ) + .unwrap_or_default() +} + /// Sanitize mapped paths. /// /// This removes a ` (deleted)` suffix, if present. @@ -136,13 +129,13 @@ fn sanitize_path(pathname: OsString) -> OsString { impl MappingInfo { /// Get the mappings for the given process. pub fn for_pid( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, pid: i32, linux_gate_loc: Option, ) -> Result> { let maps_path = format!("/proc/{}/maps", pid); let maps_file = process_inspector - .read_file(&maps_path) + .read_file(maps_path.into()) .map_err(MapsReaderError::ReadFileFailed)?; let maps = MemoryMaps::from_read(maps_file)?; Self::aggregate(maps, linux_gate_loc) @@ -150,7 +143,7 @@ impl MappingInfo { /// Return whether the `name` field is a path (contains a `/`). pub fn name_is_path(&self) -> bool { - is_mapping_a_path(self.name.as_deref()) + name_is_path(self.name.as_deref()) } pub fn is_empty_page(&self) -> bool { @@ -186,7 +179,7 @@ impl MappingInfo { MMapPath::Anonymous => None, }; - let is_path = is_mapping_a_path(pathname.as_deref()); + let is_path = name_is_path(pathname.as_deref()); if let Some(linux_gate_loc) = linux_gate_loc.map(|u| usize::try_from(u).unwrap()) && (!is_path && (start_address == linux_gate_loc)) @@ -202,7 +195,6 @@ impl MappingInfo { { // Merge adjacent mappings into one module, assuming they're a single // library mapped by the dynamic linker. - prev_module.system_mapping_info.end_address = end_address; prev_module.size = end_address - prev_module.start_address; prev_module.permissions |= mm.perms; continue; @@ -239,7 +231,6 @@ impl MappingInfo { let prev_prev_module = previous_modules.first_mut().unwrap(); if pathname == prev_prev_module.name { - prev_prev_module.system_mapping_info.end_address = end_address; prev_prev_module.size = end_address - prev_prev_module.start_address; prev_prev_module.permissions |= mm.perms; infos.pop(); @@ -251,10 +242,6 @@ impl MappingInfo { infos.push(MappingInfo { start_address, size: end_address - start_address, - system_mapping_info: SystemMappingInfo { - start_address, - end_address, - }, offset, permissions: mm.perms, name: pathname, @@ -269,8 +256,8 @@ impl MappingInfo { // the stack pointer). Regardless of the alignment of |stack_copy|, // the memory starting at |stack_copy| + |offset| represents an // aligned word in the target process. - let low_addr = self.system_mapping_info.start_address; - let high_addr = self.system_mapping_info.end_address; + let low_addr = self.start_address; + let high_addr = self.start_address + self.size; let mut offset = (sp_offset + size_of::() - 1) & !(size_of::() - 1); while offset <= stack_copy.len() - size_of::() { let addr = match std::mem::size_of::() { @@ -296,73 +283,6 @@ impl MappingInfo { false } - /// Find the shared object name (SONAME) by examining the ELF information - /// for the mapping. - fn so_name(&self, process_inspector: &ProcessInspector) -> Result { - let path = Path::new(self.name.as_deref().unwrap_or_default()); - super::module_reader::read_soname_from_file(process_inspector, path, self.offset) - .map_err(MapsReaderError::ReadSoNameFromFileFailed) - } - - #[inline] - fn so_version(&self) -> Option { - SoVersion::parse(self.name.as_deref()?) - } - - pub fn get_mapping_effective_path_name_and_version( - &self, - process_inspector: &ProcessInspector, - soname: Option, - ) -> Result<(PathBuf, String, Option)> { - let mut file_path = PathBuf::from(self.name.clone().unwrap_or_default()); - - // Tools such as minidump_stackwalk use the name of the module to look up - // symbols produced by dump_syms. dump_syms will prefer to use a module's - // DT_SONAME as the module name, if one exists, and will fall back to the - // filesystem name of the module. - - // Just use the filesystem name if no SONAME is present. - let Some(file_name) = soname.or_else(|| self.so_name(process_inspector).ok()) else { - // file_path := /path/to/libname.so - // file_name := libname.so - let file_name = file_path - .file_name() - .map(|s| s.to_string_lossy().into_owned()) - .unwrap_or_default(); - - return Ok((file_path, file_name, self.so_version())); - }; - - if self.is_executable() && self.offset != 0 { - // If an executable is mapped from a non-zero offset, this is likely because - // the executable was loaded directly from inside an archive file (e.g., an - // apk on Android). - // In this case, we append the file_name to the mapped archive path: - // file_name := libname.so - // file_path := /path/to/ARCHIVE.APK/libname.so - file_path.push(&file_name); - } else { - // Otherwise, replace the basename with the SONAME. - file_path.set_file_name(&file_name); - } - - Ok((file_path, file_name, self.so_version())) - } - - pub fn is_contained_in(&self, user_mapping_list: &MappingList) -> bool { - for user in user_mapping_list { - // Ignore any mappings that are wholly contained within - // mappings in the mapping_info_ list. - if self.start_address >= user.mapping.start_address - && (self.start_address + self.size) - <= (user.mapping.start_address + user.mapping.size) - { - return true; - } - } - false - } - pub fn is_interesting(&self) -> bool { // only want modules with filenames. self.name.is_some() && @@ -374,8 +294,7 @@ impl MappingInfo { } pub fn contains_address(&self, address: usize) -> bool { - self.system_mapping_info.start_address <= address - && address < self.system_mapping_info.end_address + self.start_address <= address && address < self.start_address + self.size } pub fn is_executable(&self) -> bool { @@ -391,110 +310,10 @@ impl MappingInfo { } } -/// Version metadata retrieved from an .so filename -/// -/// There is no standard for .so version numbers so this implementation just -/// does a best effort to pull as much data as it can based on real .so schemes -/// seen -/// -/// That being said, the [libtool](https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html) -/// versioning scheme is fairly common -#[cfg_attr(test, derive(Debug))] -pub struct SoVersion { - /// Might be non-zero if there is at least one non-zero numeric component after .so. - /// - /// Equivalent to `current` in libtool versions - pub major: u32, - /// The numeric component after the major version, if any - /// - /// Equivalent to `revision` in libtool versions - pub minor: u32, - /// The numeric component after the minor version, if any - /// - /// Equivalent to `age` in libtool versions - pub patch: u32, - /// The patch component may contain additional non-numeric metadata similar - /// to a semver prelease, this is any numeric data that suffixes that prerelease - /// string - pub prerelease: u32, -} - -impl SoVersion { - /// Attempts to retrieve the .so version of the elf path via its filename - fn parse(so_path: &OsStr) -> Option { - let filename = std::path::Path::new(so_path).file_name()?; - - // Avoid an allocation unless the string contains non-utf8 - let filename = filename.to_string_lossy(); - - let (_, version) = filename.split_once(".so.")?; - - let mut sov = Self { - major: 0, - minor: 0, - patch: 0, - prerelease: 0, - }; - - let comps = [ - &mut sov.major, - &mut sov.minor, - &mut sov.patch, - &mut sov.prerelease, - ]; - - for (i, comp) in version.split('.').enumerate() { - if i <= 1 { - *comps[i] = comp.parse().unwrap_or_default(); - } else if i >= 4 { - break; - } else { - // In some cases the release/patch version is alphanumeric (eg. '2rc5'), - // so try to parse either a single or two numbers - if let Some(pend) = comp.find(|c: char| !c.is_ascii_digit()) { - if let Ok(patch) = comp[..pend].parse() { - *comps[i] = patch; - } - - if i >= comps.len() - 1 { - break; - } - if let Some(pre) = comp.rfind(|c: char| !c.is_ascii_digit()) - && let Ok(pre) = comp[pre + 1..].parse() - { - *comps[i + 1] = pre; - break; - } - } else { - *comps[i] = comp.parse().unwrap_or_default(); - } - } - } - - Some(sov) - } -} - -#[cfg(test)] -impl PartialEq<(u32, u32, u32, u32)> for SoVersion { - fn eq(&self, o: &(u32, u32, u32, u32)) -> bool { - self.major == o.0 && self.minor == o.1 && self.patch == o.2 && self.prerelease == o.3 - } -} - #[cfg(test)] #[cfg(target_pointer_width = "64")] // All addresses are 64 bit and I'm currently too lazy to adjust it to work for both mod tests { use super::*; - use procfs_core::FromRead; - - fn get_mappings_for(map: &str, linux_gate_loc: u64) -> Vec { - MappingInfo::aggregate( - MemoryMaps::from_read(map.as_bytes()).expect("failed to read mapping info"), - Some(linux_gate_loc), - ) - .unwrap_or_default() - } const LINES: &str = "\ 5597483fc000-5597483fe000 r--p 00000000 00:31 4750073 /usr/bin/cat @@ -559,10 +378,6 @@ ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsysca let cat_map = MappingInfo { start_address: 0x5597483fc000, size: 40960, - system_mapping_info: SystemMappingInfo { - start_address: 0x5597483fc000, - end_address: 0x559748406000, - }, offset: 0, permissions: MMPermissions::READ | MMPermissions::WRITE @@ -576,10 +391,6 @@ ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsysca let heap_map = MappingInfo { start_address: 0x559749b0e000, size: 135168, - system_mapping_info: SystemMappingInfo { - start_address: 0x559749b0e000, - end_address: 0x559749b2f000, - }, offset: 0, permissions: MMPermissions::READ | MMPermissions::WRITE | MMPermissions::PRIVATE, name: Some("[heap]".into()), @@ -590,10 +401,6 @@ ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsysca let empty_map = MappingInfo { start_address: 0x7efd968d3000, size: 139264, - system_mapping_info: SystemMappingInfo { - start_address: 0x7efd968d3000, - end_address: 0x7efd968f5000, - }, offset: 0, permissions: MMPermissions::READ | MMPermissions::WRITE | MMPermissions::PRIVATE, name: None, @@ -609,10 +416,6 @@ ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsysca let gate_map = MappingInfo { start_address: 0x7ffc6e0f7000, size: 8192, - system_mapping_info: SystemMappingInfo { - start_address: 0x7ffc6e0f7000, - end_address: 0x7ffc6e0f9000, - }, offset: 0, permissions: MMPermissions::READ | MMPermissions::EXECUTE | MMPermissions::PRIVATE, name: Some("linux-gate.so".into()), @@ -669,10 +472,6 @@ ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsysca let gate_map = MappingInfo { start_address: 0x7efd96bc4000, size: 1892352, // Merged the anonymous area after in this mapping, so its bigger.. - system_mapping_info: SystemMappingInfo { - start_address: 0x7efd96bc4000, - end_address: 0x7efd96d8c000, // ..but this is not visible here - }, offset: 0, permissions: MMPermissions::READ | MMPermissions::WRITE @@ -701,10 +500,6 @@ a4840000-a4873000 rw-p 09021000 08:12 393449 /data/app/org.mozilla.firefox-1 let gate_map = MappingInfo { start_address: 0x9b4a0000, size: 155004928, // Merged the anonymous area after in this mapping, so its bigger.. - system_mapping_info: SystemMappingInfo { - start_address: 0x9b4a0000, - end_address: 0xa4873000, - }, offset: 0, permissions: MMPermissions::READ | MMPermissions::WRITE @@ -716,59 +511,6 @@ a4840000-a4873000 rw-p 09021000 08:12 393449 /data/app/org.mozilla.firefox-1 assert_eq!(mappings[0], gate_map); } - #[test] - fn test_get_mapping_effective_name() { - let mappings = get_mappings_for( - "\ -7f0b97b6f000-7f0b97b70000 r--p 00000000 00:3e 27136458 /home/martin/Documents/mozilla/devel/mozilla-central/obj/widget/gtk/mozgtk/gtk3/libmozgtk.so -7f0b97b70000-7f0b97b71000 r-xp 00000000 00:3e 27136458 /home/martin/Documents/mozilla/devel/mozilla-central/obj/widget/gtk/mozgtk/gtk3/libmozgtk.so -7f0b97b71000-7f0b97b73000 r--p 00000000 00:3e 27136458 /home/martin/Documents/mozilla/devel/mozilla-central/obj/widget/gtk/mozgtk/gtk3/libmozgtk.so -7f0b97b73000-7f0b97b74000 rw-p 00001000 00:3e 27136458 /home/martin/Documents/mozilla/devel/mozilla-central/obj/widget/gtk/mozgtk/gtk3/libmozgtk.so", - 0x7ffe091bf000, - ); - assert_eq!(mappings.len(), 1); - - let process_inspector = ProcessInspector::local(0); - - let (file_path, file_name, _version) = mappings[0] - .get_mapping_effective_path_name_and_version(&process_inspector, 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" - ) - ); - } - - #[test] - fn test_elf_file_so_version() { - #[rustfmt::skip] - let test_cases = [ - ("/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.32", (6, 0, 32, 0)), - ("/usr/lib/x86_64-linux-gnu/libcairo-gobject.so.2.11800.0", (2, 11800, 0, 0)), - ("/usr/lib/x86_64-linux-gnu/libm.so.6", (6, 0, 0, 0)), - ("/usr/lib/x86_64-linux-gnu/libpthread.so.0", (0, 0, 0, 0)), - ("/usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.7800.0", (0, 7800, 0, 0)), - ("/usr/lib/x86_64-linux-gnu/libabsl_time_zone.so.20220623.0.0", (20220623, 0, 0, 0)), - ("/usr/lib/x86_64-linux-gnu/libdbus-1.so.3.34.2rc5", (3, 34, 2, 5)), - ("/usr/lib/x86_64-linux-gnu/libdbus-1.so.3.34.2rc", (3, 34, 2, 0)), - ("/usr/lib/x86_64-linux-gnu/libdbus-1.so.3.34.rc5", (3, 34, 0, 5)), - ("/usr/lib/x86_64-linux-gnu/libtoto.so.AAA", (0, 0, 0, 0)), - ("/usr/lib/x86_64-linux-gnu/libsemver-1.so.1.2.alpha.1", (1, 2, 0, 1)), - ("/usr/lib/x86_64-linux-gnu/libboop.so.1.2.3.4.5", (1, 2, 3, 4)), - ("/usr/lib/x86_64-linux-gnu/libboop.so.1.2.3pre4.5", (1, 2, 3, 4)), - ]; - - assert!(SoVersion::parse(OsStr::new("/home/alex/bin/firefox/libmozsandbox.so")).is_none()); - - for (path, expected) in test_cases { - let actual = SoVersion::parse(OsStr::new(path)).unwrap(); - assert_eq!(actual, expected); - } - } - #[test] fn test_whitespaces_in_name() { let mappings = get_mappings_for( diff --git a/third_party/rust/minidump-writer/src/linux/minidump_writer/app_memory.rs b/third_party/rust/minidump-writer/src/linux/minidump_writer/app_memory.rs index a2f9ba0441c1..163e710a66c9 100644 --- a/third_party/rust/minidump-writer/src/linux/minidump_writer/app_memory.rs +++ b/third_party/rust/minidump-writer/src/linux/minidump_writer/app_memory.rs @@ -5,7 +5,7 @@ impl MinidumpWriter { pub fn write_app_memory(&mut self, buffer: &mut DumpBuf) -> Result<(), CopyFromProcessError> { for app_memory in &self.app_memory { let data_copy = Self::copy_from_process( - &self.process_inspector, + self.process_inspector.as_ref(), app_memory.ptr, app_memory.length, )?; diff --git a/third_party/rust/minidump-writer/src/linux/minidump_writer/errors.rs b/third_party/rust/minidump-writer/src/linux/minidump_writer/errors.rs index 722703ea2bf4..8c2784ecaa99 100644 --- a/third_party/rust/minidump-writer/src/linux/minidump_writer/errors.rs +++ b/third_party/rust/minidump-writer/src/linux/minidump_writer/errors.rs @@ -12,6 +12,7 @@ use { thread_list_stream::SectionThreadListError, thread_names_stream::SectionThreadNamesError, }, + module_list::ModuleResolveError, module_reader::ModuleReaderError, process_inspection, serializers::*, @@ -69,6 +70,10 @@ pub enum WriterError { ResumeThreadsErrors(#[source] ErrorList), #[error("Errors occurred while writing system info")] WriteSystemInfoErrors(#[source] ErrorList), + #[error("Errors occurred while writing the thread list")] + WriteThreadListErrors(#[source] ErrorList), + #[error("Errors occurred while writing the module list")] + WriteModuleListErrors(#[source] ErrorList), #[error("Failed writing cpuinfo")] WriteCpuInfoFailed(#[source] MemoryWriterError), #[error("Failed writing thread proc status")] @@ -170,6 +175,10 @@ pub enum InitError { AggregateMappingsFailed(#[source] MapsReaderError), #[error("Failed to enumerate process mappings")] EnumerateMappingsFailed(#[source] Box), + #[error("Failed to enumerate the process' loaded modules")] + EnumerateModulesFailed(#[source] Box), + #[error("Errors occurred while resolving the module list")] + ResolveModuleListErrors(#[source] ErrorList), #[error("Errors occurred while suspending threads")] SuspendThreadsErrors(#[source] ErrorList), #[error("No threads left to suspend out of {0}")] diff --git a/third_party/rust/minidump-writer/src/linux/minidump_writer/handle_data_stream.rs b/third_party/rust/minidump-writer/src/linux/minidump_writer/handle_data_stream.rs index b715bd11d951..6ab4dfe5d77e 100644 --- a/third_party/rust/minidump-writer/src/linux/minidump_writer/handle_data_stream.rs +++ b/third_party/rust/minidump-writer/src/linux/minidump_writer/handle_data_stream.rs @@ -1,6 +1,6 @@ use { super::*, - crate::{linux::process_inspection, mem_writer::MemoryWriter}, + crate::{linux::process_inspection::ProcessInspector, mem_writer::MemoryWriter}, std::{ ffi::OsStr, mem, @@ -9,14 +9,14 @@ use { }; fn descriptor_from_path( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, buffer: &mut DumpBuf, path: &Path, ) -> Option { let handle = filename_to_fd(path.file_name().unwrap())?; - let realpath = process_inspector.read_link(path).ok()?; + let realpath = process_inspector.read_link(path.into()).ok()?; let path_rva = write_string_to_location(buffer, realpath.to_string_lossy().as_ref()).ok()?; - let stat = process_inspector.stat_file(path).ok()?; + let stat = process_inspector.stat_file(path.into()).ok()?; // TODO: We store the contents of `st_mode` into the `attributes` field, but // we could also store a human-readable string of the file type inside @@ -67,13 +67,13 @@ impl MinidumpWriter { let proc_fd_path = PathBuf::from(format!("/proc/{}/fd", self.process_id)); let proc_fd_iter = self .process_inspector - .read_dir(&proc_fd_path) + .read_dir(proc_fd_path.clone()) .map_err(SectionHandleDataStreamError::ReadDirFailed)?; let descriptors: Vec<_> = proc_fd_iter .filter_map(|filename| filename.ok()) .filter_map(|filename| { let path = proc_fd_path.join(filename); - descriptor_from_path(&self.process_inspector, buffer, &path) + descriptor_from_path(self.process_inspector.as_ref(), buffer, &path) }) .collect(); let number_of_descriptors = descriptors.len() as u32; diff --git a/third_party/rust/minidump-writer/src/linux/minidump_writer/mappings.rs b/third_party/rust/minidump-writer/src/linux/minidump_writer/mappings.rs index d7f9d619599f..db65ea412b4d 100644 --- a/third_party/rust/minidump-writer/src/linux/minidump_writer/mappings.rs +++ b/third_party/rust/minidump-writer/src/linux/minidump_writer/mappings.rs @@ -1,109 +1,121 @@ -use super::{super::maps_reader::MappingInfo, *}; +use { + super::*, + crate::module_list::{ModuleListError, ModuleSource}, + std::ffi::OsString, +}; #[derive(Debug, Error, serde::Serialize)] pub enum SectionMappingsError { #[error("Failed to write to memory")] MemoryWriterError(#[from] MemoryWriterError), - #[error("Failed to get effective path of mapping ({0:?})")] - GetEffectivePathError(MappingInfo, #[source] MapsReaderError), + #[error("Errors occurred while inspecting module {}", .name.to_string_lossy())] + ModuleErrors { + name: OsString, + #[source] + errors: ErrorList, + }, } impl MinidumpWriter { - /// Write information about the mappings in effect. Because we are using the - /// minidump format, the information about the mappings is pretty limited. - /// Because of this, we also include the full, unparsed, /proc/$x/maps file in - /// another stream in the file. + /// Write information about the modules loaded into the process. Because we + /// are using the minidump format, the information about the modules is + /// pretty limited. Because of this, we also include the full, unparsed, + /// /proc/$x/maps file in another stream in the file. pub fn write_mappings( - &mut self, + &self, buffer: &mut DumpBuf, + mut soft_errors: impl WriteErrorList, ) -> Result { - let mut modules = Vec::new(); + let mut raw_modules = Vec::new(); - // First write all the mappings from the dumper - for map_idx in 0..self.mappings.len() { - // If the mapping is uninteresting, or if - // there is caller-provided information about this mapping - // in the user_mapping_list list, skip it + for module in &self.modules { + let module_name = module.name.clone().unwrap_or_default(); - if !self.mappings[map_idx].is_interesting() - || self.mappings[map_idx].is_contained_in(&self.user_mapping_list) - { + let Some((identifier, soname)) = self.get_mod_id_and_soname(module) else { continue; - } - log::debug!("retrieving build id for {:?}", &self.mappings[map_idx]); - let identifier = self - .build_id_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. - let Some(path) = &self.mappings[map_idx].name else { - return Err(e); - }; - - log::debug!("failed to get build id from process memory ({e}), attempting to retrieve from {}", path.display()); - - module_reader::read_build_id_from_file(&self.process_inspector, path.as_ref()).map_err(errors::WriterError::ModuleReaderError) - }) - .unwrap_or_else(|e| { - log::warn!("failed to get build id for mapping: {e}"); - 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; - } - - // 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 = self.soname_from_process_memory_for_index(map_idx).ok(); + }; let module = fill_raw_module( - &self.process_inspector, + self.process_inspector.as_ref(), buffer, - &self.mappings[map_idx], + module, &identifier, soname, + soft_errors.subwriter(|errors| SectionMappingsError::ModuleErrors { + name: module_name, + errors, + }), )?; - modules.push(module); + raw_modules.push(module); } - // Next write all the mappings provided by the caller - for user in &self.user_mapping_list { - // GUID was provided by caller. - let module = fill_raw_module( - &self.process_inspector, - buffer, - &user.mapping, - &user.identifier, - None, - )?; - modules.push(module); - } - - let list_header = MemoryWriter::::alloc_with_val(buffer, modules.len() as u32)?; + let list_header = MemoryWriter::::alloc_with_val(buffer, raw_modules.len() as u32)?; let mut dirent = MDRawDirectory { stream_type: MDStreamType::ModuleListStream as u32, location: list_header.location(), }; - if !modules.is_empty() { - let mapping_list = MemoryArrayWriter::::alloc_from_iter(buffer, modules)?; - dirent.location.data_size += mapping_list.location().data_size; + if !raw_modules.is_empty() { + let module_list = + MemoryArrayWriter::::alloc_from_iter(buffer, raw_modules)?; + dirent.location.data_size += module_list.location().data_size; } Ok(dirent) } + + /// What it says on the tin. Returns None if the module doesn't have identifying data. + fn get_mod_id_and_soname(&self, module: &ModuleInfo) -> Option<(Vec, Option)> { + // User-provided data is presumed to be correct. + if let ModuleSource::User { identifier } = &module.source { + return Some((identifier.clone(), None)); + } + + log::debug!("retrieving build id for {module:?}"); + let identifier = self + .build_id_from_process_memory(module.base_address) + .or_else(|e| { + // If the module 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. + let Some(path) = &module.name else { + return Err(e); + }; + + log::debug!( + "failed to get build id from process memory ({e}), attempting to retrieve from {}", + path.display() + ); + + module_reader::read_build_id_from_file(self.process_inspector.as_ref(), path.as_ref()) + .map_err(errors::WriterError::ModuleReaderError) + }) + .unwrap_or_else(|e| { + log::warn!("failed to get build id for module: {e}"); + Vec::new() + }); + + // If the identifier is all 0, its an uninteresting module (bmc#1676109) + if identifier.is_empty() || identifier.iter().all(|&x| x == 0) { + return None; + } + + // SONAME should always be accessible through program headers alone, so we don't really + // need to fall back to trying to read from the module file. + let soname = self.soname_from_process_memory(module.base_address).ok(); + + Some((identifier, soname)) + } } fn fill_raw_module( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, buffer: &mut DumpBuf, - mapping: &MappingInfo, + module: &ModuleInfo, identifier: &[u8], soname: Option, + soft_errors: impl WriteErrorList, ) -> Result { let cv_record = if identifier.is_empty() { // Just zeroes @@ -124,9 +136,8 @@ fn fill_raw_module( sig_section.location() }; - let (file_path, _, so_version) = mapping - .get_mapping_effective_path_name_and_version(process_inspector, soname) - .map_err(|e| SectionMappingsError::GetEffectivePathError(mapping.clone(), e))?; + let (file_path, _, so_version) = + module.effective_path_name_and_version(process_inspector, soname, soft_errors); let name_header = write_string_to_location(buffer, file_path.to_string_lossy().as_ref())?; let version_info = so_version.map_or(Default::default(), |sov| format::VS_FIXEDFILEINFO { @@ -140,8 +151,8 @@ fn fill_raw_module( }); let raw_module = MDRawModule { - base_of_image: mapping.start_address as u64, - size_of_image: mapping.size as u32, + base_of_image: module.base_address as u64, + size_of_image: module.size as u32, cv_record, module_name_rva: name_header.rva, version_info, diff --git a/third_party/rust/minidump-writer/src/linux/minidump_writer/memory_info_list_stream.rs b/third_party/rust/minidump-writer/src/linux/minidump_writer/memory_info_list_stream.rs index 63fc56a0f632..e9f07855c3c5 100644 --- a/third_party/rust/minidump-writer/src/linux/minidump_writer/memory_info_list_stream.rs +++ b/third_party/rust/minidump-writer/src/linux/minidump_writer/memory_info_list_stream.rs @@ -27,7 +27,7 @@ impl MinidumpWriter { let path = format!("/proc/{}/maps", self.blamed_thread); let reader = self .process_inspector - .read_file(&path) + .read_file(path.into()) .map_err(SectionMemInfoListError::ReadFileFailed)?; let maps = procfs_core::process::MemoryMaps::from_read(reader)?; diff --git a/third_party/rust/minidump-writer/src/linux/minidump_writer/mod.rs b/third_party/rust/minidump-writer/src/linux/minidump_writer/mod.rs index 0177da4437e1..396dfd785f6a 100644 --- a/third_party/rust/minidump-writer/src/linux/minidump_writer/mod.rs +++ b/third_party/rust/minidump-writer/src/linux/minidump_writer/mod.rs @@ -1,12 +1,15 @@ +use crate::module_list::ModuleInfo; + use { super::{ Pid, app_memory::AppMemoryList, auxv::AuxvDumpInfo, - crash_context::CrashContext, + crash_context_ext::CrashContextExt, dso_debug, dumper_cpu_info::CpuInfoError, - maps_reader::{MappingInfo, MappingList, MapsReaderError}, + maps_reader::{MappingInfo, MappingList}, + module_list, process_inspection::{self, ProcessInspector, process_reader::CopyFromProcessError}, serializers::*, thread_info::{ThreadInfo, ThreadInfoError}, @@ -29,14 +32,12 @@ use { }, std::{ io::{Read, Seek, Write}, + path::PathBuf, time::{Duration, Instant}, }, thiserror::Error, }; -#[cfg(target_os = "android")] -use super::android::late_process_mappings; - pub use super::auxv::{AuxvType, DirectAuxvDumpInfo}; pub mod app_memory; @@ -52,7 +53,13 @@ pub mod thread_names_stream; /// The default timeout after a `SIGSTOP` after which minidump writing proceeds /// regardless of the process state -pub const STOP_TIMEOUT: Duration = Duration::from_millis(100); +pub const STOP_TIMEOUT: Duration = if cfg!(target_os = "android") { + // For whatever reason, Android can be terribly slow for stopping processes + // This often leads to our tests failing intermittently + Duration::from_secs(5) +} else { + Duration::from_millis(100) +}; #[cfg(target_pointer_width = "32")] pub const AT_SYSINFO_EHDR: u32 = 33; @@ -71,11 +78,11 @@ pub struct MinidumpWriterConfig { memory_blocks: Vec, principal_mapping: Option, sanitize_stack: bool, - crash_context: Option, + crash_context: Option, crashing_thread_context: CrashingThreadContext, stop_timeout: Duration, direct_auxv_dump_info: Option, - process_inspector: ProcessInspector, + process_inspector: Box, } #[derive(Debug)] @@ -85,6 +92,7 @@ pub struct MinidumpWriter { pub threads: Vec, pub auxv: AuxvDumpInfo, pub mappings: Vec, + pub modules: Vec, pub page_size: usize, pub sanitize_stack: bool, pub minidump_size_limit: Option, @@ -95,10 +103,10 @@ pub struct MinidumpWriter { principal_mapping_address: Option, pub principal_mapping: Option, pub blamed_thread: Pid, - pub crash_context: Option, + pub crash_context: Option, pub app_memory: AppMemoryList, pub memory_blocks: Vec, - pub process_inspector: ProcessInspector, + pub process_inspector: Box, } #[derive(Debug, Clone)] @@ -132,7 +140,7 @@ impl MinidumpWriterConfig { crashing_thread_context: Default::default(), stop_timeout: STOP_TIMEOUT, direct_auxv_dump_info: Default::default(), - process_inspector: ProcessInspector::local(process_id), + process_inspector: process_inspection::local(process_id), } } @@ -156,7 +164,7 @@ impl MinidumpWriterConfig { self } - pub fn set_crash_context(&mut self, crash_context: CrashContext) -> &mut Self { + pub fn set_crash_context(&mut self, crash_context: CrashContextExt) -> &mut Self { self.crash_context = Some(crash_context); self } @@ -193,6 +201,7 @@ impl MinidumpWriterConfig { 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 write(self, destination: &mut (impl Write + Seek)) -> Result, WriterError> { @@ -226,6 +235,7 @@ impl MinidumpWriterConfig { threads: Default::default(), auxv, mappings: Default::default(), + modules: Default::default(), page_size: Default::default(), sanitize_stack: self.sanitize_stack, minidump_size_limit: self.minidump_size_limit, @@ -259,7 +269,7 @@ impl MinidumpWriter { // Even if we completely fail to fill in any additional Auxv info, we can still press // forward. if let Err(e) = self.auxv.try_filling_missing_info( - &self.process_inspector, + self.process_inspector.as_ref(), self.process_id, soft_errors.subwriter(InitError::FillMissingAuxvInfoErrors), ) { @@ -293,14 +303,14 @@ impl MinidumpWriter { soft_errors.push(InitError::SuspendNoThreadsLeft(threads_count)); } - #[cfg(target_os = "android")] - { - late_process_mappings(&self.process_inspector, &mut self.mappings)?; + // The module list is derived from mappings. + if let Err(e) = self.enumerate_modules(&mut soft_errors) { + soft_errors.push(InitError::EnumerateModulesFailed(Box::new(e))); } if self.skip_stacks_if_mapping_unreferenced { if let Some(address) = self.principal_mapping_address { - self.principal_mapping = self.find_mapping_no_bias(address).cloned(); + self.principal_mapping = self.find_mapping(address).cloned(); } if !self.crash_thread_references_principal_mapping() { @@ -345,10 +355,16 @@ impl MinidumpWriter { // we should have a mostly-intact dump dir_section.write_to_file(buffer, None)?; - let dirent = self.write_thread_list_stream(buffer)?; + let dirent = self.write_thread_list_stream( + buffer, + soft_errors.subwriter(WriterError::WriteThreadListErrors), + )?; dir_section.write_to_file(buffer, Some(dirent))?; - let dirent = self.write_mappings(buffer)?; + let dirent = self.write_mappings( + buffer, + soft_errors.subwriter(WriterError::WriteModuleListErrors), + )?; dir_section.write_to_file(buffer, Some(dirent))?; self.write_app_memory(buffer) @@ -362,7 +378,7 @@ impl MinidumpWriter { dir_section.write_to_file(buffer, Some(dirent))?; let dirent = systeminfo_stream::write( - &self.process_inspector, + self.process_inspector.as_ref(), buffer, soft_errors.subwriter(WriterError::WriteSystemInfoErrors), )?; @@ -396,14 +412,14 @@ impl MinidumpWriter { let trunc = proc_root.len(); proc_root.push_str($fname); - file_entry!(res write_file(&self.process_inspector, buffer, &proc_root), $kind, $err); + file_entry!(res write_file(self.process_inspector.as_ref(), buffer, &proc_root), $kind, $err); proc_root.truncate(trunc); }; } file_entry!( - res write_file(&self.process_inspector, buffer, "/proc/cpuinfo"), + res write_file(self.process_inspector.as_ref(), buffer, "/proc/cpuinfo"), LinuxCpuInfo, WriteCpuInfoFailed ); @@ -414,8 +430,8 @@ impl MinidumpWriter { #[cfg(not(target_os = "android"))] { file_entry!( - res write_file(&self.process_inspector, buffer, "/etc/lsb-release") - .or_else(|_| write_file(&self.process_inspector, buffer, "/etc/os-release")), + res write_file(self.process_inspector.as_ref(), buffer, "/etc/lsb-release") + .or_else(|_| write_file(self.process_inspector.as_ref(), buffer, "/etc/os-release")), LinuxLsbRelease, WriteOsReleaseInfoFailed ); @@ -426,14 +442,17 @@ impl MinidumpWriter { file_entry!("auxv", LinuxAuxv, WriteEnvironmentFailed); file_entry!("maps", LinuxMaps, WriteMapsFailed); - let dirent = - match dso_debug::write_dso_debug_stream(&self.process_inspector, buffer, &self.auxv) { - Ok(dirent) => dirent, - Err(e) => { - soft_errors.push(WriterError::WriteDSODebugStreamFailed(e)); - Default::default() - } - }; + let dirent = match dso_debug::write_dso_debug_stream( + self.process_inspector.as_ref(), + buffer, + &self.auxv, + ) { + Ok(dirent) => dirent, + Err(e) => { + soft_errors.push(WriterError::WriteDSODebugStreamFailed(e)); + Default::default() + } + }; dir_section.write_to_file(buffer, Some(dirent))?; file_entry!("limits", MozLinuxLimits, WriteLimitsFailed); @@ -464,34 +483,17 @@ impl MinidumpWriter { } fn crash_thread_references_principal_mapping(&self) -> bool { - if self.crash_context.is_none() || self.principal_mapping.is_none() { + let (Some(crash_context), Some(mapping)) = + (self.crash_context.as_ref(), self.principal_mapping.as_ref()) + else { return false; - } + }; - let low_addr = self - .principal_mapping - .as_ref() - .unwrap() - .system_mapping_info - .start_address; - let high_addr = self - .principal_mapping - .as_ref() - .unwrap() - .system_mapping_info - .end_address; - - let pc = self - .crash_context - .as_ref() - .unwrap() - .get_instruction_pointer(); - let stack_pointer = self.crash_context.as_ref().unwrap().get_stack_pointer(); - - if pc >= low_addr && pc < high_addr { + if mapping.contains_address(crash_context.get_instruction_pointer()) { return true; } + let stack_pointer = crash_context.get_stack_pointer(); let (valid_stack_pointer, stack_len) = match self.get_stack_info(stack_pointer) { Ok(x) => x, Err(_) => { @@ -500,7 +502,7 @@ impl MinidumpWriter { }; let stack_copy = match MinidumpWriter::copy_from_process( - &self.process_inspector, + self.process_inspector.as_ref(), valid_stack_pointer, stack_len, ) { @@ -518,7 +520,10 @@ impl MinidumpWriter { } /// Suspends a thread by attaching to it. - fn suspend_thread(process_inspector: &ProcessInspector, tid: Pid) -> Result<(), WriterError> { + fn suspend_thread( + process_inspector: &dyn ProcessInspector, + tid: Pid, + ) -> Result<(), WriterError> { process_inspector .suspend_thread(tid) .map_err(WriterError::SuspendThreadFailed)?; @@ -556,7 +561,10 @@ impl MinidumpWriter { } /// Resumes a thread by detaching from it. - fn resume_thread(process_inspector: &ProcessInspector, tid: Pid) -> Result<(), WriterError> { + fn resume_thread( + process_inspector: &dyn ProcessInspector, + tid: Pid, + ) -> Result<(), WriterError> { process_inspector .resume_thread(tid) .map_err(WriterError::ResumeThreadFailed) @@ -567,15 +575,15 @@ impl MinidumpWriter { // If the thread either disappeared before we could attach to it, or if // it was part of the seccomp sandbox's trusted code, it is OK to // silently drop it from the minidump. - self.threads.retain( - |x| match Self::suspend_thread(&self.process_inspector, x.tid) { + self.threads.retain(|x| { + match Self::suspend_thread(self.process_inspector.as_ref(), x.tid) { Ok(()) => true, Err(e) => { soft_errors.push(e); false } - }, - ); + } + }); self.threads_suspended = true; @@ -585,7 +593,7 @@ impl MinidumpWriter { fn resume_threads(&mut self, mut soft_errors: impl WriteErrorList) { if self.threads_suspended { for thread in &self.threads { - match Self::resume_thread(&self.process_inspector, thread.tid) { + match Self::resume_thread(self.process_inspector.as_ref(), thread.tid) { Ok(()) => (), Err(e) => { soft_errors.push(e); @@ -600,6 +608,10 @@ impl MinidumpWriter { /// /// This will block waiting for the process to stop until `timeout` has passed. fn stop_process(&mut self, timeout: Duration) -> Result<(), StopProcessError> { + failspot!(if StopProcess { + self.process_inspector.fail_one_syscall_with(libc::EPERM); + }); + self.process_inspector .stop_process() .map_err(StopProcessError::Stop)?; @@ -607,13 +619,13 @@ impl MinidumpWriter { // Something like waitpid for non-child processes would be better, but we have no such // tool, so we poll the status. const POLL_INTERVAL: Duration = Duration::from_millis(1); - let proc_file = format!("/proc/{}/stat", self.process_id); + let proc_file = PathBuf::from(format!("/proc/{}/stat", self.process_id)); let end = Instant::now() + timeout; loop { let stat_file = self .process_inspector - .read_file(&proc_file) + .read_file(proc_file.clone()) .map_err(StopProcessError::ReadFileFailed)?; if let Ok(ProcState::Stopped) = Stat::from_read(stat_file)?.state() { return Ok(()); @@ -646,7 +658,7 @@ impl MinidumpWriter { for file_name in self .process_inspector - .read_dir(&task_path) + .read_dir(task_path.into()) .map_err(InitError::ReadProcTaskFailed)? { let file_name = match file_name { @@ -671,7 +683,7 @@ impl MinidumpWriter { // Read the thread-name (if there is any) let name_result = self .process_inspector - .read_file(format!("/proc/{pid}/task/{tid}/comm")) + .read_file(format!("/proc/{pid}/task/{tid}/comm").into()) .map_err(std::io::Error::other) .and_then(|mut file| { let mut s = String::new(); @@ -702,32 +714,37 @@ impl MinidumpWriter { // See http://www.trilithium.com/johan/2005/08/linux-gate/ for more // information. self.mappings = MappingInfo::for_pid( - &self.process_inspector, + self.process_inspector.as_ref(), self.process_id, self.auxv.get_linux_gate_address(), ) .map_err(InitError::AggregateMappingsFailed)?; - // 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. - if let Some(entry_point_loc) = self - .auxv - .get_entry_address() - .map(|u| usize::try_from(u).unwrap()) - { - // If this module contains the entry-point, and it's not already the first - // one, then we need to make it be first. This is because the minidump - // format assumes the first module is the one that corresponds to the main - // executable (as codified in - // processor/minidump.cc:MinidumpModuleList::GetMainModule()). - if let Some(entry_mapping_idx) = self.mappings.iter().position(|mapping| { - (mapping.start_address..mapping.start_address + mapping.size) - .contains(&entry_point_loc) - }) { - self.mappings.swap(0, entry_mapping_idx); - } - } + Ok(()) + } + + /// Builds the list of loaded modules written to the `ModuleListStream`. + /// Typically, those would be ELF objects loaded by the dynamic linker, but + /// the user can also provide additional modules to be included through + /// the configuration object. + fn enumerate_modules( + &mut self, + mut soft_errors: impl WriteErrorList, + ) -> Result<(), InitError> { + let mut candidates = + module_list::from_mappings(self.process_inspector.as_ref(), &self.mappings); + candidates.append(&mut module_list::from_user_mappings( + &self.user_mapping_list, + )); + + self.modules = module_list::resolve( + candidates, + self.auxv + .get_entry_address() + .map(|u| usize::try_from(u).unwrap()), + soft_errors.subwriter(InitError::ResolveModuleListErrors), + ); + Ok(()) } @@ -735,12 +752,20 @@ impl MinidumpWriter { /// Fill out the |tgid|, |ppid| and |pid| members of |info|. If unavailable, /// these members are set to -1. Returns true if all three members are /// available. - pub fn get_thread_info_by_index(&self, index: usize) -> Result { + pub fn get_thread_info_by_index( + &self, + index: usize, + soft_errors: impl WriteErrorList, + ) -> Result { if index > self.threads.len() { return Err(ThreadInfoError::IndexOutOfBounds(index, self.threads.len())); } - ThreadInfo::create(&self.process_inspector, self.threads[index].tid) + ThreadInfo::create( + self.process_inspector.as_ref(), + self.threads[index].tid, + soft_errors, + ) } // Returns a valid stack pointer and the mapping that contains the stack. @@ -826,7 +851,7 @@ impl MinidumpWriter { let shift = 32 - 11; // let MappingInfo* last_hit_mapping = nullptr; // let MappingInfo* hit_mapping = nullptr; - let stack_mapping = self.find_mapping_no_bias(stack_pointer); + let stack_mapping = self.find_mapping(stack_pointer); let mut last_hit_mapping: Option<&MappingInfo> = None; // The magnitude below which integers are considered to be to be // 'small', and not constitute a PII risk. These are included to @@ -859,11 +884,11 @@ impl MinidumpWriter { for x in &mut stack_copy[0..offset] { *x = 0; } - let mut chunks = stack_copy[offset..].chunks_exact_mut(std::mem::size_of::()); + let (chunks, remainder) = stack_copy[offset..].as_chunks_mut::<{ size_of::() }>(); // Apply sanitization to each complete pointer-aligned word in the // stack. - for sp in &mut chunks { + for sp in chunks { let addr = usize::from_ne_bytes(sp.to_vec().as_slice().try_into()?); let addr_signed = isize::from_ne_bytes(sp.to_vec().as_slice().try_into()?); @@ -884,7 +909,7 @@ impl MinidumpWriter { let test = addr >> shift; if (could_hit_mapping[(test >> 3) & array_mask] & (1 << (test & 7)) != 0) - && let Some(hit_mapping) = self.find_mapping_no_bias(addr) + && let Some(hit_mapping) = self.find_mapping(addr) && hit_mapping.is_executable() { last_hit_mapping = Some(hit_mapping); @@ -894,7 +919,7 @@ impl MinidumpWriter { } // Zero any partial word at the top of the stack, if alignment is // such that that is required. - for sp in chunks.into_remainder() { + for sp in remainder { *sp = 0; } Ok(()) @@ -907,36 +932,25 @@ impl MinidumpWriter { .find(|map| address >= map.start_address && address - map.start_address < map.size) } - // Find the mapping which the given memory address falls in. Uses the - // unadjusted mapping address range from the kernel, rather than the - // biased range. - pub fn find_mapping_no_bias(&self, address: usize) -> Option<&MappingInfo> { - self.mappings.iter().find(|map| { - address >= map.system_mapping_info.start_address - && address < map.system_mapping_info.end_address - }) - } - - pub fn build_id_from_process_memory_for_index( - &mut self, - idx: usize, + /// Reads the build ID out of the ELF object loaded at `start_address`. + pub fn build_id_from_process_memory( + &self, + start_address: usize, ) -> Result, WriterError> { let reader = self.process_inspector.process_reader(); module_reader::read_build_id_from_module(module_reader::ProcessModuleMemoryReader::new( &reader, - self.mappings[idx].start_address, + start_address, )) .map_err(WriterError::ModuleReaderError) } - pub fn soname_from_process_memory_for_index( - &mut self, - idx: usize, - ) -> Result { + /// Reads the `DT_SONAME` out of the ELF object loaded at `start_address`. + pub fn soname_from_process_memory(&self, start_address: usize) -> Result { let reader = self.process_inspector.process_reader(); module_reader::read_soname_from_module(module_reader::ProcessModuleMemoryReader::new( &reader, - self.mappings[idx].start_address, + start_address, )) .map_err(WriterError::ModuleReaderError) } @@ -945,7 +959,7 @@ impl MinidumpWriter { /// allocated copy #[inline] pub fn copy_from_process( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, src: usize, length: usize, ) -> Result, CopyFromProcessError> { @@ -966,12 +980,12 @@ impl Drop for MinidumpWriter { } fn write_file( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, buffer: &mut DumpBuf, filename: &str, ) -> std::result::Result { let content = process_inspector - .read_file(filename) + .read_file(filename.into()) .map_err(std::io::Error::other) .and_then(|mut file| { let mut v = Vec::new(); diff --git a/third_party/rust/minidump-writer/src/linux/minidump_writer/systeminfo_stream.rs b/third_party/rust/minidump-writer/src/linux/minidump_writer/systeminfo_stream.rs index 52cbc7689ace..6d435fc7d6d3 100644 --- a/third_party/rust/minidump-writer/src/linux/minidump_writer/systeminfo_stream.rs +++ b/third_party/rust/minidump-writer/src/linux/minidump_writer/systeminfo_stream.rs @@ -14,7 +14,7 @@ pub enum SectionSystemInfoError { } pub fn write( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, buffer: &mut DumpBuf, mut soft_errors: impl WriteErrorList, ) -> Result { diff --git a/third_party/rust/minidump-writer/src/linux/minidump_writer/thread_list_stream.rs b/third_party/rust/minidump-writer/src/linux/minidump_writer/thread_list_stream.rs index f0160af96916..f0abad742415 100644 --- a/third_party/rust/minidump-writer/src/linux/minidump_writer/thread_list_stream.rs +++ b/third_party/rust/minidump-writer/src/linux/minidump_writer/thread_list_stream.rs @@ -1,4 +1,10 @@ -use {super::*, crate::minidump_cpu::RawContextCPU, std::cmp::min}; +use { + super::*, + crate::minidump_cpu::RawContextCPU, + error_graph::{ErrorList, WriteErrorList}, + failspot::failspot, + std::cmp::min, +}; // The following kLimit* constants are for when minidump_size_limit_ is set // and the minidump size might exceed it. @@ -34,8 +40,12 @@ pub enum SectionThreadListError { ), #[error("Failed to copy memory from process")] CopyFromProcessError(#[source] CopyFromProcessError), + #[error("Failed to locate the stack pointer's memory mapping")] + GetStackInfoFailed(#[source] Box), #[error("Failed to get thread info")] ThreadInfoError(#[from] ThreadInfoError), + #[error("Soft errors occurred getting thread info")] + ThreadInfoSoftErrors(#[source] ErrorList), #[error("Failed to write to memory buffer")] IOError( #[from] @@ -50,6 +60,7 @@ impl MinidumpWriter { pub fn write_thread_list_stream( &mut self, buffer: &mut DumpBuf, + mut soft_errors: impl WriteErrorList, ) -> Result { let num_threads = self.threads.len(); // Memory looks like this: @@ -107,6 +118,7 @@ impl MinidumpWriter { instruction_ptr, stack_pointer, MaxStackLen::None, + &mut soft_errors, )?; // Copy 256 bytes around crashing instruction pointer to minidump. let ip_memory_size: usize = 256; @@ -114,6 +126,12 @@ impl MinidumpWriter { // it's contained within. If it's not in mapped memory, // don't bother trying to write it. for mapping in &self.mappings { + let instruction_ptr = failspot!(if CrashingThreadIpCopy { + // Just use the first mapping since we'll error out anyway + mapping.start_address + mapping.size / 2 + } else { + instruction_ptr + }); if instruction_ptr < mapping.start_address || instruction_ptr >= mapping.start_address + mapping.size { @@ -136,13 +154,22 @@ impl MinidumpWriter { ip_memory_d.memory.data_size = (end_of_range - ip_memory_d.start_of_memory_range) as u32; - let memory_copy = MinidumpWriter::copy_from_process( - &self.process_inspector, - ip_memory_d.start_of_memory_range as _, - ip_memory_d.memory.data_size as usize, - ) - .map_err(SectionThreadListError::CopyFromProcessError)?; - + let ip_copy = failspot!(if CrashingThreadIpCopy { + Err(CopyFromProcessError::InvalidArgument) + } else { + MinidumpWriter::copy_from_process( + self.process_inspector.as_ref(), + ip_memory_d.start_of_memory_range as _, + ip_memory_d.memory.data_size as usize, + ) + }); + let memory_copy = match ip_copy { + Ok(x) => x, + Err(e) => { + soft_errors.push(SectionThreadListError::CopyFromProcessError(e)); + break; + } + }; let mem_section = MemoryArrayWriter::alloc_from_array(buffer, &memory_copy)?; ip_memory_d.memory = mem_section.location(); self.memory_blocks.push(ip_memory_d); @@ -158,7 +185,10 @@ impl MinidumpWriter { self.crashing_thread_context = CrashingThreadContext::CrashContext(cpu_section.location()); } else { - let info = self.get_thread_info_by_index(idx)?; + let info = self.get_thread_info_by_index( + idx, + soft_errors.subwriter(SectionThreadListError::ThreadInfoSoftErrors), + )?; let max_stack_len = if self.minidump_size_limit.is_some() && idx >= LIMIT_BASE_THREAD_COUNT { extra_thread_stack_len @@ -172,6 +202,7 @@ impl MinidumpWriter { instruction_ptr, info.stack_pointer, max_stack_len, + &mut soft_errors, )?; let mut cpu = RawContextCPU::default(); @@ -199,54 +230,74 @@ impl MinidumpWriter { instruction_ptr: usize, stack_ptr: usize, max_stack_len: MaxStackLen, + mut soft_errors: impl WriteErrorList, ) -> Result<(), SectionThreadListError> { thread.stack.start_of_memory_range = stack_ptr.try_into()?; thread.stack.memory.data_size = 0; thread.stack.memory.rva = buffer.position() as u32; - if let Ok((valid_stack_ptr, stack_len)) = self.get_stack_info(stack_ptr) { - let stack_len = if let MaxStackLen::Len(max_stack_len) = max_stack_len { - min(stack_len, max_stack_len) - } else { - stack_len - }; + let stack_info = failspot!(if StackPointerMapping { + Err(WriterError::NoStackPointerMapping) + } else { + self.get_stack_info(stack_ptr) + }); + let (valid_stack_ptr, stack_len) = match stack_info { + Ok(x) => x, + Err(e) => { + soft_errors.push(SectionThreadListError::GetStackInfoFailed(Box::new(e))); + return Ok(()); + } + }; - let mut stack_bytes = MinidumpWriter::copy_from_process( - &self.process_inspector, + let stack_len = if let MaxStackLen::Len(max_stack_len) = max_stack_len { + min(stack_len, max_stack_len) + } else { + stack_len + }; + + let stack_copy = failspot!(if ThreadStackCopy { + Err(CopyFromProcessError::InvalidArgument) + } else { + MinidumpWriter::copy_from_process( + self.process_inspector.as_ref(), valid_stack_ptr, stack_len, ) - .map_err(SectionThreadListError::CopyFromProcessError)?; - let stack_pointer_offset = stack_ptr.saturating_sub(valid_stack_ptr); - if self.skip_stacks_if_mapping_unreferenced { - if let Some(principal_mapping) = &self.principal_mapping { - let low_addr = principal_mapping.system_mapping_info.start_address; - let high_addr = principal_mapping.system_mapping_info.end_address; - if (instruction_ptr < low_addr || instruction_ptr > high_addr) - && !principal_mapping - .stack_has_pointer_to_mapping(&stack_bytes, stack_pointer_offset) - { - return Ok(()); - } - } else { + }); + let mut stack_bytes = match stack_copy { + Ok(x) => x, + Err(e) => { + soft_errors.push(SectionThreadListError::CopyFromProcessError(e)); + return Ok(()); + } + }; + let stack_pointer_offset = stack_ptr.saturating_sub(valid_stack_ptr); + if self.skip_stacks_if_mapping_unreferenced { + if let Some(principal_mapping) = &self.principal_mapping { + if !principal_mapping.contains_address(instruction_ptr) + && !principal_mapping + .stack_has_pointer_to_mapping(&stack_bytes, stack_pointer_offset) + { return Ok(()); } + } else { + return Ok(()); } - - if self.sanitize_stack { - self.sanitize_stack_copy(&mut stack_bytes, stack_ptr, stack_pointer_offset) - .map_err(|e| SectionThreadListError::SanitizeStackCopyFailed(Box::new(e)))?; - } - - let stack_location = MDLocationDescriptor { - data_size: stack_bytes.len() as u32, - rva: buffer.position() as u32, - }; - buffer.write_all(&stack_bytes); - thread.stack.start_of_memory_range = valid_stack_ptr as u64; - thread.stack.memory = stack_location; - self.memory_blocks.push(thread.stack); } + + if self.sanitize_stack { + self.sanitize_stack_copy(&mut stack_bytes, stack_ptr, stack_pointer_offset) + .map_err(|e| SectionThreadListError::SanitizeStackCopyFailed(Box::new(e)))?; + } + + let stack_location = MDLocationDescriptor { + data_size: stack_bytes.len() as u32, + rva: buffer.position() as u32, + }; + buffer.write_all(&stack_bytes); + thread.stack.start_of_memory_range = valid_stack_ptr as u64; + thread.stack.memory = stack_location; + self.memory_blocks.push(thread.stack); Ok(()) } } diff --git a/third_party/rust/minidump-writer/src/linux/mod.rs b/third_party/rust/minidump-writer/src/linux/mod.rs index 1e3293f16e63..ad9470f7e12f 100644 --- a/third_party/rust/minidump-writer/src/linux/mod.rs +++ b/third_party/rust/minidump-writer/src/linux/mod.rs @@ -3,13 +3,14 @@ pub use { maps_reader::LINUX_GATE_LIBRARY_NAME, - process_inspection::{Error as BackendError, process_reader}, + process_inspection::{Error as BackendError, ProcessReaderKind, process_reader}, }; pub mod app_memory; -pub mod crash_context; +mod crash_context_ext; pub mod maps_reader; pub mod minidump_writer; +pub mod module_list; pub mod module_reader; pub mod thread_info; @@ -24,3 +25,4 @@ mod serializers; mod android; pub type Pid = i32; +pub use crash_context_ext::CrashContextExt; diff --git a/third_party/rust/minidump-writer/src/linux/module_list.rs b/third_party/rust/minidump-writer/src/linux/module_list.rs new file mode 100644 index 000000000000..d2dbcd4d6931 --- /dev/null +++ b/third_party/rust/minidump-writer/src/linux/module_list.rs @@ -0,0 +1,536 @@ +//! Enumeration of the ELF modules loaded into the target process. + +use std::{ + ffi::{OsStr, OsString}, + path::{Path, PathBuf}, +}; + +use crate::{ + linux::process_inspection::ProcessInspector, + maps_reader::{MappingEntry, MappingList}, + module_reader::ModuleReaderError, +}; +use error_graph::WriteErrorList; + +use super::maps_reader::MappingInfo; + +#[derive(thiserror::Error, Debug, serde::Serialize)] +pub enum ModuleListError { + #[error("error reading soname from file")] + ReadSoNameFromFileFailed(#[source] ModuleReaderError), +} + +/// Errors that only cost us the accuracy of a single entry of the module list. +#[derive(thiserror::Error, Debug, serde::Serialize)] +pub enum ModuleResolveError { + #[error( + "user-supplied module `{}` starts at {base_address:#x}, where another \ + one already does, so only one of them can be written", + name.to_string_lossy() + )] + DuplicateUserModule { name: OsString, base_address: usize }, + #[error( + "module `{}` at {base_address:#x} was clamped at {clamped_to:#x} while \ + its last executable segment ends at {code_end:#x}", + name.to_string_lossy() + )] + ModuleImageClamped { + name: OsString, + base_address: usize, + code_end: usize, + clamped_to: usize, + }, +} + +/// Where a module's information came from. +#[derive(Debug)] +pub enum ModuleSource { + /// Read out of the process, be it from its memory map or from the dynamic + /// linker's rendez-vous. + Process, + /// Supplied by the user, and taken at face value: they know things about it + /// that we cannot derive, which is why it was supplied in the first place. + User { identifier: Vec }, +} + +impl ModuleSource { + fn is_user(&self) -> bool { + matches!(self, Self::User { .. }) + } +} + +/// An entry of the module list written to the `ModuleListStream`. +#[derive(Debug)] +pub struct ModuleInfo { + /// Where the ELF object was loaded — the minidump's `base_of_image`. + pub base_address: usize, + pub size: usize, + pub name: Option, + /// Offset of the object within its backing file; typically 0, but might + /// not be, e.g. if loaded from an APK. + pub file_offset: usize, + /// Whether the object has an executable segment. + /// It *is* possible to load data-only ELF objects! + pub executable: bool, + pub source: ModuleSource, +} + +/// A module we may write, before its extent is final. +#[derive(Debug)] +pub struct ModuleCandidate { + base_address: usize, + end_address: usize, + /// End of the object's last executable segment, or `base_address` if none. + code_end: usize, + name: Option, + file_offset: usize, + source: ModuleSource, +} + +impl ModuleCandidate { + /// Builds a module from user-supplied information. + fn from_user_entry(entry: &MappingEntry) -> Self { + Self { + base_address: entry.mapping.start_address, + end_address: entry.mapping.start_address + entry.mapping.size, + // Let's assume it's all executable. + code_end: entry.mapping.start_address + entry.mapping.size, + name: entry.mapping.name.clone(), + file_offset: entry.mapping.offset, + source: ModuleSource::User { + identifier: entry.identifier.clone(), + }, + } + } + + /// Whether `address` falls within this module's extent. + fn contains_address(&self, address: usize) -> bool { + (self.base_address..self.end_address).contains(&address) + } + + fn into_module(self) -> ModuleInfo { + ModuleInfo { + base_address: self.base_address, + size: self.end_address - self.base_address, + name: self.name, + file_offset: self.file_offset, + executable: self.code_end > self.base_address, + source: self.source, + } + } +} + +/// Any detected module that starts within a user-provided module must be dropped, as just keeping +/// the tail would make its addresses unresolvable anyway. +fn filter_out_user_overlap( + process_candidates: &mut Vec, + user_candidates: &[ModuleCandidate], +) { + process_candidates.retain(|c| { + !user_candidates + .iter() + .any(|uc| uc.contains_address(c.base_address)) + }); +} + +/// If a module contains the entry-point, and it's not already the first +/// one, then we need to make it be first. This is because the minidump +/// format assumes the first module is the one that corresponds to the main +/// executable (as codified in processor/minidump.cc:MinidumpModuleList::GetMainModule()). +fn ensure_entrypoint_is_first(candidates: &mut [ModuleCandidate], entry_point: Option) { + if let Some(entry_point) = entry_point + && let Some(index) = candidates + .iter() + .position(|c| c.contains_address(entry_point)) + { + candidates.swap(0, index); + } +} + +/// Turns the candidates into the entries written to the `ModuleListStream`. +pub(crate) fn resolve( + candidates: Vec, + entry_point: Option, + mut soft_errors: impl WriteErrorList, +) -> Vec { + let (user_candidates, mut process_candidates): (Vec<_>, Vec<_>) = + candidates.into_iter().partition(|c| c.source.is_user()); + + // Sanity check on the user-provided modules: if they happen to start at the same place, + // log the error and keep them both, as we don't have enough data to prioritize one. + for (index, candidate) in user_candidates.iter().enumerate() { + if user_candidates[..index] + .iter() + .any(|earlier| earlier.base_address == candidate.base_address) + { + soft_errors.push(ModuleResolveError::DuplicateUserModule { + name: candidate.name.clone().unwrap_or_default(), + base_address: candidate.base_address, + }); + } + } + + filter_out_user_overlap(&mut process_candidates, &user_candidates); + ensure_entrypoint_is_first(&mut process_candidates, entry_point); + + let mut candidates: Vec = process_candidates + .into_iter() + .chain(user_candidates) + .collect(); + clamp_overlapping_modules(&mut candidates, &mut soft_errors); + + candidates + .into_iter() + .map(ModuleCandidate::into_module) + .collect() +} + +/// Shortens any module whose image overlaps another entry of the module list. +fn clamp_overlapping_modules( + modules: &mut [ModuleCandidate], + mut soft_errors: impl WriteErrorList, +) { + let mut claims: Vec = modules.iter().map(|module| module.base_address).collect(); + claims.sort_unstable(); + + for module in modules { + let Some(&claim) = claims.iter().find(|&&claim| claim > module.base_address) else { + continue; + }; + if claim < module.end_address { + // Clamping is typically harmless *unless* the stuff that's cut + // out is executable code. + if claim < module.code_end { + soft_errors.push(ModuleResolveError::ModuleImageClamped { + name: module.name.clone().unwrap_or_default(), + base_address: module.base_address, + code_end: module.code_end, + clamped_to: claim, + }); + } + module.end_address = claim; + } + } +} + +/// Where the object behind `mapping` was loaded. +/// +/// `/proc//maps` reports where a mapping *starts*, which for an Android +/// object with packed relocations is `min_vaddr` above where the object was +/// actually loaded. Everywhere else the two are the same address. +#[cfg(target_os = "android")] +fn loaded_at(process_inspector: &dyn ProcessInspector, mapping: &MappingInfo) -> usize { + // Filter out unlikely candidates for libraries + if mapping.is_executable() && mapping.name_is_path() { + super::android::effective_load_base(process_inspector, mapping.start_address) + } else { + mapping.start_address + } +} + +#[cfg(not(target_os = "android"))] +fn loaded_at(_process_inspector: &dyn ProcessInspector, mapping: &MappingInfo) -> usize { + mapping.start_address +} + +impl ModuleCandidate { + /// Builds a module from a memory mapping. + fn from_mapping(process_inspector: &dyn ProcessInspector, mapping: &MappingInfo) -> Self { + // Adjust the base address if needed. + let base_address = loaded_at(process_inspector, mapping); + + Self { + base_address, + end_address: mapping.start_address + mapping.size, + code_end: if mapping.is_executable() { + mapping.start_address + mapping.size + } else { + mapping.start_address + }, + name: mapping.name.clone(), + file_offset: mapping.offset, + source: ModuleSource::Process, + } + } +} + +impl ModuleInfo { + pub fn effective_path_name_and_version( + &self, + process_inspector: &dyn ProcessInspector, + soname: Option, + soft_errors: impl WriteErrorList, + ) -> (PathBuf, String, Option) { + let mut file_path = PathBuf::from(self.name.clone().unwrap_or_default()); + + // Just use the filesystem name if no SONAME is present. + let Some(file_name) = self.find_soname(soname, process_inspector, soft_errors) else { + // file_path := /path/to/libname.so + // file_name := libname.so + let file_name = file_path + .file_name() + .map(|s| s.to_string_lossy().into_owned()) + .unwrap_or_default(); + + return (file_path, file_name, self.so_version()); + }; + + self.fix_filename(&mut file_path, &file_name); + (file_path, file_name, self.so_version()) + } + + /// Tools such as minidump_stackwalk use the name of the module to look up + /// symbols produced by dump_syms. dump_syms will prefer to use a module's + /// DT_SONAME as the module name, if one exists, and will fall back to the + /// filesystem name of the module. For this reason, we try different approaches + /// before giving up. + /// + /// We prefer the SONAME if it's available rather than parse the path. + fn find_soname( + &self, + provided_soname: Option, + process_inspector: &dyn ProcessInspector, + mut soft_errors: impl WriteErrorList, + ) -> Option { + provided_soname.or_else(|| { + // User supplied the filename, let's use that directly. + if self.source.is_user() { + return None; + } + match self.elf_so_name(process_inspector) { + Ok(soname) => soname, + Err(e) => { + // Log error and move on to fallback path. + soft_errors.push(e); + None + } + } + }) + } + + /// Look in the module ELF metadata to find its soname if it has any. + /// Typically, executables don't have one. + fn elf_so_name( + &self, + process_inspector: &dyn ProcessInspector, + ) -> Result, ModuleListError> { + let path = Path::new(self.name.as_deref().unwrap_or_default()); + match super::module_reader::read_soname_from_file(process_inspector, path, self.file_offset) + { + Ok(soname) => Ok(Some(soname)), + Err(ModuleReaderError::NoSoName { .. }) => Ok(None), + Err(e) => Err(ModuleListError::ReadSoNameFromFileFailed(e)), + } + } + + #[inline] + fn so_version(&self) -> Option { + SoVersion::parse(self.name.as_deref()?) + } + + /// Handle edge-cases on filename, e.g. archive files. + fn fix_filename(&self, path: &mut PathBuf, file_name: &str) { + if self.executable && self.file_offset != 0 { + // If an executable is mapped from a non-zero offset, this is likely because + // the executable was loaded directly from inside an archive file (e.g., an + // apk on Android). + // In this case, we append the file_name to the mapped archive path: + // file_name := libname.so + // file_path := /path/to/ARCHIVE.APK/libname.so + path.push(file_name); + } else { + // Otherwise, replace the basename with the SONAME. + path.set_file_name(file_name); + } + } +} + +/// Build module information out of kernel mapping data +/// +/// Only requires access to /proc/pid/maps, but is ultimately just an approximation based on +/// observed behaviour of linkers. +pub(crate) fn from_mappings( + process_inspector: &dyn ProcessInspector, + mappings: &[MappingInfo], +) -> Vec { + mappings + .iter() + .filter(|mapping| mapping.is_interesting()) + .map(|mapping| ModuleCandidate::from_mapping(process_inspector, mapping)) + .collect() +} + +/// Builds the modules the user told us about. +pub(crate) fn from_user_mappings(user_mapping_list: &MappingList) -> Vec { + user_mapping_list + .iter() + .map(ModuleCandidate::from_user_entry) + .collect() +} + +/// Version metadata retrieved from an .so filename +/// +/// There is no standard for .so version numbers so this implementation just +/// does a best effort to pull as much data as it can based on real .so schemes +/// seen +/// +/// That being said, the [libtool](https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html) +/// versioning scheme is fairly common +#[cfg_attr(test, derive(Debug))] +pub struct SoVersion { + /// Might be non-zero if there is at least one non-zero numeric component after .so. + /// + /// Equivalent to `current` in libtool versions + pub major: u32, + /// The numeric component after the major version, if any + /// + /// Equivalent to `revision` in libtool versions + pub minor: u32, + /// The numeric component after the minor version, if any + /// + /// Equivalent to `age` in libtool versions + pub patch: u32, + /// The patch component may contain additional non-numeric metadata similar + /// to a semver prelease, this is any numeric data that suffixes that prerelease + /// string + pub prerelease: u32, +} + +impl SoVersion { + /// Attempts to retrieve the .so version of the elf path via its filename + fn parse(so_path: &OsStr) -> Option { + let filename = std::path::Path::new(so_path).file_name()?; + + // Avoid an allocation unless the string contains non-utf8 + let filename = filename.to_string_lossy(); + + let (_, version) = filename.split_once(".so.")?; + + let mut sov = Self { + major: 0, + minor: 0, + patch: 0, + prerelease: 0, + }; + + let comps = [ + &mut sov.major, + &mut sov.minor, + &mut sov.patch, + &mut sov.prerelease, + ]; + + for (i, comp) in version.split('.').enumerate() { + if i <= 1 { + *comps[i] = comp.parse().unwrap_or_default(); + } else if i >= 4 { + break; + } else { + // In some cases the release/patch version is alphanumeric (eg. '2rc5'), + // so try to parse either a single or two numbers + if let Some(pend) = comp.find(|c: char| !c.is_ascii_digit()) { + if let Ok(patch) = comp[..pend].parse() { + *comps[i] = patch; + } + + if i >= comps.len() - 1 { + break; + } + if let Some(pre) = comp.rfind(|c: char| !c.is_ascii_digit()) + && let Ok(pre) = comp[pre + 1..].parse() + { + *comps[i + 1] = pre; + break; + } + } else { + *comps[i] = comp.parse().unwrap_or_default(); + } + } + } + + Some(sov) + } +} + +#[cfg(test)] +impl PartialEq<(u32, u32, u32, u32)> for SoVersion { + fn eq(&self, o: &(u32, u32, u32, u32)) -> bool { + self.major == o.0 && self.minor == o.1 && self.patch == o.2 && self.prerelease == o.3 + } +} + +#[cfg(test)] +#[cfg(target_pointer_width = "64")] // All addresses are 64 bit and I'm currently too lazy to adjust it to work for both +mod tests { + use super::*; + use error_graph::ErrorList; + use std::path::PathBuf; + + use crate::linux::{maps_reader::get_mappings_for, process_inspection}; + + // All addresses below are 64 bit, and `MappingInfo::aggregate` drops any + // mapping it can't fit into a `usize`. + #[cfg(target_pointer_width = "64")] + #[test] + fn test_get_module_effective_name() { + let mappings = get_mappings_for( + "\ +7f0b97b6f000-7f0b97b70000 r--p 00000000 00:3e 27136458 /home/martin/Documents/mozilla/devel/mozilla-central/obj/widget/gtk/mozgtk/gtk3/libmozgtk.so +7f0b97b70000-7f0b97b71000 r-xp 00000000 00:3e 27136458 /home/martin/Documents/mozilla/devel/mozilla-central/obj/widget/gtk/mozgtk/gtk3/libmozgtk.so +7f0b97b71000-7f0b97b73000 r--p 00000000 00:3e 27136458 /home/martin/Documents/mozilla/devel/mozilla-central/obj/widget/gtk/mozgtk/gtk3/libmozgtk.so +7f0b97b73000-7f0b97b74000 rw-p 00001000 00:3e 27136458 /home/martin/Documents/mozilla/devel/mozilla-central/obj/widget/gtk/mozgtk/gtk3/libmozgtk.so", + 0x7ffe091bf000, + ); + assert_eq!(mappings.len(), 1); + let process_inspector = process_inspection::local(0); + let modules = resolve( + from_mappings(process_inspector.as_ref(), &mappings), + None, + &mut ErrorList::default(), + ); + + // The path doesn't exist, so the SONAME read fails and we fall back to + // the filesystem name -- which is the behaviour under test. + let mut soft_errors = ErrorList::default(); + let (file_path, file_name, _version) = modules[0].effective_path_name_and_version( + process_inspector.as_ref(), + None, + &mut soft_errors, + ); + assert!(!soft_errors.is_empty()); + 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" + ) + ); + } + + #[test] + fn test_elf_file_so_version() { + #[rustfmt::skip] + let test_cases = [ + ("/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.32", (6, 0, 32, 0)), + ("/usr/lib/x86_64-linux-gnu/libcairo-gobject.so.2.11800.0", (2, 11800, 0, 0)), + ("/usr/lib/x86_64-linux-gnu/libm.so.6", (6, 0, 0, 0)), + ("/usr/lib/x86_64-linux-gnu/libpthread.so.0", (0, 0, 0, 0)), + ("/usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.7800.0", (0, 7800, 0, 0)), + ("/usr/lib/x86_64-linux-gnu/libabsl_time_zone.so.20220623.0.0", (20220623, 0, 0, 0)), + ("/usr/lib/x86_64-linux-gnu/libdbus-1.so.3.34.2rc5", (3, 34, 2, 5)), + ("/usr/lib/x86_64-linux-gnu/libdbus-1.so.3.34.2rc", (3, 34, 2, 0)), + ("/usr/lib/x86_64-linux-gnu/libdbus-1.so.3.34.rc5", (3, 34, 0, 5)), + ("/usr/lib/x86_64-linux-gnu/libtoto.so.AAA", (0, 0, 0, 0)), + ("/usr/lib/x86_64-linux-gnu/libsemver-1.so.1.2.alpha.1", (1, 2, 0, 1)), + ("/usr/lib/x86_64-linux-gnu/libboop.so.1.2.3.4.5", (1, 2, 3, 4)), + ("/usr/lib/x86_64-linux-gnu/libboop.so.1.2.3pre4.5", (1, 2, 3, 4)), + ]; + + assert!(SoVersion::parse(OsStr::new("/home/alex/bin/firefox/libmozsandbox.so")).is_none()); + + for (path, expected) in test_cases { + let actual = SoVersion::parse(OsStr::new(path)).unwrap(); + assert_eq!(actual, expected); + } + } +} diff --git a/third_party/rust/minidump-writer/src/linux/module_reader.rs b/third_party/rust/minidump-writer/src/linux/module_reader.rs index 7a1ae939ea7a..e6450fe74b10 100644 --- a/third_party/rust/minidump-writer/src/linux/module_reader.rs +++ b/third_party/rust/minidump-writer/src/linux/module_reader.rs @@ -160,11 +160,11 @@ fn section_header_with_name<'sc, MM: ReadModuleMemory>( } pub fn read_build_id_from_file( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, path: &Path, ) -> Result, Error> { let module_memory_reader = process_inspector - .map_module_into_memory(path, 0) + .map_module_into_memory(path.into(), 0) .map_err(Error::MapModuleFailed)?; read_build_id_from_module(module_memory_reader) } @@ -191,7 +191,7 @@ pub fn read_build_id_from_module(module_memory: impl ReadModuleMemory) -> Result } pub fn read_soname_from_file( - process_inspector: &ProcessInspector, + process_inspector: &dyn ProcessInspector, path: &Path, offset: usize, ) -> Result { @@ -206,7 +206,7 @@ pub fn read_soname_from_file( } let module_memory_reader = process_inspector - .map_module_into_memory(path, offset) + .map_module_into_memory(path.into(), offset) .map_err(Error::MapModuleFailed)?; let memory_len = module_memory_reader.len().map_err(Error::MapModuleFailed)?; diff --git a/third_party/rust/minidump-writer/src/linux/process_inspection/mod.rs b/third_party/rust/minidump-writer/src/linux/process_inspection/mod.rs index bbcc07eca50d..283d9138388d 100644 --- a/third_party/rust/minidump-writer/src/linux/process_inspection/mod.rs +++ b/third_party/rust/minidump-writer/src/linux/process_inspection/mod.rs @@ -1,241 +1,256 @@ -use self::process_reader::ProcessReader; -use super::maps_reader; +use super::super::linux; use crate::module_reader::{ModuleMemoryReadError, ReadError, ReadModuleMemory}; -use core::ffi::c_int; -use failspot::failspot; -use process_backend::{MAX_PATH_LEN, local, regs::*}; +use linux::maps_reader; +use process_backend::{ProcessReader as _, Stat, local, regs::*}; +use process_reader::{CopyFromProcessError, ProcessReader, ProcessReaderBackend}; use std::{ borrow::Cow, - ffi::{CString, OsString}, + ffi::{CString, OsString, c_int}, io, os::unix::ffi::OsStringExt, path::PathBuf, }; -pub use process_backend::regs; +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +use process_backend::PTRACE_DATA_LEN; + +pub(crate) use process_backend::regs; + +pub use process_backend::ProcessReaderKind; pub mod process_reader; -#[derive(Debug)] -pub struct ProcessInspector { - pid: libc::pid_t, - backend: Backend, +pub(crate) type Result = core::result::Result; + +// These are both arbitrary choices and may need to be tweaked +const MAX_PATH_LEN: usize = 65536; +const MAX_DIRECTORY_NAME_LENGTH: usize = 256; + +pub(crate) fn local(pid: libc::pid_t) -> Box { + set_process_backend_drop_fail_handler(); + Box::new(local::Backend::new(pid)) } -#[derive(Debug)] -pub enum Backend { - Local { - backend: local::Backend, - process_reader_backend: local::ProcessReader, - }, +pub trait ProcessInspector: core::fmt::Debug { + fn process_reader<'a>(&'a self) -> ProcessReader<'a>; + fn pid(&self) -> Result; + fn stop_process(&self) -> Result<()>; + fn continue_process(&self) -> Result<()>; + fn suspend_thread(&self, tid: libc::pid_t) -> Result<()>; + fn resume_thread(&self, tid: libc::pid_t) -> Result<()>; + fn map_module_into_memory<'a>( + &'a self, + path: PathBuf, + offset: u64, + ) -> Result>; + fn stat_file(&self, path: PathBuf) -> Result; + fn read_file<'a>(&'a self, path: PathBuf) -> Result>; + fn read_dir<'a>(&'a self, path: PathBuf) -> Result>; + fn read_link(&self, path: PathBuf) -> Result; + fn get_gen_regs(&self, tid: libc::pid_t) -> Result; + fn get_fp_regs(&self, tid: libc::pid_t) -> Result; + + #[cfg(target_arch = "x86")] + fn get_fpx_regs(&self, tid: libc::pid_t) -> Result; + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn ptrace_peekuser(&self, addr: usize) -> Result<[u8; PTRACE_DATA_LEN]>; + + fn force_process_reader_kind(&mut self, kind: ProcessReaderKind) -> Result<()>; + + fn fail_one_syscall_with(&self, errno: core::ffi::c_int); } -impl ProcessInspector { - pub fn local(pid: libc::pid_t) -> Self { - let backend = local::Backend::new(pid); - let process_reader_backend = backend.process_reader(); - - ProcessInspector { - pid, - backend: Backend::Local { - backend, - process_reader_backend, - }, - } - } - pub fn process_reader(&self) -> ProcessReader<'_> { +impl ProcessInspector for B { + fn process_reader<'a>(&'a self) -> ProcessReader<'a> { ProcessReader::new(self) } - pub fn stop_process(&self) -> Result<(), Error> { - failspot!(if StopProcess { - return Err(Error::Local(local::Error::SigStopFailed(libc::EPERM))); - }); - match &self.backend { - Backend::Local { backend, .. } => backend.stop_process().map_err(Error::Local), - } + fn pid(&self) -> Result { + B::pid(self).map_err(Error::Backend) } - pub fn continue_process(&self) -> Result<(), Error> { - match &self.backend { - Backend::Local { backend, .. } => backend.continue_process().map_err(Error::Local), - } + fn stop_process(&self) -> Result<()> { + B::stop_process(self).map_err(Error::Backend) } - pub fn suspend_thread(&self, tid: libc::pid_t) -> Result<(), Error> { - match &self.backend { - Backend::Local { backend, .. } => backend.suspend_thread(tid).map_err(Error::Local), - } + fn continue_process(&self) -> Result<()> { + B::continue_process(self).map_err(Error::Backend) } - pub fn resume_thread(&self, tid: libc::pid_t) -> Result<(), Error> { - match &self.backend { - Backend::Local { backend, .. } => backend.resume_thread(tid).map_err(Error::Local), - } + fn suspend_thread(&self, tid: libc::pid_t) -> Result<()> { + B::suspend_thread(self, tid).map_err(Error::Backend) } - pub fn map_module_into_memory( - &self, - path: impl Into, + fn resume_thread(&self, tid: libc::pid_t) -> Result<()> { + B::resume_thread(self, tid).map_err(Error::Backend) + } + + fn map_module_into_memory<'a>( + &'a self, + path: PathBuf, offset: u64, - ) -> Result { - let c_path = CString::new(path.into().into_os_string().into_vec()).unwrap(); - match &self.backend { - Backend::Local { backend, .. } => backend - .map_module_into_memory(&c_path, offset) - .map(MappedModuleMemoryReader::Local) - .map_err(Error::Local), - } + ) -> Result> { + let c_path = CString::new(path.into_os_string().into_vec()).unwrap(); + let reader = B::map_module_into_memory(self, &c_path, offset).map_err(Error::Backend)?; + Ok(MappedModuleMemoryReader(Box::new(reader))) } - pub fn stat_file(&self, path: impl Into) -> Result { - let c_path = CString::new(path.into().into_os_string().into_vec()).unwrap(); - match &self.backend { - Backend::Local { backend, .. } => backend.stat_file(&c_path).map_err(Error::Local), - } + fn stat_file(&self, path: PathBuf) -> Result { + let c_path = CString::new(path.into_os_string().into_vec()).unwrap(); + B::stat_file(self, &c_path).map_err(Error::Backend) } - pub fn read_file(&self, path: impl Into) -> Result { - let c_path = CString::new(path.into().into_os_string().into_vec()).unwrap(); - match &self.backend { - Backend::Local { backend, .. } => backend - .read_file(&c_path) - .map(FileReader::Local) - .map_err(Error::Local), - } + fn read_file<'a>(&'a self, path: PathBuf) -> Result> { + let c_path = CString::new(path.into_os_string().into_vec()).unwrap(); + let reader = B::read_file(self, &c_path).map_err(Error::Backend)?; + Ok(FileReader(Box::new(reader))) } - pub fn read_dir(&self, path: impl Into) -> Result { - let c_path = CString::new(path.into().into_os_string().into_vec()).unwrap(); - match &self.backend { - Backend::Local { backend, .. } => backend - .read_dir(&c_path) - .map(DirReader::Local) - .map_err(Error::Local), - } + fn read_dir<'a>(&'a self, path: PathBuf) -> Result> { + let c_path = CString::new(path.into_os_string().into_vec()).unwrap(); + let reader = B::read_dir(self, &c_path).map_err(Error::Backend)?; + Ok(DirReader(Box::new(reader))) } - pub fn read_link(&self, path: impl Into) -> Result { - let c_path = CString::new(path.into().into_os_string().into_vec()).unwrap(); - + fn read_link(&self, path: PathBuf) -> Result { + let c_path = CString::new(path.into_os_string().into_vec()).unwrap(); let mut buf = vec![0u8; MAX_PATH_LEN]; - - let len = match &self.backend { - Backend::Local { backend, .. } => { - backend.read_link(&c_path, &mut buf).map_err(Error::Local)? - } - }; - + let len = B::read_link(self, &c_path, &mut buf).map_err(Error::Backend)?; buf.truncate(len); Ok(PathBuf::from(OsString::from_vec(buf))) } - - pub fn get_gen_regs(&self, tid: libc::pid_t) -> Result { - match &self.backend { - Backend::Local { backend, .. } => backend.get_gen_regs(tid).map_err(Error::Local), - } + fn get_gen_regs(&self, tid: libc::pid_t) -> Result { + B::get_gen_regs(self, tid).map_err(Error::Backend) } - pub fn get_fp_regs(&self, tid: libc::pid_t) -> Result { - match &self.backend { - Backend::Local { backend, .. } => backend.get_fp_regs(tid).map_err(Error::Local), - } + fn get_fp_regs(&self, tid: libc::pid_t) -> Result { + B::get_fp_regs(self, tid).map_err(Error::Backend) } #[cfg(target_arch = "x86")] - pub fn get_fpx_regs(&self, tid: libc::pid_t) -> Result { - match &self.backend { - Backend::Local { backend, .. } => backend.get_fpx_regs(tid).map_err(Error::Local), - } + fn get_fpx_regs(&self, tid: libc::pid_t) -> Result { + B::get_fpx_regs(self, tid).map_err(Error::Backend) } #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - pub fn ptrace_peekuser( + fn ptrace_peekuser(&self, addr: usize) -> Result<[u8; PTRACE_DATA_LEN]> { + B::ptrace_peekuser(self, addr).map_err(Error::Backend) + } + + fn force_process_reader_kind(&mut self, kind: ProcessReaderKind) -> Result<()> { + B::force_process_reader_kind(self, kind).map_err(Error::Backend) + } + + #[doc(hidden)] + fn fail_one_syscall_with(&self, errno: c_int) { + B::fail_one_syscall_with(self, errno) + } +} + +impl ProcessReaderBackend for B { + fn process_inspector(&self) -> &dyn ProcessInspector { + self + } + + fn read_at( &self, - pid: libc::pid_t, - addr: usize, - ) -> Result<[u8; core::mem::size_of::()], Error> { - match &self.backend { - Backend::Local { backend, .. } => { - backend.ptrace_peekuser(pid, addr).map_err(Error::Local) - } - } + src: usize, + dst: &mut [u8], + ) -> core::result::Result { + B::process_reader(self) + .read_at(src, dst) + .map_err(|e| CopyFromProcessError::Backend(Error::Backend(e))) } } #[derive(Debug)] -pub enum FileReader { - Local(local::FileReader), -} +pub struct FileReader<'a>(Box); -impl io::Read for FileReader { +impl<'a> io::Read for FileReader<'a> { fn read(&mut self, buf: &mut [u8]) -> io::Result { - match self { - Self::Local(l) => l.read(buf).map_err(Error::Local), - } - .map_err(io::Error::other) + self.0 + .read(buf) + .map_err(Error::Backend) + .map_err(io::Error::other) } } #[derive(Debug)] -pub enum DirReader { - Local(local::DirReader), -} +pub struct DirReader<'a>(Box); -impl Iterator for DirReader { - type Item = Result; +impl<'a> Iterator for DirReader<'a> { + type Item = Result; fn next(&mut self) -> Option { - match self { - Self::Local(l) => match l.read_name().map_err(Error::Local) { - Ok(Some(name_bytes)) => Some(Ok(OsString::from_vec(name_bytes.to_vec()))), - Ok(None) => None, - Err(e) => Some(Err(e)), - }, - } - } -} - -#[doc(hidden)] -impl ProcessInspector { - pub fn fail_one_syscall_with(&self, errno: c_int) { - match &self.backend { - Backend::Local { backend, .. } => backend.fail_one_syscall_with(errno), + let mut buf = vec![0; MAX_DIRECTORY_NAME_LENGTH]; + match self.0.read_next_name(&mut buf).map_err(Error::Backend) { + Ok(0) => None, + Ok(len) => { + buf.truncate(len); + Some(Ok(OsString::from_vec(buf))) + } + Err(e) => Some(Err(e)), } } } #[derive(Debug)] -pub enum MappedModuleMemoryReader { - Local(local::MappedModuleMemoryReader), -} +pub struct MappedModuleMemoryReader<'a>(Box); -impl MappedModuleMemoryReader { - pub fn read(&self, offset: u64, length: u64) -> Result<&[u8], Error> { - match self { - Self::Local(l) => l.read(offset, length).map_err(Error::Local), +impl<'a> MappedModuleMemoryReader<'a> { + pub fn read_exact_at(&self, mut offset: usize, mut buf: &mut [u8]) -> Result<()> { + if buf.is_empty() { + return Ok(()); + } + + loop { + let bytes_read = self.0.read_at(offset, buf).map_err(Error::Backend)?; + if bytes_read == 0 { + return Err(Error::UnexpectedEndOfBuffer); + } + + if bytes_read == buf.len() { + return Ok(()); + } + + offset = offset + .checked_add(bytes_read) + .ok_or(Error::AddressOverflowed)?; + buf = &mut buf[bytes_read..]; } } - pub fn len(&self) -> Result { - match self { - Self::Local(l) => l.len().map_err(Error::Local), - } - } - pub fn is_empty(&self) -> Result { - match self { - Self::Local(l) => l.is_empty().map_err(Error::Local), - } + pub fn len(&self) -> Result { + self.0.len().map_err(Error::Backend) } } -impl ReadModuleMemory for MappedModuleMemoryReader { - fn read(&self, offset: u64, length: u64) -> Result, ModuleMemoryReadError> { - self.read(offset, length) - .map(Cow::Borrowed) - .map_err(|e| ModuleMemoryReadError { +impl<'a> ReadModuleMemory for MappedModuleMemoryReader<'a> { + fn read( + &self, + offset: u64, + length: u64, + ) -> core::result::Result, ModuleMemoryReadError> { + let result = (|| { + let (offset, length) = match (usize::try_from(offset), usize::try_from(length)) { + (Ok(o), Ok(l)) => (o, l), + _ => return Err(ReadError::OutOfBounds), + }; + + let mut buf = vec![0u8; length]; + + self.read_exact_at(offset, &mut buf) + .map_err(ReadError::PlatformSpecific)?; + + Ok(buf) + })(); + + result + .map(Cow::Owned) + .map_err(|error| ModuleMemoryReadError { offset, length, start_address: None, - error: ReadError::PlatformSpecific(e), + error, }) } fn absolute_to_relative(&self, addr: u64) -> Option { @@ -250,8 +265,23 @@ impl ReadModuleMemory for MappedModuleMemoryReader { } } -#[derive(Debug, thiserror::Error, serde::Serialize, serde::Deserialize)] +#[derive(Debug, thiserror::Error, serde::Serialize)] pub enum Error { - #[error("an error occurred running a syscall directly")] - Local(#[source] local::Error), + #[error("an error occurred running the backend")] + Backend(#[source] process_backend::Error), + #[error("an address overflowed")] + AddressOverflowed, + #[error("unexpected end of buffer reached")] + UnexpectedEndOfBuffer, + #[error("got an unexpected end of file")] + UnexpectedEndOfFile, +} + +fn set_process_backend_drop_fail_handler() { + fn drop_fail_handler(args: core::fmt::Arguments<'_>) { + log::error!("a drop() error occurred in process-backend: {args}"); + } + const HANDLER: process_backend::DropFailHandler = + process_backend::DropFailHandler::new(drop_fail_handler); + HANDLER.install_global(); } diff --git a/third_party/rust/minidump-writer/src/linux/process_inspection/process_reader.rs b/third_party/rust/minidump-writer/src/linux/process_inspection/process_reader.rs index d7cc3bd91df0..092e2521a6c9 100644 --- a/third_party/rust/minidump-writer/src/linux/process_inspection/process_reader.rs +++ b/third_party/rust/minidump-writer/src/linux/process_inspection/process_reader.rs @@ -1,120 +1,182 @@ use super::{ - Backend, Error, ProcessInspector, + Error, ProcessInspector, maps_reader::{MappingInfo, MapsReaderError}, }; use crate::module_reader::ProcessModuleMemoryReader; -use process_backend::local; +use plain::Plain; pub type ProcessHandle = libc::pid_t; #[derive(Debug)] -pub struct ProcessReader<'a> { - process_inspector: &'a ProcessInspector, - forced_backend: Option, -} - -#[derive(Debug)] -enum ForcedBackend { - Local(local::ProcessReader), -} +pub struct ProcessReader<'a>(&'a dyn ProcessReaderBackend); impl<'a> ProcessReader<'a> { - pub fn new(process_inspector: &'a ProcessInspector) -> Self { - Self { - process_inspector, - forced_backend: None, - } - } - pub fn for_virtual_mem(process_inspector: &'a ProcessInspector) -> Self { - let forced_backend = match &process_inspector.backend { - Backend::Local { backend, .. } => { - ForcedBackend::Local(backend.process_reader_for_virtual_mem()) - } - }; - Self { - process_inspector, - forced_backend: Some(forced_backend), - } - } - pub fn for_file(process_inspector: &'a ProcessInspector) -> Result { - let forced_backend = match &process_inspector.backend { - Backend::Local { backend, .. } => { - ForcedBackend::Local(backend.process_reader_for_file().map_err(Error::Local)?) - } - }; - Ok(Self { - process_inspector, - forced_backend: Some(forced_backend), - }) - } - pub fn for_ptrace(process_inspector: &'a ProcessInspector) -> Self { - let forced_backend = match &process_inspector.backend { - Backend::Local { backend, .. } => { - ForcedBackend::Local(backend.process_reader_for_ptrace()) - } - }; - Self { - process_inspector, - forced_backend: Some(forced_backend), - } - } - /// Read memory from the process into the given buffer. /// /// Returns the number of bytes read. pub fn read(&self, src: usize, dst: &mut [u8]) -> Result { - if let Some(forced_backend) = &self.forced_backend { - match forced_backend { - ForcedBackend::Local(process_reader_backend) => process_reader_backend - .read_at(src, dst) - .map_err(Error::Local), - } - } else { - match &self.process_inspector.backend { - Backend::Local { - process_reader_backend, - .. - } => process_reader_backend - .read_at(src, dst) - .map_err(Error::Local), - } - } - .map_err(CopyFromProcessError::Backend) + self.0.read_at(src, dst) } + + /// Read memory from the process until the buffer is filled. + /// + /// This is a convenience wrapper around [`ProcessReader::read`]. Unlike + /// [`read`](Self::read), this method does not return successful short + /// reads. It repeatedly calls [`read`](Self::read), advancing `address` + /// and the output buffer by the number of bytes read, until the entire buffer + /// has been filled. + /// + /// If an underlying read fails before the buffer is filled, this method returns + /// that error as is. If an underlying read succeeds but returns `0` + /// bytes before the buffer is filled, this method returns + /// [`CopyFromProcessError::Backend`] containing [`Error::UnexpectedEndOfFile`]. + /// + /// On success, all of `buf` has been filled with bytes read from the target + /// process. + /// + /// # Errors + /// + /// Returns whichever error [`read`](Self::read) would return. + /// + /// In addition, returns [`CopyFromProcessError::Backend`] containing + /// [`Error::UnexpectedEndOfFile`] if an underlying read returns `0` bytes + /// before the buffer is full, and [`CopyFromProcessError::Backend`] containing + /// [`Error::AddressOverflowed`] if advancing the read address by the number of + /// bytes read would wrap past the end of the address space. + /// + /// If this method returns an error, `buf` may have been partially overwritten. + /// The error type does not report how many bytes were read before the failure. + pub fn read_exact( + &self, + mut src: usize, + mut dst: &mut [u8], + ) -> Result<(), CopyFromProcessError> { + if dst.is_empty() { + return Ok(()); + } + + loop { + let bytes_read = self.read(src, dst)?; + if bytes_read == 0 { + return Err(CopyFromProcessError::Backend(Error::UnexpectedEndOfFile)); + } + if bytes_read == dst.len() { + return Ok(()); + } + src = src + .checked_add(bytes_read) + .ok_or(CopyFromProcessError::Backend(Error::AddressOverflowed))?; + dst = &mut dst[bytes_read..]; + } + } + + /// Reads a plain-old-data value of type `T` from the target process at + /// `address`. + /// + /// This reads exactly `size_of::()` bytes into a freshly zeroed `T` using + /// [`read_exact`](Self::read_exact). The [`Plain`] bound guarantees that + /// every possible bit pattern is a valid `T`, so the bytes read from the + /// target process are always a valid value. + /// + /// # Errors + /// + /// See [`read_exact`](Self::read_exact) for the possible errors. + pub fn read_pod(&self, address: usize) -> Result { + // Safety: `Plain` is an unsafe trait that may only be implemented on + // types for which every possible bit pattern is valid, so there is + // nothing we could read from the other process that isn't a valid value + // for `T`. + let mut pod: T = unsafe { core::mem::zeroed() }; + let bytes = unsafe { + core::slice::from_raw_parts_mut( + core::ptr::from_mut(&mut pod).cast::(), + size_of::(), + ) + }; + self.read_exact(address, bytes)?; + Ok(pod) + } + + /// Read `count` consecutive plain-old-data values of type `T` starting at + /// `address`. + pub fn read_pod_vec( + &self, + mut address: usize, + count: usize, + ) -> Result, CopyFromProcessError> { + let mut v = Vec::with_capacity(count); + for _ in 0..count { + v.push(self.read_pod(address)?); + address += std::mem::size_of::(); + } + Ok(v) + } + + /// Read bytes from the process starting at `address` into `buf` up to and + /// including the first `terminator` byte (or until a read returns no bytes). + /// + /// Returns the number of bytes appended to `buf`. + pub fn read_until( + &self, + mut address: usize, + terminator: u8, + buf: &mut Vec, + ) -> Result { + let start_len = buf.len(); + let mut b = [0u8]; + while self.read(address, &mut b)? > 0 { + buf.push(b[0]); + if b[0] == terminator { + break; + } + address += 1; + } + Ok(buf.len() - start_len) + } + /// Find the address at which a module with the given name is loaded in the process. pub fn find_module( &self, module_name: &str, ) -> Result, FindModuleError> { - MappingInfo::for_pid(self.process_inspector, self.process_inspector.pid, None)? - .into_iter() - .find_map(|m| { - let mmem = ProcessModuleMemoryReader::new(self, m.start_address); - let name = m.name.as_ref().and_then(|s| s.to_str())?; - if name == module_name { - return Some(mmem); - } - // Check whether the SO_NAME matches the module name. - // - // For now, only check the SO_NAME of Android APKS, because libraries may be mapped - // directly from within an APK. See bug 1982902. - #[cfg(target_os = "android")] - if name.ends_with(".apk") { - if let Ok(so_name) = crate::module_reader::read_soname_from_module(&mmem) { - if so_name == name { - return Some(mmem); - } - } - } + MappingInfo::for_pid( + self.0.process_inspector(), + self.0 + .process_inspector() + .pid() + .map_err(FindModuleError::GetTargetPidFailed)?, + None, + )? + .into_iter() + .find_map(|m| { + let mmem = ProcessModuleMemoryReader::new(self, m.start_address); + let name = m.name.as_ref().and_then(|s| s.to_str())?; + if name == module_name { + return Some(mmem); + } + // Check whether the SO_NAME matches the module name. + // + // For now, only check the SO_NAME of Android APKS, because libraries may be mapped + // directly from within an APK. See bug 1982902. + #[cfg(target_os = "android")] + if name.ends_with(".apk") + && let Ok(so_name) = crate::module_reader::read_soname_from_module(&mmem) + && so_name == name + { + return Some(mmem); + } - None - }) - .ok_or(FindModuleError::ModuleNotFound) + None + }) + .ok_or(FindModuleError::ModuleNotFound) + } + pub(crate) fn new(backend: &'a dyn ProcessReaderBackend) -> Self { + Self(backend) } } -#[derive(Debug, thiserror::Error, serde::Serialize, serde::Deserialize)] +#[derive(Debug, thiserror::Error, serde::Serialize)] pub enum CopyFromProcessError { #[error("an error occurred calling ProcessReader")] Backend(Error), @@ -128,4 +190,11 @@ pub enum FindModuleError { ModuleNotFound, #[error("Failed to read process module mappings")] MappingError(#[from] MapsReaderError), + #[error("Failed to get PID of target process")] + GetTargetPidFailed(#[source] Error), +} + +pub(crate) trait ProcessReaderBackend: core::fmt::Debug { + fn process_inspector(&self) -> &dyn ProcessInspector; + fn read_at(&self, src: usize, dst: &mut [u8]) -> Result; } diff --git a/third_party/rust/minidump-writer/src/linux/thread_info/aarch64.rs b/third_party/rust/minidump-writer/src/linux/thread_info/aarch64.rs index 8d68e099cb25..103b96c4fb6b 100644 --- a/third_party/rust/minidump-writer/src/linux/thread_info/aarch64.rs +++ b/third_party/rust/minidump-writer/src/linux/thread_info/aarch64.rs @@ -1,6 +1,7 @@ use { super::{Pid, ProcessInspector, ThreadInfoError, regs::*}, crate::minidump_cpu::{FP_REG_COUNT, GP_REG_COUNT, RawContextCPU}, + error_graph::WriteErrorList, }; #[derive(Debug)] @@ -8,8 +9,8 @@ pub struct ThreadInfoAarch64 { pub stack_pointer: usize, pub tgid: Pid, // thread group id pub ppid: Pid, // parent process - pub regs: libc::user_regs_struct, - pub fpregs: user_fpsimd_struct, + pub regs: GenRegs, + pub fpregs: Option, } impl ThreadInfoAarch64 { @@ -29,19 +30,33 @@ impl ThreadInfoAarch64 { // field instead out.pc = self.regs.pc; - out.fpsr = self.fpregs.fpsr; - out.fpcr = self.fpregs.fpcr; - out.float_regs[..FP_REG_COUNT].copy_from_slice(&self.fpregs.vregs[..FP_REG_COUNT]); + let fpregs = self.fpregs.unwrap_or_default(); + out.fpsr = fpregs.fpsr; + out.fpcr = fpregs.fpcr; + out.float_regs[..FP_REG_COUNT].copy_from_slice(&fpregs.vregs[..FP_REG_COUNT]); } - pub fn create(process_inspector: &ProcessInspector, tid: Pid) -> Result { + pub fn create( + process_inspector: &dyn ProcessInspector, + tid: Pid, + mut soft_errors: impl WriteErrorList, + ) -> Result { let (ppid, tgid) = super::get_ppid_and_tgid(process_inspector, tid)?; + let regs = process_inspector .get_gen_regs(tid) - .map_err(ThreadInfoError::PtraceError)?; - let fpregs = process_inspector + .map_err(ThreadInfoError::GetGenRegsFailed)?; + + let fpregs = match process_inspector .get_fp_regs(tid) - .map_err(ThreadInfoError::PtraceError)?; + .map_err(ThreadInfoError::GetFpRegsFailed) + { + Ok(regs) => Some(regs), + Err(e) => { + soft_errors.push(e); + None + } + }; let stack_pointer = regs.sp as usize; diff --git a/third_party/rust/minidump-writer/src/linux/thread_info/arm.rs b/third_party/rust/minidump-writer/src/linux/thread_info/arm.rs index 5cfa60279f91..ec255d7aeb06 100644 --- a/third_party/rust/minidump-writer/src/linux/thread_info/arm.rs +++ b/third_party/rust/minidump-writer/src/linux/thread_info/arm.rs @@ -1,6 +1,7 @@ use { super::{Pid, ProcessInspector, ThreadInfoError, regs::*}, crate::minidump_cpu::RawContextCPU, + error_graph::WriteErrorList, }; #[derive(Debug)] @@ -8,8 +9,8 @@ pub struct ThreadInfoArm { pub stack_pointer: usize, pub tgid: Pid, // thread group id pub ppid: Pid, // parent process - pub regs: user_regs_struct, - pub fpregs: user_fpregs_struct, + pub regs: GenRegs, + pub fpregs: Option, } impl ThreadInfoArm { @@ -23,18 +24,34 @@ impl ThreadInfoArm { out.iregs.copy_from_slice(&self.regs.uregs[..16]); out.cpsr = self.regs.uregs[16]; - out.float_save.fpscr = self.fpregs.fpscr as u64; - out.float_save.regs = self.fpregs.fpregs; + + let fpregs = self.fpregs.unwrap_or_default(); + + out.float_save.fpscr = fpregs.fpscr as u64; + out.float_save.regs = fpregs.fpregs; } - pub fn create(process_inspector: &ProcessInspector, tid: Pid) -> Result { + pub fn create( + process_inspector: &dyn ProcessInspector, + tid: Pid, + mut soft_errors: impl WriteErrorList, + ) -> Result { let (ppid, tgid) = super::get_ppid_and_tgid(process_inspector, tid)?; + let regs = process_inspector .get_gen_regs(tid) - .map_err(ThreadInfoError::PtraceError)?; - let fpregs = process_inspector + .map_err(ThreadInfoError::GetGenRegsFailed)?; + + let fpregs = match process_inspector .get_fp_regs(tid) - .unwrap_or_default(); + .map_err(ThreadInfoError::GetFpRegsFailed) + { + Ok(regs) => Some(regs), + Err(e) => { + soft_errors.push(e); + None + } + }; let stack_pointer = regs.uregs[13] as usize; diff --git a/third_party/rust/minidump-writer/src/linux/thread_info/mod.rs b/third_party/rust/minidump-writer/src/linux/thread_info/mod.rs index 0e5d14b48626..a88b8c7efc6d 100644 --- a/third_party/rust/minidump-writer/src/linux/thread_info/mod.rs +++ b/third_party/rust/minidump-writer/src/linux/thread_info/mod.rs @@ -32,8 +32,14 @@ pub enum ThreadInfoError { #[serde(skip)] std::num::ParseIntError, ), - #[error("ptrace error")] - PtraceError(#[source] process_inspection::Error), + #[error("failed to get general-purpose registers")] + GetGenRegsFailed(#[source] process_inspection::Error), + #[error("failed to get floating-point registers")] + GetFpRegsFailed(#[source] process_inspection::Error), + #[error("failed to get floating-point register extended info")] + GetFpxRegsFailed(#[source] process_inspection::Error), + #[error("failed to get debug registers")] + GetDebugRegsFailed(#[source] process_inspection::Error), #[error("Invalid line in /proc/{0}/status: {1}")] InvalidProcStatusFile(Pid, String), } @@ -54,7 +60,7 @@ cfg_if::cfg_if! { } } -fn get_ppid_and_tgid(process_inspector: &ProcessInspector, tid: Pid) -> Result<(Pid, Pid)> { +fn get_ppid_and_tgid(process_inspector: &dyn ProcessInspector, tid: Pid) -> Result<(Pid, Pid)> { let mut ppid = -1; let mut tgid = -1; diff --git a/third_party/rust/minidump-writer/src/linux/thread_info/x86.rs b/third_party/rust/minidump-writer/src/linux/thread_info/x86.rs index 0f2e2d8f65c3..50512cb53cf0 100644 --- a/third_party/rust/minidump-writer/src/linux/thread_info/x86.rs +++ b/third_party/rust/minidump-writer/src/linux/thread_info/x86.rs @@ -2,6 +2,7 @@ use { super::{Pid, ProcessInspector, ThreadInfoError, regs::*}, crate::{minidump_cpu::RawContextCPU, minidump_format::format}, core::mem, + error_graph::WriteErrorList, scroll::Pwrite, }; @@ -9,43 +10,67 @@ pub struct ThreadInfoX86 { pub stack_pointer: usize, pub tgid: Pid, // thread group id pub ppid: Pid, // parent process - pub regs: user_regs_struct, - pub fpregs: user_fpregs_struct, + pub regs: GenRegs, + pub fpregs: Option, pub dregs: [RegType; NUM_DEBUG_REGISTERS], #[cfg(target_arch = "x86")] - pub fpxregs: user_fpxregs_struct, + pub fpxregs: Option, } impl ThreadInfoX86 { - pub fn create(process_inspector: &ProcessInspector, tid: Pid) -> Result { + pub fn create( + process_inspector: &dyn ProcessInspector, + tid: Pid, + mut soft_errors: impl WriteErrorList, + ) -> Result { let (ppid, tgid) = super::get_ppid_and_tgid(process_inspector, tid)?; + let regs = process_inspector .get_gen_regs(tid) - .map_err(ThreadInfoError::PtraceError)?; - let fpregs = process_inspector + .map_err(ThreadInfoError::GetGenRegsFailed)?; + + let fpregs = match process_inspector .get_fp_regs(tid) - .map_err(ThreadInfoError::PtraceError)?; + .map_err(ThreadInfoError::GetFpRegsFailed) + { + Ok(regs) => Some(regs), + Err(e) => { + soft_errors.push(e); + None + } + }; #[cfg(target_arch = "x86")] - let fpxregs = { - if cfg!(target_feature = "fxsr") { - process_inspector - .get_fpx_regs(tid) - .map_err(ThreadInfoError::PtraceError)? - } else { - unsafe { mem::zeroed() } + let fpxregs = if cfg!(target_feature = "fxsr") { + match process_inspector + .get_fpx_regs(tid) + .map_err(ThreadInfoError::GetFpxRegsFailed) + { + Ok(regs) => Some(regs), + Err(e) => { + soft_errors.push(e); + None + } } + } else { + None }; let mut dregs: [RegType; NUM_DEBUG_REGISTERS] = [0; NUM_DEBUG_REGISTERS]; - let debug_offset = mem::offset_of!(user, u_debugreg); + let debug_offset = USER_STRUCT_DEBUGREG_OFFSET; for (idx, dreg) in dregs.iter_mut().enumerate() { - let chunk = process_inspector - .ptrace_peekuser(tid, debug_offset + idx * mem::size_of::()) - .map_err(ThreadInfoError::PtraceError)?; - - *dreg = RegType::from_ne_bytes(chunk[0..mem::size_of::()].try_into().unwrap()); + match process_inspector + .ptrace_peekuser(debug_offset + idx * mem::size_of::()) + .map_err(ThreadInfoError::GetDebugRegsFailed) + { + Ok(chunk) => { + *dreg = RegType::from_ne_bytes( + chunk[0..mem::size_of::()].try_into().unwrap(), + ) + } + Err(e) => soft_errors.push(e), + } } #[cfg(target_arch = "x86_64")] @@ -123,23 +148,23 @@ impl ThreadInfoX86 { out.rip = self.regs.rip; { - let fs = &self.fpregs; + let fs = self.fpregs.unwrap_or_default(); let mut float_save = crate::minidump_cpu::FloatStateCPU { control_word: fs.cwd, status_word: fs.swd, - tag_word: fs.ftw as u8, + tag_word: fs.twd as u8, error_opcode: fs.fop, error_offset: fs.rip as u32, data_offset: fs.rdp as u32, error_selector: 0, // We don't have this. data_selector: 0, // We don't have this. mx_csr: fs.mxcsr, - mx_csr_mask: fs.mxcr_mask, + mx_csr_mask: fs.mxcsr_mask, ..Default::default() }; copy_u32_registers(&mut float_save.float_registers, &fs.st_space); - copy_u32_registers(&mut float_save.xmm_registers, &fs.xmm_space); + copy_u32_registers(&mut float_save.xmm_registers, &fs.xmm_space.0); out.float_save .pwrite_with(float_save, 0, scroll::Endian::Little) @@ -151,46 +176,48 @@ impl ThreadInfoX86 { pub fn fill_cpu_context(&self, out: &mut RawContextCPU) { out.context_flags = format::ContextFlagsX86::CONTEXT_X86_ALL.bits(); - out.dr0 = self.dregs[0] as u32; - out.dr3 = self.dregs[3] as u32; - out.dr1 = self.dregs[1] as u32; - out.dr2 = self.dregs[2] as u32; + out.dr0 = self.dregs[0]; + out.dr3 = self.dregs[3]; + out.dr1 = self.dregs[1]; + out.dr2 = self.dregs[2]; // 4 and 5 deliberatly omitted because they aren't included in the minidump // format. - out.dr6 = self.dregs[6] as u32; - out.dr7 = self.dregs[7] as u32; + out.dr6 = self.dregs[6]; + out.dr7 = self.dregs[7]; - out.gs = self.regs.xgs as u32; - out.fs = self.regs.xfs as u32; - out.es = self.regs.xes as u32; - out.ds = self.regs.xds as u32; + out.gs = self.regs.gs; + out.fs = self.regs.fs; + out.es = self.regs.es; + out.ds = self.regs.ds; - out.edi = self.regs.edi as u32; - out.esi = self.regs.esi as u32; - out.ebx = self.regs.ebx as u32; - out.edx = self.regs.edx as u32; - out.ecx = self.regs.ecx as u32; - out.eax = self.regs.eax as u32; + out.edi = self.regs.edi; + out.esi = self.regs.esi; + out.ebx = self.regs.ebx; + out.edx = self.regs.edx; + out.ecx = self.regs.ecx; + out.eax = self.regs.eax; - out.ebp = self.regs.ebp as u32; - out.eip = self.regs.eip as u32; - out.cs = self.regs.xcs as u32; - out.eflags = self.regs.eflags as u32; - out.esp = self.regs.esp as u32; - out.ss = self.regs.xss as u32; + out.ebp = self.regs.ebp; + out.eip = self.regs.eip; + out.cs = self.regs.cs; + out.eflags = self.regs.eflags; + out.esp = self.regs.esp; + out.ss = self.regs.ss; - out.float_save.control_word = self.fpregs.cwd as u32; - out.float_save.status_word = self.fpregs.swd as u32; - out.float_save.tag_word = self.fpregs.twd as u32; - out.float_save.error_offset = self.fpregs.fip as u32; - out.float_save.error_selector = self.fpregs.fcs as u32; - out.float_save.data_offset = self.fpregs.foo as u32; - out.float_save.data_selector = self.fpregs.fos as u32; + let fpregs = self.fpregs.unwrap_or_default(); + + out.float_save.control_word = fpregs.cwd; + out.float_save.status_word = fpregs.swd; + out.float_save.tag_word = fpregs.twd; + out.float_save.error_offset = fpregs.fip; + out.float_save.error_selector = fpregs.fcs; + out.float_save.data_offset = fpregs.foo; + out.float_save.data_selector = fpregs.fos; { let ra = &mut out.float_save.register_area; // 8 registers * 10 bytes per register. - for (idx, block) in self.fpregs.st_space.iter().enumerate() { + for (idx, block) in fpregs.st_space.iter().enumerate() { let offset = idx * std::mem::size_of::(); if offset >= ra.len() { break; @@ -213,26 +240,29 @@ impl ThreadInfoX86 { }; } + let fpregs = self.fpregs.unwrap_or_default(); + let fpxregs = self.fpxregs.unwrap_or_default(); + // This matches the Intel fpsave format. - write_er!(self.fpregs.cwd as u16); - write_er!(self.fpregs.swd as u16); - write_er!(self.fpregs.twd as u16); - write_er!(self.fpxregs.fop); - write_er!(self.fpxregs.fip); - write_er!(self.fpxregs.fcs); - write_er!(self.fpregs.foo); - write_er!(self.fpregs.fos); - write_er!(self.fpxregs.mxcsr); + write_er!(fpregs.cwd as u16); + write_er!(fpregs.swd as u16); + write_er!(fpregs.twd as u16); + write_er!(fpxregs.fop); + write_er!(fpxregs.fip); + write_er!(fpxregs.fcs); + write_er!(fpregs.foo); + write_er!(fpregs.fos); + write_er!(fpxregs.mxcsr); offset = 32; - for val in &self.fpxregs.st_space { + for val in &fpxregs.st_space { write_er!(val); } debug_assert_eq!(offset, 160); - for val in &self.fpxregs.xmm_space { + for val in &fpxregs.xmm_space.0 { write_er!(val); } } diff --git a/third_party/rust/minidump-writer/src/mac/mach.rs b/third_party/rust/minidump-writer/src/mac/mach.rs index f8077830de08..17422b2ae4ef 100644 --- a/third_party/rust/minidump-writer/src/mac/mach.rs +++ b/third_party/rust/minidump-writer/src/mac/mach.rs @@ -639,8 +639,7 @@ pub fn sysctl_string(name: &[u8]) -> String { return String::new(); } - let mut buff = Vec::new(); - buff.resize(buf_len, 0); + let mut buff = vec![0; buf_len]; if libc::sysctlbyname( name.as_ptr().cast(), diff --git a/third_party/rust/minidump-writer/src/mac/streams/exception.rs b/third_party/rust/minidump-writer/src/mac/streams/exception.rs index c0494f7fd351..9ce965401d11 100644 --- a/third_party/rust/minidump-writer/src/mac/streams/exception.rs +++ b/third_party/rust/minidump-writer/src/mac/streams/exception.rs @@ -33,11 +33,11 @@ impl MinidumpWriter { .exception .as_ref() .map(|exc| { - let code = exc.code as u64; + let code = exc.code; // `EXC_CRASH` exceptions wrap other exceptions, so we want to // retrieve the _actual_ exception - let wrapped_exc = if exc.kind as u32 == et::EXC_CRASH { + let wrapped_exc = if exc.kind == et::EXC_CRASH { recover_exc_crash_wrapped_exception(code) } else { None @@ -59,21 +59,20 @@ impl MinidumpWriter { // +--------------------------------------------------------+ // |[63:61] resource type | [60:58] flavor | [57:32] unused | // +--------------------------------------------------------+ - let exception_code = - if exc.kind as u32 == et::EXC_RESOURCE || exc.kind as u32 == et::EXC_GUARD { - (code >> 32) as u32 - } else if let Some(wrapped) = wrapped_exc { - wrapped.code - } else { - // For all other exceptions types, the value in the code - // _should_ never exceed 32 bits, crashpad does an actual - // range check here. - if code > u32::MAX.into() { - // TODO: do something more than logging? - log::warn!("exception code {code:#018x} exceeds the expected 32 bits"); - } - code as u32 - }; + let exception_code = if exc.kind == et::EXC_RESOURCE || exc.kind == et::EXC_GUARD { + (code >> 32) as u32 + } else if let Some(wrapped) = wrapped_exc { + wrapped.code + } else { + // For all other exceptions types, the value in the code + // _should_ never exceed 32 bits, crashpad does an actual + // range check here. + if code > u32::MAX.into() { + // TODO: do something more than logging? + log::warn!("exception code {code:#018x} exceeds the expected 32 bits"); + } + code as u32 + }; let exception_kind = if let Some(wrapped) = wrapped_exc { wrapped.kind @@ -168,7 +167,7 @@ struct WrappedException { /// should not be possible to be wrapped in an `EXC_CRASH` #[inline] fn recover_exc_crash_wrapped_exception(code: u64) -> Option { - is_valid_exc_crash(code).then(|| WrappedException { + is_valid_exc_crash(code).then_some(WrappedException { kind: ((code >> 20) & 0xf) as u32, code: (code & 0xfffff) as u32, _signal: ((code >> 24) & 0xff) as u8, diff --git a/third_party/rust/minidump-writer/src/mac/streams/memory_list.rs b/third_party/rust/minidump-writer/src/mac/streams/memory_list.rs index 47a37fbfd620..6ddac4c0f2ce 100644 --- a/third_party/rust/minidump-writer/src/mac/streams/memory_list.rs +++ b/third_party/rust/minidump-writer/src/mac/streams/memory_list.rs @@ -11,47 +11,46 @@ impl MinidumpWriter { ) -> Result { // Include some memory around the instruction pointer if the crash was // due to an exception - if let Some(cc) = &self.crash_context { - if cc.exception.is_some() { - const IP_MEM_SIZE: u64 = 256; + if let Some(cc) = &self.crash_context + && cc.exception.is_some() + { + const IP_MEM_SIZE: u64 = 256; - let get_ip_block = |tid| -> Option> { - let thread_state = dumper.read_thread_state(tid).ok()?; + let get_ip_block = |tid| -> Option> { + let thread_state = dumper.read_thread_state(tid).ok()?; - let ip = thread_state.pc(); + let ip = thread_state.pc(); - // Bound it to the upper and lower bounds of the region - // it's contained within. If it's not in a known memory region, - // don't bother trying to write it. - let region = dumper.get_vm_region(ip).ok()?; + // Bound it to the upper and lower bounds of the region + // it's contained within. If it's not in a known memory region, + // don't bother trying to write it. + let region = dumper.get_vm_region(ip).ok()?; - if ip < region.range.start || ip > region.range.end { - return None; - } - - // Try to get IP_MEM_SIZE / 2 bytes before and after the IP, but - // settle for whatever's available. - let start = std::cmp::max(region.range.start, ip - IP_MEM_SIZE / 2); - let end = std::cmp::min(ip + IP_MEM_SIZE / 2, region.range.end); - - Some(start..end) - }; - - if let Some(ip_range) = get_ip_block(cc.thread) { - let size = ip_range.end - ip_range.start; - let stack_buffer = - dumper.read_task_memory(ip_range.start as _, size as usize)?; - let ip_location = MDLocationDescriptor { - data_size: size as u32, - rva: buffer.position() as u32, - }; - buffer.write_all(&stack_buffer); - - self.memory_blocks.push(MDMemoryDescriptor { - start_of_memory_range: ip_range.start, - memory: ip_location, - }); + if ip < region.range.start || ip > region.range.end { + return None; } + + // Try to get IP_MEM_SIZE / 2 bytes before and after the IP, but + // settle for whatever's available. + let start = std::cmp::max(region.range.start, ip - IP_MEM_SIZE / 2); + let end = std::cmp::min(ip + IP_MEM_SIZE / 2, region.range.end); + + Some(start..end) + }; + + if let Some(ip_range) = get_ip_block(cc.thread) { + let size = ip_range.end - ip_range.start; + let stack_buffer = dumper.read_task_memory(ip_range.start as _, size as usize)?; + let ip_location = MDLocationDescriptor { + data_size: size as u32, + rva: buffer.position() as u32, + }; + buffer.write_all(&stack_buffer); + + self.memory_blocks.push(MDMemoryDescriptor { + start_of_memory_range: ip_range.start, + memory: ip_location, + }); } } diff --git a/third_party/rust/minidump-writer/src/mac/streams/module_list.rs b/third_party/rust/minidump-writer/src/mac/streams/module_list.rs index 38be3c5d2f18..dfc8fe6ef2a5 100644 --- a/third_party/rust/minidump-writer/src/mac/streams/module_list.rs +++ b/third_party/rust/minidump-writer/src/mac/streams/module_list.rs @@ -92,7 +92,7 @@ impl MinidumpWriter { } if !modules - .get(0) + .first() .map(|rm| rm.version_info.signature != format::VS_FFI_SIGNATURE) .unwrap_or_default() { @@ -104,10 +104,10 @@ impl MinidumpWriter { // Apple, which considering their penchant for changings things often // and not actually documenting anything, is fair, but if that ever // happens we can just...change the code. - if let Ok(dyld_image) = self.read_dyld(&all_images_info, dumper) { - if let Ok(module) = self.write_module(dyld_image, buf) { - modules.push(module); - } + if let Ok(dyld_image) = self.read_dyld(&all_images_info, dumper) + && let Ok(module) = self.write_module(dyld_image, buf) + { + modules.push(module); } Ok(modules) @@ -372,7 +372,7 @@ mod test { let expect_segment_data = unsafe { getsegmentdata( expected_img_hdr, - b"__TEXT\0".as_ptr(), + c"__TEXT".as_ptr().cast(), &mut expect_segment_size, ) }; diff --git a/third_party/rust/minidump-writer/tests/common/mod.rs b/third_party/rust/minidump-writer/tests/common/mod.rs index bf6368b1beeb..74fc0f42e45e 100644 --- a/third_party/rust/minidump-writer/tests/common/mod.rs +++ b/third_party/rust/minidump-writer/tests/common/mod.rs @@ -1,10 +1,12 @@ use std::{ error, - io::{BufRead, BufReader, Write}, + io::{BufRead, BufReader}, process::{Child, Command, Stdio}, result, }; +use serde::Serialize; + #[allow(unused)] type Error = Box; #[allow(unused)] @@ -39,16 +41,34 @@ fn build_command() -> Command { cmd } +/// Must be taken by tests that use ptrace() to avoid racing on attaching to the parent, +/// leading to random failures. +static PTRACE_PARENT_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); + #[allow(unused)] pub fn spawn_child(command: &str, args: &[&str]) { let mut cmd = build_command(); cmd.arg(command).args(args); - let child = cmd.output().expect("failed to execute child"); + let child = { + // Panicking is fine as far as ptrace is concerned, + // no need to poison other tests. + let _guard = PTRACE_PARENT_LOCK + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()); + cmd.output().expect("failed to execute child") + }; println!("Child output:"); - std::io::stdout().write_all(&child.stdout).unwrap(); - std::io::stdout().write_all(&child.stderr).unwrap(); + println!("===stdout==="); + + print_stdio(&child.stdout); + + println!("\n===stderr==="); + + print_stdio(&child.stderr); + + println!("\n============"); assert_eq!(child.status.code().expect("No return value"), 0); } @@ -122,25 +142,112 @@ where serde_json::from_str(contents).expect("expected json") } +pub fn visit_json_objects(json: &serde_json::Value, path: &mut Vec, visit: &mut V) +where + V: FnMut(&[String], &serde_json::Value), +{ + if let Some(obj) = json.as_object() { + for (key, value) in obj.iter() { + // visiting the key is useful if you're matching against a complex enum member + // but don't really care about its contents + visit(path, &serde_json::Value::String(key.clone())); + path.push(key.clone()); + visit_json_objects(value, path, visit); + path.pop(); + } + } + if let Some(arr) = json.as_array() { + for value in arr.iter() { + visit_json_objects(value, path, visit); + } + return; + } + visit(path, json); +} + #[allow(unused)] -pub fn assert_soft_errors_in_minidump<'a, 'b, T, I>( +#[derive(Debug)] +pub struct ErrorPattern { + value: serde_json::Value, + ancestor: Option, +} + +#[allow(unused)] +impl ErrorPattern { + pub fn value(value: impl Serialize) -> Self { + Self { + value: serde_json::to_value(value).unwrap(), + ancestor: None, + } + } + pub fn with_ancestor(mut self, ancestor: impl ToString) -> Self { + self.ancestor = Some(ancestor.to_string()); + self + } + + fn matches(&self, value: &serde_json::Value, path: &[String]) -> bool { + &self.value == value + && match &self.ancestor { + None => true, + Some(ancestor) => path.contains(ancestor), + } + } +} + +#[allow(unused)] +pub(crate) fn assert_minidump_soft_errors_match_all<'a, T>( dump: &minidump::Minidump<'a, T>, - expected_errors: I, + patterns: &[ErrorPattern], ) where T: std::ops::Deref + 'a, - I: IntoIterator, { let actual_json = read_minidump_soft_errors_or_panic(dump); - let actual_errors = actual_json.as_array().unwrap(); - // Ensure that every error we expect is in the actual list somewhere - for expected_error in expected_errors { - assert!( - actual_errors - .iter() - .any(|actual_error| actual_error == expected_error), - "soft error list missing expected error `{expected_error:#?}`\nError_list: {actual_errors:#?}" - ); + let mut path = vec![]; + // We can't use a HashSet because remove() is too greedy in terms of + // lifetime. + let mut expected: Vec<_> = patterns.iter().collect(); + + visit_json_objects(&actual_json, &mut path, &mut |path, value| { + for i in 0..expected.len() { + let pattern = &expected[i]; + if pattern.matches(value, path) { + expected.remove(i); + return; + } + } + }); + + if !expected.is_empty() { + panic!("Soft errors patterns not found: {:?}", expected); + } +} + +/// Asserts that the soft-error stream contains an error named `variant` anywhere +/// in its (possibly nested) structure. Data-carrying variants appear as object +/// keys and unit variants as strings, so both forms are matched. +#[allow(unused)] +pub fn assert_minidump_contains_soft_error<'a, T>(dump: &minidump::Minidump<'a, T>, variant: &str) +where + T: std::ops::Deref + 'a, +{ + let errors = read_minidump_soft_errors_or_panic(dump); + assert!( + soft_errors_contain(&errors, variant), + "soft error list missing expected error `{variant}`\nError_list: {errors:#?}" + ); +} + +fn soft_errors_contain(value: &serde_json::Value, variant: &str) -> bool { + match value { + serde_json::Value::String(s) => s == variant, + serde_json::Value::Array(items) => { + items.iter().any(|item| soft_errors_contain(item, variant)) + } + serde_json::Value::Object(map) => { + map.contains_key(variant) || map.values().any(|v| soft_errors_contain(v, variant)) + } + _ => false, } } @@ -152,7 +259,10 @@ pub use linux::*; #[allow(unused)] mod linux { use { - minidump_writer::module_reader::{self, ModuleMemoryReadError, ReadModuleMemory}, + minidump_writer::{ + CrashContextExt, Pid, + module_reader::{self, ModuleMemoryReadError, ReadModuleMemory}, + }, std::borrow::Cow, }; pub struct SliceModuleMemoryReader<'a>(pub &'a [u8]); @@ -192,4 +302,37 @@ mod linux { false } } + + pub fn get_dummy_crash_context(tid: Pid) -> CrashContextExt { + let siginfo: libc::signalfd_siginfo = unsafe { std::mem::zeroed() }; + let context = unsafe { std::mem::zeroed() }; + #[cfg(not(target_arch = "arm"))] + let float_state = unsafe { std::mem::zeroed() }; + CrashContextExt { + inner: crash_context::CrashContext { + siginfo, + pid: std::process::id() as _, + tid, + context, + #[cfg(not(target_arch = "arm"))] + float_state, + }, + } + } +} + +fn print_stdio(bytes: &[u8]) { + if let Ok(s) = str::from_utf8(bytes) { + print!("{s}"); + } else { + for (idx, b) in bytes.iter().enumerate() { + if idx == 0 { + print!("{b:02x}"); + } else if idx % 16 == 0 { + print!("\n{b:02x}"); + } else { + print!(" {b:02x}"); + } + } + } } diff --git a/third_party/rust/minidump-writer/tests/linux_minidump_writer.rs b/third_party/rust/minidump-writer/tests/linux_minidump_writer.rs index 3920932258e0..71fbec90ee25 100644 --- a/third_party/rust/minidump-writer/tests/linux_minidump_writer.rs +++ b/third_party/rust/minidump-writer/tests/linux_minidump_writer.rs @@ -6,10 +6,9 @@ use { minidump::*, minidump_common::format::{GUID, MINIDUMP_STREAM_TYPE::*}, minidump_writer::{ - Pid, + CrashContextExt, Pid, app_memory::AppMemory, - crash_context::CrashContext, - maps_reader::{MappingEntry, MappingInfo, SystemMappingInfo}, + maps_reader::{MappingEntry, MappingInfo}, minidump_writer::{MinidumpWriter, MinidumpWriterConfig, errors::WriterError}, module_reader::{self}, }, @@ -35,41 +34,13 @@ impl Context { pub fn minidump_writer(&self, pid: Pid) -> MinidumpWriterConfig { let mut mw = MinidumpWriterConfig::new(pid, pid); if self == &Context::With { - let crash_context = get_crash_context(pid); + let crash_context = get_dummy_crash_context(pid); mw.set_crash_context(crash_context); } mw } } -fn get_ucontext() -> Result { - let mut context = std::mem::MaybeUninit::uninit(); - unsafe { - let res = crash_context::crash_context_getcontext(context.as_mut_ptr()); - if res == -1 { - Err(std::io::Error::last_os_error())?; - } - Ok(context.assume_init()) - } -} - -fn get_crash_context(tid: Pid) -> CrashContext { - let siginfo: libc::signalfd_siginfo = unsafe { std::mem::zeroed() }; - let context = get_ucontext().expect("Failed to get ucontext"); - #[cfg(not(target_arch = "arm"))] - let float_state = unsafe { std::mem::zeroed() }; - CrashContext { - inner: crash_context::CrashContext { - siginfo, - pid: std::process::id() as _, - tid, - context, - #[cfg(not(target_arch = "arm"))] - float_state, - }, - } -} - macro_rules! contextual_test { ( $(#[$attr:meta])? fn $name:ident ($ctx:ident : Context) $body:block ) => { mod $name { @@ -156,10 +127,6 @@ contextual_test! { offset: 0, permissions: MMPermissions::READ | MMPermissions::WRITE, name: Some("a fake mapping".into()), - system_mapping_info: SystemMappingInfo { - start_address: mmap_addr, - end_address: mmap_addr + memory_size, - }, }; let identifier = vec![ @@ -233,6 +200,51 @@ contextual_test! { } } +/// A module list starts with the executable and doesn't have overlaps +#[test] +fn module_list_properties() { + let mut child = start_child_and_wait_for_threads(1); + let pid = child.id() as i32; + + let executable = std::fs::read_link(format!("/proc/{pid}/exe")).expect("failed to read exe"); + + let mut tmpfile = tempfile::Builder::new() + .prefix("module_list") + .tempfile() + .unwrap(); + + MinidumpWriterConfig::new(pid, pid) + .write(&mut tmpfile) + .expect("could not write minidump"); + + child.kill().expect("Failed to kill process"); + child.wait().expect("Failed to wait for child"); + + let dump = Minidump::read_path(tmpfile.path()).expect("failed to read minidump"); + let module_list: MinidumpModuleList = dump + .get_stream() + .expect("Couldn't find stream MinidumpModuleList"); + let modules: Vec<_> = module_list.iter().collect(); + assert!(!modules.is_empty(), "no modules in the dump"); + + // Executable is first + assert_eq!(modules[0].code_file(), executable.to_string_lossy()); + + // Get the ranges ordered by their start + let mut ranges: Vec<_> = modules + .iter() + .map(|module| (module.base_address(), module.size())) + .collect(); + ranges.sort_unstable(); + + // Test for overlap + for pair in ranges.windows(2) { + let (base, size) = pair[0]; + let (next_base, _) = pair[1]; + assert!(base + size <= next_base); + } +} + contextual_test! { fn write_with_additional_memory(context: Context) { let mut child = start_child_and_return(&["spawn_alloc_wait"]); @@ -300,9 +312,7 @@ contextual_test! { contextual_test! { fn skip_if_requested(context: Context) { let expected_errors = vec![ - json!({ - "InitErrors": ["PrincipalMappingNotReferenced"] - }), + ErrorPattern::value("PrincipalMappingNotReferenced").with_ancestor("InitErrors") ]; let num_of_threads = 1; @@ -340,7 +350,7 @@ contextual_test! { // Ensure the MozSoftErrors stream contains the expected errors let dump = Minidump::read_path(tmpfile.path()).expect("failed to read minidump"); - assert_soft_errors_in_minidump(&dump, &expected_errors); + assert_minidump_soft_errors_match_all(&dump, &expected_errors); } } diff --git a/third_party/rust/minidump-writer/tests/linux_minidump_writer_soft_error.rs b/third_party/rust/minidump-writer/tests/linux_minidump_writer_soft_error.rs index 0b2bd1a0a19a..d4a999d7a922 100644 --- a/third_party/rust/minidump-writer/tests/linux_minidump_writer_soft_error.rs +++ b/third_party/rust/minidump-writer/tests/linux_minidump_writer_soft_error.rs @@ -1,11 +1,8 @@ #![cfg(any(target_os = "linux", target_os = "android"))] -use { - common::*, - minidump::Minidump, - minidump_writer::{FailSpotName, minidump_writer::MinidumpWriterConfig}, - serde_json::json, -}; +use common::*; +use minidump::Minidump; +use minidump_writer::{FailSpotName, minidump_writer::MinidumpWriterConfig}; mod common; @@ -36,41 +33,6 @@ fn soft_error_stream() { #[test] fn soft_error_stream_content() { - let expected_errors = vec![ - json!({"InitErrors": [ - {"StopProcessFailed": - {"Stop": - {"Local": - {"SigStopFailed": 1} - } - } - }, - {"FillMissingAuxvInfoErrors": ["InvalidFormat"]}, - {"EnumerateThreadsErrors": [ - {"ReadThreadNameFailed": "\ - Custom {\n \ - kind: Other,\n \ - error: Local(\n \ - OpenFileFailed(\n \ - 1,\n \ - ),\n \ - ),\n\ - }" - } - ]}, - {"SuspendThreadsErrors": [{"PtraceAttachError": [1234, libc::EPERM]}]} - ]}), - json!({"WriteSystemInfoErrors": [ - {"WriteCpuInformationFailed": { - "ReadFileError": { - "Local": { - "OpenFileFailed": 1 - } - } - }} - ]}), - ]; - let mut child = start_child_and_wait_for_threads(1); let pid = child.id() as i32; @@ -97,7 +59,89 @@ fn soft_error_stream_content() { child.kill().expect("Failed to kill process"); child.wait().expect("Failed to wait on killed process"); - // Ensure the MozSoftErrors stream contains the expected errors let dump = Minidump::read_path(tmpfile.path()).expect("failed to read minidump"); - assert_soft_errors_in_minidump(&dump, &expected_errors); + + // Ensure the MozSoftErrors stream contains the expected errors + assert_minidump_soft_errors_match_all( + &dump, + &[ + ErrorPattern::value(libc::EPERM).with_ancestor("StopProcessFailed"), + // AuxvError is not reachable so use the string form instead + ErrorPattern::value("InvalidFormat").with_ancestor("FillMissingAuxvInfoErrors"), + ErrorPattern::value("ReadThreadNameFailed"), + ErrorPattern::value(libc::EPERM).with_ancestor("SuspendThreadsErrors"), + ErrorPattern::value(libc::EPERM).with_ancestor("WriteCpuInformationFailed"), + ], + ); +} + +#[test] +fn thread_stack_pointer_unmapped_soft_error() { + let mut child = start_child_and_wait_for_threads(1); + let pid = child.id() as i32; + + let mut tmpfile = tempfile::Builder::new() + .prefix("stack_pointer_unmapped") + .tempfile() + .unwrap(); + + let mut fail_client = FailSpotName::testing_client(); + fail_client.set_enabled(FailSpotName::StackPointerMapping, true); + + MinidumpWriterConfig::new(pid, pid) + .write(&mut tmpfile) + .expect("could not write minidump"); + child.kill().expect("Failed to kill process"); + child.wait().expect("Failed to wait on killed process"); + + let dump = Minidump::read_path(tmpfile.path()).expect("failed to read minidump"); + assert_minidump_contains_soft_error(&dump, "GetStackInfoFailed"); +} + +#[test] +fn thread_stack_unreadable_soft_error() { + let mut child = start_child_and_wait_for_threads(1); + let pid = child.id() as i32; + + let mut tmpfile = tempfile::Builder::new() + .prefix("stack_unreadable") + .tempfile() + .unwrap(); + + let mut fail_client = FailSpotName::testing_client(); + fail_client.set_enabled(FailSpotName::ThreadStackCopy, true); + + MinidumpWriterConfig::new(pid, pid) + .write(&mut tmpfile) + .expect("could not write minidump"); + child.kill().expect("Failed to kill process"); + child.wait().expect("Failed to wait on killed process"); + + let dump = Minidump::read_path(tmpfile.path()).expect("failed to read minidump"); + assert_minidump_contains_soft_error(&dump, "CopyFromProcessError"); +} + +#[test] +fn crashing_thread_ip_memory_unreadable_soft_error() { + let mut child = start_child_and_wait_for_threads(1); + let pid = child.id() as i32; + + let mut tmpfile = tempfile::Builder::new() + .prefix("ip_memory_unreadable") + .tempfile() + .unwrap(); + + let mut fail_client = FailSpotName::testing_client(); + fail_client.set_enabled(FailSpotName::CrashingThreadIpCopy, true); + + let mut config = MinidumpWriterConfig::new(pid, pid); + config.set_crash_context(get_dummy_crash_context(pid)); + config + .write(&mut tmpfile) + .expect("could not write minidump"); + child.kill().expect("Failed to kill process"); + child.wait().expect("Failed to wait on killed process"); + + let dump = Minidump::read_path(tmpfile.path()).expect("failed to read minidump"); + assert_minidump_contains_soft_error(&dump, "CopyFromProcessError"); } diff --git a/third_party/rust/minidump-writer/tests/mac_minidump_writer.rs b/third_party/rust/minidump-writer/tests/mac_minidump_writer.rs index 1087951af77a..4a9293263c5f 100644 --- a/third_party/rust/minidump-writer/tests/mac_minidump_writer.rs +++ b/third_party/rust/minidump-writer/tests/mac_minidump_writer.rs @@ -7,6 +7,7 @@ use { MinidumpModuleList, MinidumpSystemInfo, MinidumpThreadList, }, minidump_writer::minidump_writer::MinidumpWriter, + std::os::unix::process::ExitStatusExt, }; mod common; @@ -67,6 +68,11 @@ fn capture_minidump(name: &str, exception_kind: u32) -> Captured<'_> { .expect("failed to send ack"); child.kill().expect("failed to kill child"); + // Reap child + let waitres = child.wait().expect("Failed to wait for child"); + let status = waitres.signal().expect("Child did not die due to signal"); + assert_eq!(waitres.code(), None); + assert_eq!(status, libc::SIGKILL); let minidump = Minidump::read_path(tmpfile.path()).expect("failed to read minidump"); diff --git a/third_party/rust/minidump-writer/tests/ptrace_dumper.rs b/third_party/rust/minidump-writer/tests/ptrace_dumper.rs index cdbb6f7939f9..efad47f92dde 100644 --- a/third_party/rust/minidump-writer/tests/ptrace_dumper.rs +++ b/third_party/rust/minidump-writer/tests/ptrace_dumper.rs @@ -116,7 +116,7 @@ fn thread_list_from_parent() { for (idx, curr_thread) in dumper.threads.iter().enumerate() { println!("curr_thread: {curr_thread:?}"); let info = dumper - .get_thread_info_by_index(idx) + .get_thread_info_by_index(idx, error_graph::strategy::DontCare) .expect("Could not get thread info by index"); let (_valid_stack_ptr, stack_len) = dumper .get_stack_info(info.stack_pointer) @@ -293,7 +293,7 @@ fn sanitizes_stack_copies() { assert_eq!(dumper.threads.len(), num_of_threads); let thread_info = dumper - .get_thread_info_by_index(0) + .get_thread_info_by_index(0, error_graph::strategy::DontCare) .expect("Couldn't find thread_info"); let defaced; @@ -338,7 +338,7 @@ fn sanitizes_stack_copies() { // The instruction pointer definitely should point into an executable mapping. let instr_ptr = thread_info.get_instruction_pointer(); let mapping_info = dumper - .find_mapping_no_bias(instr_ptr) + .find_mapping(instr_ptr) .expect("Failed to find mapping info"); assert!(mapping_info.is_executable()); diff --git a/third_party/rust/minidump-writer/tests/windows_minidump_writer.rs b/third_party/rust/minidump-writer/tests/windows_minidump_writer.rs index 548f6e87a16b..3af18bdd30e2 100644 --- a/third_party/rust/minidump-writer/tests/windows_minidump_writer.rs +++ b/third_party/rust/minidump-writer/tests/windows_minidump_writer.rs @@ -171,7 +171,11 @@ fn dump_external_process() { .expect("failed to write minidump"); child.kill().expect("failed to kill child"); + // Reap child + child.wait().expect("Failed to wait for child"); + // Clean up the zombie child. + child.wait().expect("failed to wait child"); let md = Minidump::read_path(tmpfile.path()).expect("failed to read minidump"); let _: MinidumpThreadList = md.get_stream().expect("Couldn't find MinidumpThreadList"); diff --git a/third_party/rust/process-backend/.cargo-checksum.json b/third_party/rust/process-backend/.cargo-checksum.json index 6787a57e4d00..952861a34d21 100644 --- a/third_party/rust/process-backend/.cargo-checksum.json +++ b/third_party/rust/process-backend/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"f9d1e68bc8475f1697b1db4819c5f56fdae0d74d8e3bd69e9d4d0e4f2866f934","src/lib.rs":"68df3ce07860f4906e661839395d14778bf9bcc5db9724ad937929c713a6b041","src/local/error.rs":"7bd22342592178779bc54bbd5d6d64410900eef6a0d52b52ed2164ec6581d7a1","src/local/mod.rs":"c2bfc6f964e2654472ca3e305a9dff8206aa081691c7c4d50e611455b2d4cd85","src/local/module_reader.rs":"ee8d897a600556504f1558eb5bfb5cb2a272ab50865cfc2b1265aa98c84bf7fb","src/local/syscall_invoker.rs":"a3b333c6d9c9f66f2f0b98e91e2677df667ef99f3b3038c3a823c91fcc374167","src/regs.rs":"54cc917765fb3026efcaba8ded8a7e457c4dddca102e8a9a214e86faa1e0ba31"},"package":null} \ No newline at end of file +{"files":{"CHANGELOG.md":"97d489f8a23585b32373cae606921baa6831227cb4c43499463d6b4f430d8c34","Cargo.toml":"a81025b251e527c2eb6efd47c294b4f507061b1af0599bab5eff30686901925c","LICENSE":"1ecdd8e8977af83c07c5f97bec87b47d27059b7ea323ca3160fbfa2314f5d99c","release.toml":"ed4ec6d0e3744b28d47888423856249697d8477223cfa4023b2e41f4ffe9daf7","src/drop_fail_handler.rs":"a8ec9a82694639cb8254a27f8f5a302ba71479408a6b1cafd6cccfd5d70d3dbe","src/lib.rs":"abdf25dee1aea02d675bb73aee56c6a645ad3f693247b65391c058a5e2591843","src/local/error.rs":"0ca89bb4a0e8865fd17970157170ecfedadeb6a545686c7ec78a81e189688f55","src/local/mod.rs":"ce6fa793304ab4010f6aa7d89614c6e68ffef027a658ec2d2fca492e55684f3d","src/local/module_reader.rs":"98f5e6098d4abadbc392fe80c7e2cc7dbb8b88538dbd2524a6dd9242e650f783","src/local/syscall_invoker.rs":"498a27f7554a67dbaab0924fae61ba3438a17ecf83cd9912ea8cc5aa6fb26da2","src/regs.rs":"55d9a71ef2d9f7560ddab9a15efbd6c3b821d580cec06f3cd96c42e3b04ce9e9","src/wrapper.rs":"8d045c58182d94851a949fad36707ff9fee2d6986b278cda94968cd27fd9055f"},"package":null} \ No newline at end of file diff --git a/third_party/rust/process-backend/CHANGELOG.md b/third_party/rust/process-backend/CHANGELOG.md new file mode 100644 index 000000000000..bf77b603952d --- /dev/null +++ b/third_party/rust/process-backend/CHANGELOG.md @@ -0,0 +1,17 @@ + + +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + +## [Unreleased] - ReleaseDate +## [0.1.0] - 2026-07-20 +### Added +- Initial release. + + +[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/process-backend-0.1.0...HEAD +[0.1.0]: https://github.com/rust-minidump/minidump-writer/releases/tag/process-backend-0.1.0 diff --git a/third_party/rust/process-backend/Cargo.toml b/third_party/rust/process-backend/Cargo.toml index dd7e3a4e2bf3..c9f38157b01b 100644 --- a/third_party/rust/process-backend/Cargo.toml +++ b/third_party/rust/process-backend/Cargo.toml @@ -13,13 +13,14 @@ edition = "2024" rust-version = "1.88.0" name = "process-backend" -version = "0.0.0" +version = "0.1.0" build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false +description = "Providers helpers for reading process memory specialized for minidump-writer" homepage = "https://github.com/rust-minidump/minidump-writer" readme = false license = "MIT" @@ -34,11 +35,10 @@ path = "src/lib.rs" [target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies.libc] version = "0.2" - -[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies.log] -version = "0.4" +default-features = false [target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies.process-reader] +version = "0.1.0" path = "../../process-reader" features = ["serde"] diff --git a/third_party/rust/process-backend/LICENSE b/third_party/rust/process-backend/LICENSE new file mode 100644 index 000000000000..6f9ec1352ea4 --- /dev/null +++ b/third_party/rust/process-backend/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 + +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 included in all +copies or 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. diff --git a/third_party/rust/process-backend/release.toml b/third_party/rust/process-backend/release.toml new file mode 100644 index 000000000000..99df5ccd9b90 --- /dev/null +++ b/third_party/rust/process-backend/release.toml @@ -0,0 +1,10 @@ +pre-release-commit-message = "Release process-backend-{{version}}" +tag-message = "Release process-backend-{{version}}" +tag-name = "process-backend-{{version}}" +pre-release-replacements = [ + { file = "CHANGELOG.md", search = "Unreleased", replace = "{{version}}" }, + { file = "CHANGELOG.md", search = "\\.\\.\\.HEAD", replace = "...{{tag_name}}" }, + { file = "CHANGELOG.md", search = "ReleaseDate", replace = "{{date}}" }, + { file = "CHANGELOG.md", search = "", replace = "\n## [Unreleased] - ReleaseDate" }, + { file = "CHANGELOG.md", search = "", replace = "\n[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/{{tag_name}}...HEAD" }, +] diff --git a/third_party/rust/process-backend/src/drop_fail_handler.rs b/third_party/rust/process-backend/src/drop_fail_handler.rs new file mode 100644 index 000000000000..b9056ae73805 --- /dev/null +++ b/third_party/rust/process-backend/src/drop_fail_handler.rs @@ -0,0 +1,54 @@ +//! Set a custom handler for when a Drop failure occurs +//! +//! Normally, there is not much that can be done when an error occurs during execution of `drop()` +//! -- Common strategies are to just ignore it, or to just log it and ignore it. +//! +//! We prefer the latter approach, but the issue is that if a Rust global logger has been set up +//! in the crashed process that will run the Executor, that could result in `log` being used in +//! a signal handler context. And since common logging behavior is to print to stderr, that will +//! almost-certainly cause a deadlock or some kind of other re-entrancy issue. +//! +//! Instead, we don't prescribe a behavior - We allow the user of minidump-writer to set their +//! own handler for failed `drop()` calls. If the user knows it's safe to log or print or +//! whatever, they can do that. +//! +//! Note that using [`install_global()`] to install a new handler will always overwrite any +//! previously-installed handler. This is intentional, as the user of this crate may want to +//! disable a previously-installed handler after a crash occurs (if that handler would cause +//! re-entrancy issues) + +use core::sync::atomic::{AtomicPtr, Ordering}; + +static HANDLER: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); + +pub struct Handler { + pub(crate) f: for<'a> fn(core::fmt::Arguments<'a>), +} + +impl Handler { + /// Decorate the given function as a potential global Drop handler + pub const fn new(f: for<'a> fn(core::fmt::Arguments<'a>)) -> Self { + Self { f } + } + /// Install this handler as the new global Drop handler + /// + /// Will overwrite any previously installed handler + pub fn install_global(&'static self) { + HANDLER.store((self as *const Handler).cast_mut(), Ordering::Release); + } +} + +pub(crate) fn get() -> Option<&'static Handler> { + let ptr: *const Handler = HANDLER.load(Ordering::Acquire).cast_const(); + if ptr.is_null() { + None + } else { + Some(unsafe { &*ptr }) + } +} + +macro_rules! report_drop_failed(($($arg: tt)*) => {{ + if let Some(handler) = $crate::drop_fail_handler::get() { + (handler.f)(::core::format_args!($($arg)*)); + } +}}); diff --git a/third_party/rust/process-backend/src/lib.rs b/third_party/rust/process-backend/src/lib.rs index 00d9371058a4..38b513e281b9 100644 --- a/third_party/rust/process-backend/src/lib.rs +++ b/third_party/rust/process-backend/src/lib.rs @@ -1,9 +1,99 @@ #![no_std] #![cfg(any(target_os = "linux", target_os = "android"))] +use core::ffi::CStr; +use regs::*; + +pub use drop_fail_handler::Handler as DropFailHandler; +pub use wrapper::Stat; + +#[macro_use] +mod drop_fail_handler; + pub mod local; pub mod regs; -/// This is the longest path length we guarantee we can handle, since we won't be able to allocate -/// in the fork of the crashed process. We can increase if necessary. -pub const MAX_PATH_LEN: usize = 256; +mod wrapper; + +pub type Result = core::result::Result; + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +pub const PTRACE_DATA_LEN: usize = core::mem::size_of::(); + +pub trait Backend: core::fmt::Debug { + type ProcessReader<'a>: ProcessReader + where + Self: 'a; + type FileReader<'a>: FileReader + where + Self: 'a; + type DirReader<'a>: DirReader + where + Self: 'a; + type MappedModuleMemoryReader<'a>: MappedModuleMemoryReader + where + Self: 'a; + + fn pid(&self) -> Result; + fn process_reader<'a>(&'a self) -> Self::ProcessReader<'a>; + fn stop_process(&self) -> Result<()>; + fn continue_process(&self) -> Result<()>; + fn suspend_thread(&self, tid: libc::pid_t) -> Result<()>; + fn resume_thread(&self, tid: libc::pid_t) -> Result<()>; + fn map_module_into_memory<'a>( + &'a self, + path: &CStr, + offset: u64, + ) -> Result>; + fn stat_file(&self, path: &CStr) -> Result; + fn read_file<'a>(&'a self, path: &CStr) -> Result>; + fn read_dir<'a>(&'a self, path: &CStr) -> Result>; + fn read_link(&self, path: &CStr, buf: &mut [u8]) -> Result; + fn get_gen_regs(&self, tid: libc::pid_t) -> Result; + fn get_fp_regs(&self, tid: libc::pid_t) -> Result; + + #[cfg(target_arch = "x86")] + fn get_fpx_regs(&self, tid: libc::pid_t) -> Result; + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn ptrace_peekuser(&self, addr: usize) -> Result<[u8; PTRACE_DATA_LEN]>; + + fn force_process_reader_kind(&mut self, kind: ProcessReaderKind) -> Result<()>; + + #[cfg(feature = "testing")] + fn fail_one_syscall_with(&self, errno: core::ffi::c_int); +} + +pub trait FileReader: core::fmt::Debug { + fn read(&mut self, buf: &mut [u8]) -> Result; +} + +pub trait DirReader: core::fmt::Debug { + fn read_next_name(&mut self, buf: &mut [u8]) -> Result; +} + +pub trait ProcessReader: core::fmt::Debug { + fn read_at(&self, address: usize, buf: &mut [u8]) -> Result; +} + +pub trait MappedModuleMemoryReader: core::fmt::Debug { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result; + fn len(&self) -> Result; + fn is_empty(&self) -> Result; +} + +#[derive(Debug, serde::Deserialize, serde::Serialize)] +pub enum ProcessReaderKind { + Unspecified, + VirtualMem, + File, + Ptrace, +} + +#[derive(Debug, thiserror::Error, serde::Deserialize, serde::Serialize)] +pub enum Error { + #[error("there was a failure making a direct syscall")] + Local(#[source] local::Error), + #[error("buffer was too small to contain the result")] + BufferTooSmall, +} diff --git a/third_party/rust/process-backend/src/local/error.rs b/third_party/rust/process-backend/src/local/error.rs index 79feefc3a5cc..2eceb220ed9b 100644 --- a/third_party/rust/process-backend/src/local/error.rs +++ b/third_party/rust/process-backend/src/local/error.rs @@ -34,8 +34,13 @@ pub enum Error { BufferTooSmall, #[error("not supported")] NotSupported, - #[error("failed to get registers: {0}")] - GetRegistersFailed(c_int), + #[error( + "failed to get registers. getregset_error: `{getregset_error}`, legacy_error: `{legacy_error}`" + )] + GetRegistersFailed { + getregset_error: super::PtraceGetRegSetError, + legacy_error: super::PtraceGetRegsLegacyError, + }, #[error("failed to map memory: {0}")] MMapfailed(c_int), #[error("the start position of a mapping is past its end position")] diff --git a/third_party/rust/process-backend/src/local/mod.rs b/third_party/rust/process-backend/src/local/mod.rs index c8c7de065fe9..922e7027a958 100644 --- a/third_party/rust/process-backend/src/local/mod.rs +++ b/third_party/rust/process-backend/src/local/mod.rs @@ -1,4 +1,8 @@ -use crate::regs::*; +use crate::{ + ProcessReaderKind, Stat, + regs::*, + wrapper::{OwnedFd, errno, set_errno}, +}; use core::{ cell::RefCell, ffi::{CStr, c_int, c_long, c_void}, @@ -7,21 +11,19 @@ use core::{ use libc::pid_t; use syscall_invoker::SyscallInvoker; -pub use self::{error::Error, module_reader::MappedModuleMemoryReader}; +pub use error::Error; +pub use module_reader::MappedModuleMemoryReader; mod error; mod module_reader; mod syscall_invoker; -#[cfg(target_env = "gnu")] -type PtraceRequestType = core::ffi::c_uint; - -#[cfg(not(target_env = "gnu"))] -type PtraceRequestType = core::ffi::c_int; +pub type Result = core::result::Result; #[derive(Debug)] pub struct Backend { pid: pid_t, + process_reader: process_reader::ProcessReader, syscall_invoker: RefCell, } @@ -29,25 +31,29 @@ impl Backend { pub fn new(pid: libc::pid_t) -> Self { Self { pid, + process_reader: process_reader::ProcessReader::new(pid), syscall_invoker: Default::default(), } } - pub fn process_reader(&self) -> ProcessReader { - ProcessReader(process_reader::ProcessReader::new(self.pid)) + pub fn pid(&self) -> libc::pid_t { + self.pid } - pub fn stop_process(&self) -> Result<(), Error> { + pub fn process_reader(&self) -> ProcessReader<'_> { + ProcessReader(&self.process_reader) + } + pub fn stop_process(&self) -> Result<()> { self.standard_syscall(|| unsafe { libc::kill(self.pid, libc::SIGSTOP) }) .map_err(Error::SigStopFailed)?; Ok(()) } - pub fn continue_process(&self) -> Result<(), Error> { + pub fn continue_process(&self) -> Result<()> { self.standard_syscall(|| unsafe { libc::kill(self.pid, libc::SIGCONT) }) .map_err(Error::SigContFailed)?; Ok(()) } - pub fn suspend_thread(&self, tid: libc::pid_t) -> Result<(), Error> { + pub fn suspend_thread(&self, tid: libc::pid_t) -> Result<()> { self.standard_syscall(|| unsafe { ptrace(libc::PTRACE_ATTACH, tid, ptr::null_mut(), ptr::null_mut()) }) @@ -89,7 +95,7 @@ impl Backend { Ok(()) } - pub fn resume_thread(&self, tid: libc::pid_t) -> Result<(), Error> { + pub fn resume_thread(&self, tid: libc::pid_t) -> Result<()> { self.ptrace_detach(tid) } @@ -97,22 +103,24 @@ impl Backend { &self, path: &CStr, offset: u64, - ) -> Result { + ) -> Result { MappedModuleMemoryReader::new(&mut self.syscall_invoker.borrow_mut(), path, offset) } - pub fn stat_file(&self, path: &CStr) -> Result { + pub fn stat_file(&self, path: &CStr) -> Result { let mut output = unsafe { mem::zeroed::() }; self.standard_syscall(|| unsafe { libc::stat(path.as_ptr(), &mut output) }) .map_err(Error::StatFailed)?; - Ok(output) + Ok(Stat { + st_mode: output.st_mode, + }) } - pub fn read_file(&self, path: &CStr) -> Result { + pub fn read_file(&self, path: &CStr) -> Result { self.open_file(path).map(FileReader) } - pub fn read_dir(&self, path: &CStr) -> Result { + pub fn read_dir(&self, path: &CStr) -> Result { self.special_syscall(|| unsafe { let dirp = libc::opendir(path.as_ptr()); if dirp.is_null() { @@ -124,7 +132,7 @@ impl Backend { .map_err(Error::OpenDirFailed) } - pub fn read_link(&self, path: &CStr, buf: &mut [u8]) -> Result { + pub fn read_link(&self, path: &CStr, buf: &mut [u8]) -> Result { let bytes_read = self .standard_syscall(|| unsafe { libc::readlink(path.as_ptr(), buf.as_mut_ptr().cast(), buf.len()) @@ -139,31 +147,25 @@ impl Backend { Ok(bytes_read) } - pub fn get_gen_regs(&self, tid: libc::pid_t) -> Result { - self.getregset(tid).or_else(|_| self.getregs(tid)) + pub fn get_gen_regs(&self, tid: libc::pid_t) -> Result { + self.get_regs::(tid) } - - pub fn get_fp_regs(&self, tid: libc::pid_t) -> Result { - self.getfpregset(tid).or_else(|_| self.getfpregs(tid)) + pub fn get_fp_regs(&self, tid: libc::pid_t) -> Result { + self.get_regs::(tid) } #[cfg(target_arch = "x86")] - pub fn get_fpx_regs(&self, tid: libc::pid_t) -> Result { - const PTRACE_GETFPXREGS: PtraceRequestType = 18; - unsafe { self.ptrace_getregs::(PTRACE_GETFPXREGS, tid) } + pub fn get_fpx_regs(&self, tid: libc::pid_t) -> Result { + self.get_regs::(tid) } #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - pub fn ptrace_peekuser( - &self, - pid: libc::pid_t, - addr: usize, - ) -> Result<[u8; mem::size_of::()], Error> { + pub fn ptrace_peekuser(&self, addr: usize) -> Result<[u8; crate::PTRACE_DATA_LEN]> { self.special_syscall(|| unsafe { set_errno(0); let rv = ptrace( libc::PTRACE_PEEKUSER, - pid, + self.pid, addr as *mut _, core::ptr::null_mut(), ); @@ -175,21 +177,20 @@ impl Backend { .map_err(Error::PtracePeekUserFailed) } - pub fn process_reader_for_virtual_mem(&self) -> ProcessReader { - ProcessReader(process_reader::ProcessReader::for_virtual_mem(self.pid)) + pub fn force_process_reader_kind(&mut self, kind: ProcessReaderKind) -> Result<()> { + use ProcessReaderKind as K; + self.process_reader = match kind { + K::Unspecified => process_reader::ProcessReader::new(self.pid), + K::VirtualMem => process_reader::ProcessReader::for_virtual_mem(self.pid), + K::File => { + process_reader::ProcessReader::for_file(self.pid).map_err(Error::ProcessReader)? + } + K::Ptrace => process_reader::ProcessReader::for_ptrace(self.pid), + }; + Ok(()) } - pub fn process_reader_for_file(&self) -> Result { - process_reader::ProcessReader::for_file(self.pid) - .map(ProcessReader) - .map_err(Error::ProcessReader) - } - - pub fn process_reader_for_ptrace(&self) -> ProcessReader { - ProcessReader(process_reader::ProcessReader::for_ptrace(self.pid)) - } - - fn open_file(&self, path: &CStr) -> Result { + fn open_file(&self, path: &CStr) -> Result { self.standard_syscall(|| unsafe { libc::open(path.as_ptr(), libc::O_RDONLY | libc::O_CLOEXEC, 0) }) @@ -197,94 +198,78 @@ impl Backend { .map_err(Error::OpenFileFailed) } - fn getregset(&self, _pid: libc::pid_t) -> Result { - #[cfg(target_arch = "arm")] - { - Err(Error::NotSupported) - } - #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))] - { - const NT_PRSTATUS: usize = 1; - self.ptrace_getregset(NT_PRSTATUS, _pid) - } + fn get_regs(&self, tid: libc::pid_t) -> Result { + let getregset_error = match self.ptrace_getregset::(tid) { + Ok(output) => return Ok(output), + Err(e) => e, + }; + + let legacy_error = match self.ptrace_getregs_legacy::(tid) { + Ok(output) => return Ok(output), + Err(e) => e, + }; + + Err(Error::GetRegistersFailed { + getregset_error, + legacy_error, + }) } - fn getregs(&self, pid: libc::pid_t) -> Result { - const PTRACE_GETREGS: PtraceRequestType = 12; - unsafe { self.ptrace_getregs::(PTRACE_GETREGS, pid) } - } - - fn getfpregset(&self, pid: libc::pid_t) -> Result { - #[cfg(target_arch = "arm")] - { - const NT_ARM_VFP: usize = 0x400; - self.ptrace_getregset(NT_ARM_VFP, pid) - } - #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))] - { - const NT_PRFPREGSET: usize = 2; - self.ptrace_getregset(NT_PRFPREGSET, pid) - } - } - - fn getfpregs(&self, _pid: libc::pid_t) -> Result { - #[cfg(target_arch = "arm")] - { - Err(Error::NotSupported) - } - #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))] - { - const PTRACE_GETFPREGS: PtraceRequestType = 14; - unsafe { self.ptrace_getregs::(PTRACE_GETFPREGS, _pid) } - } - } - - /// Safety: RequestType and T must agree on the size of the returned type - unsafe fn ptrace_getregs( + fn ptrace_getregs_legacy( &self, - request: PtraceRequestType, - pid: libc::pid_t, - ) -> Result { - let mut output = mem::MaybeUninit::::uninit(); + tid: libc::pid_t, + ) -> core::result::Result { + let Some(request) = T::LEGACY_REQUEST else { + return Err(PtraceGetRegsLegacyError::NotSupported); + }; + + let mut output = T::Output::default(); self.standard_syscall(|| unsafe { ptrace( request, - pid, + tid, core::ptr::null_mut(), - output.as_mut_ptr().cast(), + (&raw mut output).cast(), ) }) - .map_err(Error::GetRegistersFailed)?; - Ok(unsafe { output.assume_init() }) + .map_err(PtraceGetRegsLegacyError::PtraceFailed)?; + Ok(output) } - fn ptrace_getregset(&self, regset_type: usize, pid: libc::pid_t) -> Result { - let mut output = mem::MaybeUninit::::uninit(); + fn ptrace_getregset( + &self, + tid: libc::pid_t, + ) -> core::result::Result { + let output_size = size_of::(); + assert!(T::KERNEL_SIZE <= output_size); + + let mut output = T::Output::default(); let mut io = libc::iovec { - iov_base: output.as_mut_ptr().cast(), - iov_len: mem::size_of::(), + iov_base: (&raw mut output).cast(), + iov_len: T::KERNEL_SIZE, }; self.standard_syscall(|| unsafe { ptrace( libc::PTRACE_GETREGSET, - pid, - regset_type as *mut _, + tid, + T::NOTE.0 as *mut _, (&raw mut io).cast(), ) }) - .map_err(Error::GetRegistersFailed)?; + .map_err(PtraceGetRegSetError::PtraceFailed)?; - // PTRACE_GETREGSET returns the number of bytes actually read in iov_len. Need to ensure - // all bytes of T are actually initialized - if io.iov_len != mem::size_of::() { - Err(Error::GetRegistersFailed(libc::EINVAL))?; + if T::KERNEL_SIZE != io.iov_len { + return Err(PtraceGetRegSetError::UnexpectedRegisterSetSize( + T::KERNEL_SIZE, + io.iov_len, + )); } - Ok(unsafe { output.assume_init() }) + Ok(output) } - fn ptrace_detach(&self, tid: libc::pid_t) -> Result<(), Error> { + fn ptrace_detach(&self, tid: libc::pid_t) -> Result<()> { self.standard_syscall(|| unsafe { ptrace(libc::PTRACE_DETACH, tid, ptr::null_mut(), ptr::null_mut()) }) @@ -292,7 +277,7 @@ impl Backend { Ok(()) } - fn standard_syscall(&self, f: F) -> Result + fn standard_syscall(&self, f: F) -> core::result::Result where F: FnOnce() -> T, T: From + core::cmp::PartialEq, @@ -300,9 +285,9 @@ impl Backend { self.syscall_invoker.borrow_mut().invoke_standard(f) } - fn special_syscall(&self, f: F) -> Result + fn special_syscall(&self, f: F) -> core::result::Result where - F: FnOnce() -> Result, + F: FnOnce() -> core::result::Result, { self.syscall_invoker.borrow_mut().invoke(f) } @@ -315,18 +300,103 @@ impl Backend { } } +impl crate::Backend for Backend { + type ProcessReader<'a> = ProcessReader<'a>; + + type FileReader<'a> = FileReader; + + type DirReader<'a> = DirReader; + + type MappedModuleMemoryReader<'a> = MappedModuleMemoryReader; + + fn pid(&self) -> crate::Result { + Ok(Backend::pid(self)) + } + + fn process_reader<'a>(&'a self) -> Self::ProcessReader<'a> { + Backend::process_reader(self) + } + + fn stop_process(&self) -> crate::Result<()> { + Backend::stop_process(self).map_err(crate::Error::Local) + } + + fn continue_process(&self) -> crate::Result<()> { + Backend::continue_process(self).map_err(crate::Error::Local) + } + + fn suspend_thread(&self, tid: libc::pid_t) -> crate::Result<()> { + Backend::suspend_thread(self, tid).map_err(crate::Error::Local) + } + + fn resume_thread(&self, tid: libc::pid_t) -> crate::Result<()> { + Backend::resume_thread(self, tid).map_err(crate::Error::Local) + } + + fn map_module_into_memory<'a>( + &'a self, + path: &CStr, + offset: u64, + ) -> crate::Result> { + Backend::map_module_into_memory(self, path, offset).map_err(crate::Error::Local) + } + + fn stat_file(&self, path: &CStr) -> crate::Result { + Backend::stat_file(self, path).map_err(crate::Error::Local) + } + + fn read_file<'a>(&'a self, path: &CStr) -> crate::Result> { + Backend::read_file(self, path).map_err(crate::Error::Local) + } + + fn read_dir<'a>(&'a self, path: &CStr) -> crate::Result> { + Backend::read_dir(self, path).map_err(crate::Error::Local) + } + + fn read_link(&self, path: &CStr, buf: &mut [u8]) -> crate::Result { + Backend::read_link(self, path, buf).map_err(crate::Error::Local) + } + + fn get_gen_regs(&self, tid: libc::pid_t) -> crate::Result { + Backend::get_gen_regs(self, tid).map_err(crate::Error::Local) + } + + fn get_fp_regs(&self, tid: libc::pid_t) -> crate::Result { + Backend::get_fp_regs(self, tid).map_err(crate::Error::Local) + } + + #[cfg(target_arch = "x86")] + fn get_fpx_regs(&self, tid: libc::pid_t) -> crate::Result { + Backend::get_fpx_regs(self, tid).map_err(crate::Error::Local) + } + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn ptrace_peekuser(&self, addr: usize) -> crate::Result<[u8; crate::PTRACE_DATA_LEN]> { + Backend::ptrace_peekuser(self, addr).map_err(crate::Error::Local) + } + + fn force_process_reader_kind(&mut self, kind: ProcessReaderKind) -> crate::Result<()> { + Backend::force_process_reader_kind(self, kind).map_err(crate::Error::Local) + } + + #[cfg(feature = "testing")] + fn fail_one_syscall_with(&self, errno: c_int) { + Backend::fail_one_syscall_with(self, errno) + } +} + #[derive(Debug)] pub struct FileReader(OwnedFd); impl FileReader { - pub fn read(&mut self, buf: &mut [u8]) -> Result { + pub fn read(&mut self, buf: &mut [u8]) -> Result { let rv = unsafe { libc::read(self.0.as_raw_fd(), buf.as_mut_ptr().cast(), buf.len()) }; if rv == -1 { return Err(Error::ReadFileFailed(errno())); } Ok(rv.try_into().unwrap()) } - pub fn read_at(&self, buf: &mut [u8], offset: u64) -> Result { + pub fn read_at(&self, buf: &mut [u8], offset: u64) -> Result { let rv = unsafe { libc::pread( self.0.as_raw_fd(), @@ -342,6 +412,12 @@ impl FileReader { } } +impl crate::FileReader for FileReader { + fn read(&mut self, buf: &mut [u8]) -> crate::Result { + FileReader::read(self, buf).map_err(crate::Error::Local) + } +} + #[derive(Debug)] pub struct DirReader { dirp: *mut libc::DIR, @@ -349,7 +425,7 @@ pub struct DirReader { } impl DirReader { - pub fn read_name(&mut self) -> Result, Error> { + pub fn read_next_name(&mut self) -> Result> { if self.eof { return Ok(None); } @@ -386,39 +462,36 @@ impl Drop for DirReader { fn drop(&mut self) { let rv = unsafe { libc::closedir(self.dirp) }; if rv == -1 { - log::debug!("failed to close directory: {}", errno()); + report_drop_failed!("failed to close directory: {}", errno()); } } } -#[derive(Debug)] -pub struct ProcessReader(process_reader::ProcessReader); +impl crate::DirReader for DirReader { + fn read_next_name(&mut self, buf: &mut [u8]) -> crate::Result { + let Some(name) = DirReader::read_next_name(self).map_err(crate::Error::Local)? else { + return Ok(0); + }; + let buf = buf + .get_mut(0..name.len()) + .ok_or(crate::Error::BufferTooSmall)?; + buf.copy_from_slice(name); + Ok(name.len()) + } +} -impl ProcessReader { - pub fn read_at(&self, address: usize, buf: &mut [u8]) -> Result { +#[derive(Debug)] +pub struct ProcessReader<'a>(&'a process_reader::ProcessReader); + +impl<'a> ProcessReader<'a> { + pub fn read_at(&self, address: usize, buf: &mut [u8]) -> Result { self.0.read_at(address, buf).map_err(Error::ProcessReader) } } -#[derive(Debug)] -struct OwnedFd(c_int); - -impl OwnedFd { - // SAFETY: Must be a valid fd - pub unsafe fn new(fd: c_int) -> Self { - Self(fd) - } - pub fn as_raw_fd(&self) -> c_int { - self.0 - } -} - -impl Drop for OwnedFd { - fn drop(&mut self) { - let rv = unsafe { libc::close(self.0) }; - if rv == -1 { - log::error!("failed to close file: {}", errno()); - } +impl<'a> crate::ProcessReader for ProcessReader<'a> { + fn read_at(&self, address: usize, buf: &mut [u8]) -> crate::Result { + ProcessReader::read_at(self, address, buf).map_err(crate::Error::Local) } } @@ -433,22 +506,18 @@ unsafe fn ptrace( unsafe { libc::ptrace(request, pid, addr, data) } } -fn errno() -> c_int { - unsafe { *errno_location() } +#[derive(Debug, thiserror::Error, serde::Deserialize, serde::Serialize)] +pub enum PtraceGetRegSetError { + #[error("ptrace returned error code: {0}")] + PtraceFailed(c_int), + #[error("unexpected size for register set. Expected: {0}, actual: {0}")] + UnexpectedRegisterSetSize(usize, usize), } -fn set_errno(value: c_int) { - unsafe { - *errno_location() = value; - } -} - -#[cfg(target_os = "android")] -fn errno_location() -> *mut c_int { - unsafe { libc::__errno() } -} - -#[cfg(not(target_os = "android"))] -fn errno_location() -> *mut c_int { - unsafe { libc::__errno_location() } +#[derive(Debug, thiserror::Error, serde::Deserialize, serde::Serialize)] +pub enum PtraceGetRegsLegacyError { + #[error("ptrace returned error code: {0}")] + PtraceFailed(c_int), + #[error("legacy API not supported on this architecture")] + NotSupported, } diff --git a/third_party/rust/process-backend/src/local/module_reader.rs b/third_party/rust/process-backend/src/local/module_reader.rs index 7871a567d1d6..f7ea40ff9790 100644 --- a/third_party/rust/process-backend/src/local/module_reader.rs +++ b/third_party/rust/process-backend/src/local/module_reader.rs @@ -1,10 +1,10 @@ -use { - super::{Error, OwnedFd, SyscallInvoker, errno}, - core::{ - ffi::{CStr, c_void}, - mem, ptr, - }, +use super::super::local; +use crate::wrapper::{OwnedFd, errno}; +use core::{ + ffi::{CStr, c_void}, + mem, ptr, }; +use local::{Error, Result, SyscallInvoker}; #[derive(Debug)] pub struct MappedModuleMemoryReader { @@ -14,11 +14,24 @@ pub struct MappedModuleMemoryReader { } impl MappedModuleMemoryReader { - pub fn new( + pub fn read_at(&self, offset: usize, length: usize) -> Result<&[u8]> { + let s = self.as_slice(); + let requested_end = offset.checked_add(length).ok_or(Error::IndexOutOfBounds)?; + let maximum_end = s.len(); + let end = usize::min(requested_end, maximum_end); + s.get(offset..end).ok_or(Error::IndexOutOfBounds) + } + pub fn len(&self) -> usize { + self.as_slice().len() + } + pub fn is_empty(&self) -> bool { + self.as_slice().is_empty() + } + pub(crate) fn new( syscall_invoker: &mut SyscallInvoker, path: &CStr, start_position: u64, - ) -> Result { + ) -> Result { let fd = Self::open_file(syscall_invoker, path)?; // So far, we only ever map files from the start position to EOF - We never specify a @@ -51,22 +64,7 @@ impl MappedModuleMemoryReader { Ok(MappedModuleMemoryReader { mapped, ptr, len }) } - pub fn read(&self, offset: u64, length: u64) -> Result<&[u8], Error> { - (|| { - let offset = usize::try_from(offset).ok()?; - let length = usize::try_from(length).ok()?; - let end = offset.checked_add(length)?; - self.as_slice().get(offset..end) - })() - .ok_or(Error::IndexOutOfBounds) - } - pub fn len(&self) -> Result { - Ok(self.as_slice().len()) - } - pub fn is_empty(&self) -> Result { - self.len().map(|l| l == 0) - } - fn open_file(syscall_invoker: &mut SyscallInvoker, path: &CStr) -> Result { + fn open_file(syscall_invoker: &mut SyscallInvoker, path: &CStr) -> Result { syscall_invoker .invoke_standard(|| unsafe { libc::open(path.as_ptr(), libc::O_RDONLY | libc::O_CLOEXEC, 0) @@ -74,7 +72,7 @@ impl MappedModuleMemoryReader { .map(|fd| unsafe { OwnedFd::new(fd) }) .map_err(Error::OpenFileFailed) } - fn get_file_size(syscall_invoker: &mut SyscallInvoker, fd: &OwnedFd) -> Result { + fn get_file_size(syscall_invoker: &mut SyscallInvoker, fd: &OwnedFd) -> Result { let mut stat: libc::stat = unsafe { mem::zeroed() }; syscall_invoker @@ -93,7 +91,7 @@ impl MappedModuleMemoryReader { fd: &OwnedFd, page_aligned_start_position: u64, len: usize, - ) -> Result { + ) -> Result { // Linux requires the mapping length to be non-zero, even though we want to support // zero-length mappings -- So we just make it a one-byte mapping (and ignore the byte). let len = usize::max(len, 1); @@ -139,6 +137,23 @@ impl MappedModuleMemoryReader { } } +impl crate::MappedModuleMemoryReader for MappedModuleMemoryReader { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> core::result::Result { + let bytes = MappedModuleMemoryReader::read_at(self, offset, buf.len()) + .map_err(crate::Error::Local)?; + buf[0..bytes.len()].copy_from_slice(bytes); + Ok(bytes.len()) + } + + fn len(&self) -> core::result::Result { + Ok(MappedModuleMemoryReader::len(self)) + } + + fn is_empty(&self) -> core::result::Result { + Ok(MappedModuleMemoryReader::is_empty(self)) + } +} + #[derive(Debug)] struct Mapped { ptr: *mut c_void, @@ -149,7 +164,7 @@ impl Drop for Mapped { fn drop(&mut self) { let rv = unsafe { libc::munmap(self.ptr, self.len) }; if rv == -1 { - log::error!("failed to unmap memory: {}", errno()); + report_drop_failed!("failed to unmap memory: {}", errno()); } } } diff --git a/third_party/rust/process-backend/src/local/syscall_invoker.rs b/third_party/rust/process-backend/src/local/syscall_invoker.rs index f0e7596f77a5..15a013f34c45 100644 --- a/third_party/rust/process-backend/src/local/syscall_invoker.rs +++ b/third_party/rust/process-backend/src/local/syscall_invoker.rs @@ -1,7 +1,8 @@ -use {super::errno, core::ffi::c_int}; +use crate::wrapper::errno; +use core::ffi::c_int; #[derive(Debug, Default)] -pub struct SyscallInvoker(Option); +pub(crate) struct SyscallInvoker(Option); impl SyscallInvoker { /// Helper function to invoke a syscall and capture errno if it fails @@ -12,7 +13,7 @@ impl SyscallInvoker { /// /// If testing requests a failure, will never actually make the syscall and just returns /// the errno requested by testing - pub fn invoke(&mut self, f: F) -> Result + pub(crate) fn invoke(&mut self, f: F) -> Result where F: FnOnce() -> Result, { @@ -24,7 +25,7 @@ impl SyscallInvoker { } /// Ergonomics for `invoke` for the standard case where `-1` indicates the syscall failed - pub fn invoke_standard(&mut self, f: F) -> Result + pub(crate) fn invoke_standard(&mut self, f: F) -> Result where F: FnOnce() -> T, T: From + core::cmp::PartialEq, @@ -40,7 +41,7 @@ impl SyscallInvoker { /// Force the next syscall to fail with the given errno #[cfg(feature = "testing")] - pub fn fail_one_syscall_with(&mut self, errno: c_int) { + pub(crate) fn fail_one_syscall_with(&mut self, errno: c_int) { self.0 = Some(errno); } } diff --git a/third_party/rust/process-backend/src/regs.rs b/third_party/rust/process-backend/src/regs.rs index b98c8f061482..d5c52fa5670b 100644 --- a/third_party/rust/process-backend/src/regs.rs +++ b/third_party/rust/process-backend/src/regs.rs @@ -1,138 +1,451 @@ +// We define our own versions of the various constants/register-holding structures from the ptrace +// API of Linux for a few reasons: +// +// 1. The versions of them defined in the `libc` crate don't provide `Deserialize` or `Serialize` +// implementations, and we need that - So we'd have to maintain parallel versions of these +// structs anyway. +// +// 2. A lot of these structures/constants vary slightly by name and availability between glibc, +// bionic and musl, even though the kernel itself supports them. Doing it ourselves helps us +// maintain more consistency. +// +// 3. All of these structures are basically plain-old-data types under the hood, so we can avoid +// using MaybeUninit by deriving a `Default` implementation for them - something the `libc` +// crate doesn't do because it doesn't generalize to all types in libc. +// +// All information was obtained directly from the Linux Kernel source code, with a few +// modifications like explicitly-declared padding, and consistent use of fixed-width unsigned +// integer types. +// +// Kernel names will be used for these structs, and links to the relevant code in the kernel are +// included. +#![allow(unused)] + +#[cfg(target_env = "gnu")] +pub(crate) type PtraceRequestType = core::ffi::c_uint; + +#[cfg(not(target_env = "gnu"))] +pub(crate) type PtraceRequestType = core::ffi::c_int; + +/// A kernel-defined constant that names a register set as part of a call to +/// ptrace(PTRACE_GETREGSET) +pub(crate) struct RegSetNote(pub(crate) usize); + +/// Describes a register-set buffer that may be populated by `ptrace`. +/// +/// # Safety +/// +/// Implementors must guarantee all of the following: +/// +/// 1. `NOTE` identifies a `PTRACE_GETREGSET` register set whose first +/// `KERNEL_SIZE` bytes have the layout of the corresponding prefix +/// of `Output`. +/// +/// 2. If `LEGACY_REQUEST` is `Some`, that request writes the same register +/// representation, writes no more than `KERNEL_SIZE` bytes, and uses the +/// fourth `ptrace` argument as the output buffer. +/// +/// 3. `KERNEL_SIZE <= size_of::()`. +/// +/// 4. Every byte pattern the kernel may leave in the first `KERNEL_SIZE` +/// bytes, combined with the untouched bytes of `Output::default()`, +/// must constitute a valid `Output`, including when the syscall fails +/// after a partial write. +/// +/// 5. `Output` must not require drop glue. +pub(crate) unsafe trait PtraceRegisterSet { + const NOTE: RegSetNote; + /// Legacy ptrace request to fall back on if PTRACE_GETREGSET fails + const LEGACY_REQUEST: Option; + const KERNEL_SIZE: usize; + type Output: Copy + Default; +} + +pub(crate) enum GenRegsTag {} +pub(crate) enum FpRegsTag {} + +// https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/uapi/linux/elf.h?h=v7.1.8 +const NT_PRSTATUS: RegSetNote = RegSetNote(1); +const NT_PRFPREG: RegSetNote = RegSetNote(2); +const NT_ARM_VFP: RegSetNote = RegSetNote(0x400); +const NT_PRXFPREG: RegSetNote = RegSetNote(0x46e62b7f); + pub use imp::*; +// https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm64/kernel/ptrace.c?h=v7.1.8#n1614 #[cfg(target_arch = "aarch64")] mod imp { - pub type GenRegs = libc::user_regs_struct; - pub type FpRegs = user_fpsimd_struct; + use super::*; - /// https://github.com/rust-lang/libc/pull/2719 + pub type GenRegs = user_pt_regs; + pub type FpRegs = user_fpsimd_state; + + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm64/include/uapi/asm/ptrace.h?h=v7.1.8#n88 #[repr(C)] - #[derive(Debug)] - pub struct user_fpsimd_struct { + #[derive(Clone, Copy, Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct user_pt_regs { + pub regs: [u64; 31], + pub sp: u64, + pub pc: u64, + pub pstate: u64, + } + + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm64/include/uapi/asm/ptrace.h?h=v7.1.8#n95 + #[repr(C)] + #[derive(Clone, Copy, Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct user_fpsimd_state { pub vregs: [u128; 32], pub fpsr: u32, pub fpcr: u32, + #[serde(skip)] + pub __reserved: [u32; 2], } + + unsafe impl PtraceRegisterSet for GenRegsTag { + const NOTE: RegSetNote = NT_PRSTATUS; + const LEGACY_REQUEST: Option = None; + const KERNEL_SIZE: usize = size_of::(); + type Output = user_pt_regs; + } + + unsafe impl PtraceRegisterSet for FpRegsTag { + const NOTE: RegSetNote = NT_PRFPREG; + const LEGACY_REQUEST: Option = None; + const KERNEL_SIZE: usize = size_of::(); + type Output = user_fpsimd_state; + } + + const _: () = { + assert!(size_of::() == 272); + assert!(align_of::() == 8); + assert!(size_of::() == 528); + assert!(align_of::() == 16); + }; } +// https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm/kernel/ptrace.c?h=v7.1.8#n678 #[cfg(target_arch = "arm")] mod imp { - pub type GenRegs = user_regs_struct; - pub type FpRegs = user_fpregs_struct; + use super::*; - // Not defined by libc because this works only for cores support VFP + pub type GenRegs = pt_regs; + pub type FpRegs = user_vfp; + + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm/include/uapi/asm/ptrace.h?h=v7.1.8 + const PTRACE_GETREGS: PtraceRequestType = 12; + const PTRACE_GETVFPREGS: PtraceRequestType = 27; + + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm/include/uapi/asm/ptrace.h?h=v7.1.8#n149 + const ARM_VFPREGS_SIZE: usize = 32 * 8 /*fpregs*/ + 4 /*fpscr*/; + + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm/include/asm/user.h?h=v7.1.8#n85 + // + // Note: This struct has 4 bytes of padding at the end due to its alignment requirements, but + // the kernel does not write those 4 bytes as part of a ptrace call - it will only write 260 + // bytes and not 264 (the size of this struct with trailing padding). + // + // We capture that by setting the `KERNEL_SIZE` to `ARM_VFPREGS_SIZE` instead of + // `size_of::()`. #[repr(C)] - #[derive(Debug, Eq, Hash, PartialEq, Copy, Clone, Default)] - pub struct user_fpregs_struct { + #[derive(Clone, Copy, Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct user_vfp { pub fpregs: [u64; 32], pub fpscr: u32, } + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm/include/asm/ptrace.h?h=v7.1.8#n16 #[repr(C)] - #[derive(Debug, Eq, Hash, PartialEq, Copy, Clone, Default)] - pub struct user_regs_struct { + #[derive(Clone, Copy, Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct pt_regs { pub uregs: [u32; 18], } + + unsafe impl PtraceRegisterSet for GenRegsTag { + const NOTE: RegSetNote = NT_PRSTATUS; + const LEGACY_REQUEST: Option = Some(PTRACE_GETREGS); + const KERNEL_SIZE: usize = size_of::(); + type Output = pt_regs; + } + + unsafe impl PtraceRegisterSet for FpRegsTag { + const NOTE: RegSetNote = NT_ARM_VFP; + const LEGACY_REQUEST: Option = Some(PTRACE_GETVFPREGS); + const KERNEL_SIZE: usize = ARM_VFPREGS_SIZE; + type Output = user_vfp; + } + + const _: () = { + assert!(size_of::() == 72); + assert!(align_of::() == 4); + assert!(size_of::() == 264); + assert!(align_of::() == 8); + }; } +// https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/kernel/ptrace.c?h=v7.1.8#n1298 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] mod imp { - pub type GenRegs = user_regs_struct; - pub type FpRegs = user_fpregs_struct; + use super::*; - #[cfg(target_arch = "x86")] - pub type FpxRegs = user_fpxregs_struct; + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/include/uapi/asm/ptrace-abi.h?h=v7.1.8 + const PTRACE_GETREGS: PtraceRequestType = 12; + const PTRACE_GETFPREGS: PtraceRequestType = 14; pub const NUM_DEBUG_REGISTERS: usize = 8; + pub use subarch::*; + #[cfg(target_arch = "x86")] - pub type RegType = u32; + mod subarch { + use super::*; + + pub type GenRegs = user_regs_struct; + pub type FpRegs = user_i387_ia32_struct; + pub type FpxRegs = fxregs_state; + pub type RegType = u32; + + pub(crate) enum FpxRegsTag {} + + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/include/uapi/asm/ptrace-abi.h?h=v7.1.8 + const PTRACE_GETFPXREGS: PtraceRequestType = 18; + + // Obtained by running: + // println!("{}", std::mem::offset_of!(libc::user, u_debugreg)); + pub const USER_STRUCT_DEBUGREG_OFFSET: usize = 252; + + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/include/asm/user_32.h?h=v7.1.8#n78 + #[repr(C)] + #[derive(Clone, Copy, Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct user_regs_struct { + pub ebx: u32, + pub ecx: u32, + pub edx: u32, + pub esi: u32, + pub edi: u32, + pub ebp: u32, + pub eax: u32, + pub ds: u32, + pub es: u32, + pub fs: u32, + pub gs: u32, + pub orig_eax: u32, + pub eip: u32, + pub cs: u32, + pub eflags: u32, + pub esp: u32, + pub ss: u32, + } + + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/include/asm/user32.h?h=v7.1.8#n8 + #[repr(C)] + #[derive(Clone, Copy, Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct user_i387_ia32_struct { + pub cwd: u32, + pub swd: u32, + pub twd: u32, + pub fip: u32, + pub fcs: u32, + pub foo: u32, + pub fos: u32, + pub st_space: [u32; 20], + } + + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/include/asm/fpu/types.h?h=v7.1.8#n36 + #[repr(C, align(16))] + #[derive(Clone, Copy, Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct fxregs_state { + pub cwd: u16, + pub swd: u16, + pub twd: u16, + pub fop: u16, + pub fip: u32, + pub fcs: u32, + pub foo: u32, + pub fos: u32, + pub mxcsr: u32, + pub mxcsr_mask: u32, + pub st_space: [u32; 32], + pub xmm_space: super::XmmSpace, + #[serde(skip)] + pub __padding: [u32; 12], + #[serde(skip)] + pub __padding1: [u32; 12], + } + + unsafe impl PtraceRegisterSet for GenRegsTag { + const NOTE: RegSetNote = NT_PRSTATUS; + const LEGACY_REQUEST: Option = Some(PTRACE_GETREGS); + const KERNEL_SIZE: usize = size_of::(); + type Output = user_regs_struct; + } + + unsafe impl PtraceRegisterSet for FpRegsTag { + const NOTE: RegSetNote = NT_PRFPREG; + const LEGACY_REQUEST: Option = Some(PTRACE_GETFPREGS); + const KERNEL_SIZE: usize = size_of::(); + type Output = user_i387_ia32_struct; + } + + unsafe impl PtraceRegisterSet for FpxRegsTag { + const NOTE: RegSetNote = NT_PRXFPREG; + const LEGACY_REQUEST: Option = Some(PTRACE_GETFPXREGS); + const KERNEL_SIZE: usize = size_of::(); + type Output = fxregs_state; + } + + const _: () = { + assert!(size_of::() == 68); + assert!(align_of::() == 4); + assert!(size_of::() == 108); + assert!(align_of::() == 4); + assert!(size_of::() == 512); + assert!(align_of::() == 16); + }; + } #[cfg(target_arch = "x86_64")] - pub type RegType = u64; + mod subarch { + use super::*; - #[cfg(all(not(target_os = "android"), target_arch = "x86"))] - pub use libc::user_fpxregs_struct; - #[cfg(not(all(target_os = "android", target_arch = "x86")))] - pub use libc::{user, user_fpregs_struct, user_regs_struct}; + pub type GenRegs = user_regs_struct; + pub type FpRegs = fxregs_state; + pub type RegType = u64; - // Not defined by libc on Android - #[cfg(all(target_os = "android", target_arch = "x86"))] - #[allow(non_camel_case_types)] - #[repr(C)] - pub struct user_regs_struct { - pub ebx: libc::c_long, - pub ecx: libc::c_long, - pub edx: libc::c_long, - pub esi: libc::c_long, - pub edi: libc::c_long, - pub ebp: libc::c_long, - pub eax: libc::c_long, - pub xds: libc::c_long, - pub xes: libc::c_long, - pub xfs: libc::c_long, - pub xgs: libc::c_long, - pub orig_eax: libc::c_long, - pub eip: libc::c_long, - pub xcs: libc::c_long, - pub eflags: libc::c_long, - pub esp: libc::c_long, - pub xss: libc::c_long, + // Obtained by running: + // println!("{}", std::mem::offset_of!(libc::user, u_debugreg)); + pub const USER_STRUCT_DEBUGREG_OFFSET: usize = 848; + + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/include/asm/user_64.h?h=v7.1.8#n69 + #[repr(C)] + #[derive(Clone, Copy, Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct user_regs_struct { + pub r15: u64, + pub r14: u64, + pub r13: u64, + pub r12: u64, + pub rbp: u64, + pub rbx: u64, + pub r11: u64, + pub r10: u64, + pub r9: u64, + pub r8: u64, + pub rax: u64, + pub rcx: u64, + pub rdx: u64, + pub rsi: u64, + pub rdi: u64, + pub orig_rax: u64, + pub rip: u64, + pub cs: u64, + pub eflags: u64, + pub rsp: u64, + pub ss: u64, + pub fs_base: u64, + pub gs_base: u64, + pub ds: u64, + pub es: u64, + pub fs: u64, + pub gs: u64, + } + + // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/include/asm/fpu/types.h?h=v7.1.8#n36 + #[repr(C, align(16))] + #[derive(Clone, Copy, Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct fxregs_state { + pub cwd: u16, + pub swd: u16, + pub twd: u16, + pub fop: u16, + pub rip: u64, + pub rdp: u64, + pub mxcsr: u32, + pub mxcsr_mask: u32, + pub st_space: [u32; 32], + pub xmm_space: super::XmmSpace, + #[serde(skip)] + pub __padding: [u32; 12], + #[serde(skip)] + pub __padding1: [u32; 12], + } + + unsafe impl PtraceRegisterSet for GenRegsTag { + const NOTE: RegSetNote = NT_PRSTATUS; + const LEGACY_REQUEST: Option = Some(PTRACE_GETREGS); + const KERNEL_SIZE: usize = size_of::(); + type Output = user_regs_struct; + } + + unsafe impl PtraceRegisterSet for FpRegsTag { + const NOTE: RegSetNote = NT_PRFPREG; + const LEGACY_REQUEST: Option = Some(PTRACE_GETFPREGS); + const KERNEL_SIZE: usize = size_of::(); + type Output = fxregs_state; + } + + const _: () = { + assert!(size_of::() == 216); + assert!(align_of::() == 8); + assert!(size_of::() == 512); + assert!(align_of::() == 16); + }; } - // Not defined by libc on Android - #[cfg(all(target_os = "android", target_arch = "x86"))] - #[allow(non_camel_case_types)] - #[repr(C)] - pub struct user_fpxregs_struct { - pub cwd: libc::c_ushort, - pub swd: libc::c_ushort, - pub twd: libc::c_ushort, - pub fop: libc::c_ushort, - pub fip: libc::c_long, - pub fcs: libc::c_long, - pub foo: libc::c_long, - pub fos: libc::c_long, - pub mxcsr: libc::c_long, - __reserved: libc::c_long, - pub st_space: [libc::c_long; 32], - pub xmm_space: [libc::c_long; 32], - padding: [libc::c_long; 56], + // std and serde don't implement Default, Deserialize, and Serialize traits for arrays longer + // than 32 elements, so we have to hand-code them for the XMM array + + #[derive(Clone, Copy, Debug)] + #[repr(transparent)] + pub struct XmmSpace(pub [u32; 64]); + + impl Default for XmmSpace { + fn default() -> XmmSpace { + XmmSpace([0; 64]) + } } - // Not defined by libc on Android - #[cfg(all(target_os = "android", target_arch = "x86"))] - #[allow(non_camel_case_types)] - #[repr(C)] - pub struct user_fpregs_struct { - pub cwd: libc::c_long, - pub swd: libc::c_long, - pub twd: libc::c_long, - pub fip: libc::c_long, - pub fcs: libc::c_long, - pub foo: libc::c_long, - pub fos: libc::c_long, - pub st_space: [libc::c_long; 20], + impl serde::Serialize for XmmSpace { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + use serde::ser::SerializeTuple; + let mut tup = serializer.serialize_tuple(64)?; + for element in self.0.iter() { + tup.serialize_element::(element)?; + } + tup.end() + } } - #[cfg(all(target_os = "android", target_arch = "x86"))] - #[allow(non_camel_case_types)] - #[repr(C)] - pub struct user { - pub regs: user_regs_struct, - pub u_fpvalid: libc::c_long, - pub i387: user_fpregs_struct, - pub u_tsize: libc::c_ulong, - pub u_dsize: libc::c_ulong, - pub u_ssize: libc::c_ulong, - pub start_code: libc::c_ulong, - pub start_stack: libc::c_ulong, - pub signal: libc::c_long, - __reserved: libc::c_int, - pub u_ar0: *mut user_regs_struct, - pub u_fpstate: *mut user_fpregs_struct, - pub magic: libc::c_ulong, - pub u_comm: [libc::c_char; 32], - pub u_debugreg: [libc::c_int; 8], + impl<'de> serde::Deserialize<'de> for XmmSpace { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = XmmSpace; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(formatter, "a u32 array of length 64") + } + + fn visit_seq>( + self, + mut seq: A, + ) -> Result { + let mut arr = [0u32; 64]; + for (idx, element) in arr.iter_mut().enumerate() { + *element = seq + .next_element::()? + .ok_or(::invalid_length(idx, &self))?; + } + Ok(XmmSpace(arr)) + } + } + + deserializer.deserialize_tuple(64, Visitor) + } } } diff --git a/third_party/rust/process-backend/src/wrapper.rs b/third_party/rust/process-backend/src/wrapper.rs new file mode 100644 index 000000000000..fef8c44ef9fc --- /dev/null +++ b/third_party/rust/process-backend/src/wrapper.rs @@ -0,0 +1,49 @@ +use core::ffi::c_int; +use serde::{Deserialize, Serialize}; + +#[derive(Debug)] +pub(crate) struct OwnedFd(c_int); + +impl OwnedFd { + // SAFETY: Must be a valid fd + pub(crate) unsafe fn new(fd: c_int) -> Self { + Self(fd) + } + pub(crate) fn as_raw_fd(&self) -> c_int { + self.0 + } +} + +impl Drop for OwnedFd { + fn drop(&mut self) { + let rv = unsafe { libc::close(self.0) }; + if rv == -1 { + report_drop_failed!("failed to close file: {}", errno()); + } + } +} + +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +pub struct Stat { + pub st_mode: u32, +} + +pub(crate) fn errno() -> c_int { + unsafe { *errno_location() } +} + +pub(crate) fn set_errno(value: c_int) { + unsafe { + *errno_location() = value; + } +} + +#[cfg(target_os = "android")] +fn errno_location() -> *mut c_int { + unsafe { libc::__errno() } +} + +#[cfg(not(target_os = "android"))] +fn errno_location() -> *mut c_int { + unsafe { libc::__errno_location() } +} diff --git a/third_party/rust/process-reader/.cargo-checksum.json b/third_party/rust/process-reader/.cargo-checksum.json index 14c699f0975f..04e3dacb499f 100644 --- a/third_party/rust/process-reader/.cargo-checksum.json +++ b/third_party/rust/process-reader/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"6ffbfe0446feceebbf53140cdecff1b8fc92c8bc590f72654115f7aa834c74de","README.md":"0ffb552cecf854ee8b3b115d31e32dd064448044dbf06b713ef4a246fe269907","src/lib.rs":"2b2a31a23367207f046a2872115bd621414ed7bea3a99e8a52b36e10e9e6ded2","src/linux/error.rs":"45c45bd887e83acf7ec5aeff3930a2400fcd2318dc1fbf9dd727d41d04c659d1","src/linux/mod.rs":"1e2633e4ef490fcc0d8cf3f716383a0b6c88d4b2740f68bc8bb2681aee3c2365","src/linux/wrapper.rs":"d8f85881fae3c556fc804add94014517f96873044c7306501914a19555643faf"},"package":null} \ No newline at end of file +{"files":{"CHANGELOG.md":"cdc8c9eb6e8709e6c9fbf2b33bc5bb9d57a60eae314e1208320e879ced32b35c","Cargo.toml":"399b18319b4503777686e9e2aa4bf0662b4d8398a0d7584c6117b0a9acba3254","LICENSE":"1ecdd8e8977af83c07c5f97bec87b47d27059b7ea323ca3160fbfa2314f5d99c","README.md":"0ffb552cecf854ee8b3b115d31e32dd064448044dbf06b713ef4a246fe269907","release.toml":"67b8ae859100b1ec242cc1e8e9c52c4735daadfc117f2226f8733caf8ef9fc1c","src/lib.rs":"2b2a31a23367207f046a2872115bd621414ed7bea3a99e8a52b36e10e9e6ded2","src/linux/error.rs":"45c45bd887e83acf7ec5aeff3930a2400fcd2318dc1fbf9dd727d41d04c659d1","src/linux/mod.rs":"1e2633e4ef490fcc0d8cf3f716383a0b6c88d4b2740f68bc8bb2681aee3c2365","src/linux/wrapper.rs":"d8f85881fae3c556fc804add94014517f96873044c7306501914a19555643faf"},"package":null} \ No newline at end of file diff --git a/third_party/rust/process-reader/CHANGELOG.md b/third_party/rust/process-reader/CHANGELOG.md new file mode 100644 index 000000000000..543284cf5d3c --- /dev/null +++ b/third_party/rust/process-reader/CHANGELOG.md @@ -0,0 +1,18 @@ + + +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + +## [Unreleased] - ReleaseDate + +## [0.1.0] - 2026-07-20 +### Added +- Initial release. + + +[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/process-reader-0.1.0...HEAD +[0.1.0]: https://github.com/rust-minidump/minidump-writer/releases/tag/process-reader-0.1.0 diff --git a/third_party/rust/process-reader/Cargo.toml b/third_party/rust/process-reader/Cargo.toml index 7b44427c2fd2..cb94bb46af1a 100644 --- a/third_party/rust/process-reader/Cargo.toml +++ b/third_party/rust/process-reader/Cargo.toml @@ -13,15 +13,18 @@ edition = "2024" rust-version = "1.88.0" name = "process-reader" -version = "0.0.0" +version = "0.1.0" build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false +description = "Utilities for reading process memory on Linux" +homepage = "https://github.com/rust-minidump/minidump-writer" readme = "README.md" license = "MIT" +repository = "https://github.com/rust-minidump/minidump-writer" [features] serde = ["dep:serde"] @@ -31,7 +34,7 @@ name = "process_reader" path = "src/lib.rs" [target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies.libc] -version = "0.2.186" +version = "0.2" default-features = false [target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies.serde] diff --git a/third_party/rust/process-reader/LICENSE b/third_party/rust/process-reader/LICENSE new file mode 100644 index 000000000000..6f9ec1352ea4 --- /dev/null +++ b/third_party/rust/process-reader/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 + +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 included in all +copies or 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. diff --git a/third_party/rust/process-reader/release.toml b/third_party/rust/process-reader/release.toml new file mode 100644 index 000000000000..7d25cc6321af --- /dev/null +++ b/third_party/rust/process-reader/release.toml @@ -0,0 +1,10 @@ +pre-release-commit-message = "Release process-reader-{{version}}" +tag-message = "Release process-reader-{{version}}" +tag-name = "process-reader-{{version}}" +pre-release-replacements = [ + { file = "CHANGELOG.md", search = "Unreleased", replace = "{{version}}" }, + { file = "CHANGELOG.md", search = "\\.\\.\\.HEAD", replace = "...{{tag_name}}" }, + { file = "CHANGELOG.md", search = "ReleaseDate", replace = "{{date}}" }, + { file = "CHANGELOG.md", search = "", replace = "\n## [Unreleased] - ReleaseDate" }, + { file = "CHANGELOG.md", search = "", replace = "\n[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/{{tag_name}}...HEAD" }, +] diff --git a/toolkit/crashreporter/crash_helper_client/Cargo.toml b/toolkit/crashreporter/crash_helper_client/Cargo.toml index 8ecf5a5de77b..e03e835afbac 100644 --- a/toolkit/crashreporter/crash_helper_client/Cargo.toml +++ b/toolkit/crashreporter/crash_helper_client/Cargo.toml @@ -15,10 +15,10 @@ num-traits = "0.2" nix = { version = "0.30", features = ["process"] } [target."cfg(target_os = \"macos\")".dependencies] -mach2 = { version = "0.4" } +mach2 = { version = "0.6" } [target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dependencies] -minidump-writer = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "ee5b9d59d85bea1d4c6845f6b854e04fe204adf2" } +minidump-writer = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "6744feee58804a78730d176cdcc31bb4f3021107" } rust_minidump_writer_linux = { path = "../rust_minidump_writer_linux" } [target."cfg(target_os = \"windows\")".dependencies] diff --git a/toolkit/crashreporter/crash_helper_common/Cargo.toml b/toolkit/crashreporter/crash_helper_common/Cargo.toml index 7d31538ac274..fac2c6990054 100644 --- a/toolkit/crashreporter/crash_helper_common/Cargo.toml +++ b/toolkit/crashreporter/crash_helper_common/Cargo.toml @@ -19,11 +19,11 @@ nix = { version = "0.30", features = ["fs", "poll", "socket", "uio", "user"] } [target."cfg(any(target_os = \"ios\", target_os = \"macos\"))".dependencies] getrandom = { version = "0.3" } -mach2 = "0.4" +mach2 = "0.6" log = "0.4" [target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dependencies] -minidump-writer = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "ee5b9d59d85bea1d4c6845f6b854e04fe204adf2" } +minidump-writer = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "6744feee58804a78730d176cdcc31bb4f3021107" } [target."cfg(target_os = \"windows\")".dependencies] getrandom = { version = "0.3" } diff --git a/toolkit/crashreporter/crash_helper_server/Cargo.toml b/toolkit/crashreporter/crash_helper_server/Cargo.toml index 13a69514efba..22e67ee0ee30 100644 --- a/toolkit/crashreporter/crash_helper_server/Cargo.toml +++ b/toolkit/crashreporter/crash_helper_server/Cargo.toml @@ -28,7 +28,7 @@ android_logger = "0.12" [target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dependencies] nix = { version = "0.30", features = ["process", "poll", "socket", "uio"] } -minidump-writer = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "ee5b9d59d85bea1d4c6845f6b854e04fe204adf2" } +minidump-writer = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "6744feee58804a78730d176cdcc31bb4f3021107" } rust_minidump_writer_linux = { path = "../rust_minidump_writer_linux" } [target."cfg(target_os = \"windows\")".dependencies] diff --git a/toolkit/crashreporter/process_reader/Cargo.toml b/toolkit/crashreporter/process_reader/Cargo.toml index 2d460eb45d19..8ff0401069b7 100644 --- a/toolkit/crashreporter/process_reader/Cargo.toml +++ b/toolkit/crashreporter/process_reader/Cargo.toml @@ -26,4 +26,4 @@ windows-sys = { version = "0.61", features = [ mozilla-central-workspace-hack = { version = "0.1", optional = true } [target."cfg(target_os = \"macos\")".dependencies] -mach2 = { version = "0.4" } +mach2 = { version = "0.6" } diff --git a/toolkit/crashreporter/rust_minidump_writer_linux/Cargo.toml b/toolkit/crashreporter/rust_minidump_writer_linux/Cargo.toml index ea27cd965edd..238745c19c64 100644 --- a/toolkit/crashreporter/rust_minidump_writer_linux/Cargo.toml +++ b/toolkit/crashreporter/rust_minidump_writer_linux/Cargo.toml @@ -8,8 +8,8 @@ license = "MPL-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -crash-context = "0.6.1" -minidump-writer = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "ee5b9d59d85bea1d4c6845f6b854e04fe204adf2" } +crash-context = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "6744feee58804a78730d176cdcc31bb4f3021107" } +minidump-writer = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "6744feee58804a78730d176cdcc31bb4f3021107" } crash_helper_common = { path = "../crash_helper_common/" } mozannotation_server = { path = "../mozannotation_server/" } libc = "0.2.74" diff --git a/toolkit/crashreporter/rust_minidump_writer_linux/src/lib.rs b/toolkit/crashreporter/rust_minidump_writer_linux/src/lib.rs index 25bbef5c8534..bb819a9bf459 100644 --- a/toolkit/crashreporter/rust_minidump_writer_linux/src/lib.rs +++ b/toolkit/crashreporter/rust_minidump_writer_linux/src/lib.rs @@ -9,8 +9,8 @@ use { crash_helper_common::{crash_annotations::CrashAnnotation, ExtraCrashData}, libc::{pid_t, SI_TKILL, SI_USER}, minidump_writer::{ - crash_context::CrashContext, minidump_writer::{DirectAuxvDumpInfo as InternalDumpInfo, MinidumpWriterConfig}, + CrashContextExt, }, mozannotation_server::{AnnotationData, CAnnotation}, std::{ @@ -176,7 +176,7 @@ pub extern "C" fn minidump_writer_set_crash_context( assert!(float_state.is_none()); context.siginfo = siginfo.cloned(); - context.writer_config.set_crash_context(CrashContext { + context.writer_config.set_crash_context(CrashContextExt { inner: crash_context::CrashContext { context: ucontext.clone(), #[cfg(not(target_arch = "arm"))]