diff --git a/Cargo.lock b/Cargo.lock index 37ae7d4f683..976cdb7dc74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -19,6 +28,18 @@ dependencies = [ "version_check 0.9.4", ] +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check 0.9.4", +] + [[package]] name = "aho-corasick" version = "1.0.2" @@ -28,6 +49,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "aliasable" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -40,7 +67,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ - "libc 0.2.146", + "libc 0.2.147", ] [[package]] @@ -75,13 +102,13 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "7b2d0f03b3640e3a630367e40c468cb7f309529c708ed1d88597047b0e7c6ef7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.23", ] [[package]] @@ -91,7 +118,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi 0.1.19", - "libc 0.2.146", + "libc 0.2.147", "winapi", ] @@ -101,6 +128,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc 0.2.147", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.21.2" @@ -144,7 +186,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.18", + "syn 2.0.23", "which", ] @@ -293,7 +335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" dependencies = [ "glob", - "libc 0.2.146", + "libc 0.2.147", "libloading", ] @@ -369,7 +411,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", - "libc 0.2.146", + "libc 0.2.147", ] [[package]] @@ -384,7 +426,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9e393a7668fe1fad3075085b86c781883000b4ede868f43627b34a87c8b7ded" dependencies = [ - "libc 0.2.146", + "libc 0.2.147", "winapi", ] @@ -551,7 +593,7 @@ dependencies = [ "criterion 0.5.1", "futures", "io-lifetimes", - "libc 0.2.146", + "libc 0.2.147", "nix", "pin-project", "pretty_assertions", @@ -571,8 +613,10 @@ dependencies = [ name = "datadog-php-profiling" version = "0.90.0" dependencies = [ + "ahash 0.8.3", "anyhow", "bindgen", + "bumpalo", "cc", "cfg-if", "cpu-time", @@ -584,9 +628,10 @@ dependencies = [ "env_logger", "indexmap 2.0.0", "lazy_static", - "libc 0.2.146", + "libc 0.2.147", "log", "once_cell", + "ouroboros", "perfcnt", "rand 0.8.5", "rand_distr", @@ -612,7 +657,7 @@ dependencies = [ "hyper", "hyper-multipart-rfc7578", "indexmap 1.9.3", - "libc 0.2.146", + "libc 0.2.147", "lz4_flex", "mime", "mime_guess", @@ -640,7 +685,7 @@ dependencies = [ "hyper", "io-lifetimes", "lazy_static", - "libc 0.2.146", + "libc 0.2.147", "manual_future", "nix", "pin-project", @@ -669,7 +714,7 @@ dependencies = [ "ddcommon-ffi", "ddtelemetry", "ddtelemetry-ffi", - "libc 0.2.146", + "libc 0.2.147", "paste", "tempfile", ] @@ -679,7 +724,7 @@ name = "datadog-sidecar-macros" version = "0.0.1" dependencies = [ "quote", - "syn 2.0.18", + "syn 2.0.23", ] [[package]] @@ -767,7 +812,7 @@ version = "3.0.0" dependencies = [ "ddcommon-ffi", "ddtelemetry", - "libc 0.2.146", + "libc 0.2.147", "paste", "tempfile", ] @@ -838,7 +883,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.23", ] [[package]] @@ -867,8 +912,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", - "libc 0.2.146", - "windows-sys 0.48.0", + "libc 0.2.147", + "windows-sys", ] [[package]] @@ -878,7 +923,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" dependencies = [ "cc", - "libc 0.2.146", + "libc 0.2.147", ] [[package]] @@ -968,7 +1013,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.23", ] [[package]] @@ -1025,10 +1070,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", - "libc 0.2.146", + "libc 0.2.147", "wasi", ] +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + [[package]] name = "glob" version = "0.3.1" @@ -1047,7 +1098,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.6", ] [[package]] @@ -1068,16 +1119,7 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ - "libc 0.2.146", -] - -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc 0.2.146", + "libc 0.2.147", ] [[package]] @@ -1134,9 +1176,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -1247,20 +1289,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.1", - "libc 0.2.146", - "windows-sys 0.48.0", + "libc 0.2.147", + "windows-sys", ] [[package]] name = "is-terminal" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" dependencies = [ "hermit-abi 0.3.1", - "io-lifetimes", - "rustix", - "windows-sys 0.48.0", + "rustix 0.38.2", + "windows-sys", ] [[package]] @@ -1274,9 +1315,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" [[package]] name = "js-sys" @@ -1313,9 +1354,9 @@ checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libloading" @@ -1339,6 +1380,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +[[package]] +name = "linux-raw-sys" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" + [[package]] name = "lock_api" version = "0.4.10" @@ -1400,7 +1447,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffc89ccdc6e10d6907450f753537ebc5c5d3460d2e4e62ea74bd571db62c0f9e" dependencies = [ - "rustix", + "rustix 0.37.22", ] [[package]] @@ -1458,9 +1505,9 @@ version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ - "libc 0.2.146", + "libc 0.2.147", "wasi", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1481,7 +1528,7 @@ checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ "bitflags 1.3.2", "cfg-if", - "libc 0.2.146", + "libc 0.2.147", "memoffset 0.6.5", ] @@ -1548,12 +1595,12 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", - "libc 0.2.146", + "hermit-abi 0.3.1", + "libc 0.2.147", ] [[package]] @@ -1645,6 +1692,30 @@ version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +[[package]] +name = "ouroboros" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d813b7b31a82efae94bd30ffaac09aec85efc18db2d5ec3aead1a220ee954351" +dependencies = [ + "aliasable", + "ouroboros_macro", + "static_assertions", +] + +[[package]] +name = "ouroboros_macro" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a56f651b4dd45ae3ac3d260ced32eaf0620cddaae5f26c69b554a9016594726" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.23", +] + [[package]] name = "output_vt100" version = "0.1.3" @@ -1677,7 +1748,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", - "libc 0.2.146", + "libc 0.2.147", "redox_syscall", "smallvec", "windows-targets", @@ -1685,9 +1756,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35" [[package]] name = "peeking_take_while" @@ -1708,7 +1779,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ba1fd955270ca6f8bd8624ec0c4ee1a251dd3cc0cc18e1e2665ca8f5acb1501" dependencies = [ "bitflags 1.3.2", - "libc 0.2.146", + "libc 0.2.147", "mmap", "nom 4.2.3", "x86", @@ -1754,29 +1825,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.23", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" @@ -1824,7 +1895,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "059a34f111a9dee2ce1ac2826a68b24601c4298cfeb1a587c3cb493d5ab46f52" dependencies = [ - "libc 0.2.146", + "libc 0.1.12", "nix", ] @@ -1847,14 +1918,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282" dependencies = [ "proc-macro2", - "syn 2.0.18", + "syn 2.0.23", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check 0.9.4", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check 0.9.4", ] [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" dependencies = [ "unicode-ident", ] @@ -1884,9 +1979,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] @@ -1898,7 +1993,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" dependencies = [ "fuchsia-cprng", - "libc 0.2.146", + "libc 0.2.147", "rand_core 0.3.1", "rdrand", "winapi", @@ -1910,7 +2005,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc 0.2.146", + "libc 0.2.147", "rand_chacha", "rand_core 0.6.4", ] @@ -2056,7 +2151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" dependencies = [ "cc", - "libc 0.2.146", + "libc 0.2.147", "once_cell", "spin", "untrusted", @@ -2070,9 +2165,15 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7278a1ec8bfd4a4e07515c589f5ff7b309a373f987393aef44813d9dcf87aa3" dependencies = [ - "libc 0.2.146", + "libc 0.2.147", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -2081,16 +2182,29 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.37.20" +version = "0.37.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" +checksum = "8818fa822adcc98b18fedbb3632a6a33213c070556b5aa7c4c8cc21cff565c4c" dependencies = [ "bitflags 1.3.2", "errno", "io-lifetimes", - "libc 0.2.146", - "linux-raw-sys", - "windows-sys 0.48.0", + "libc 0.2.147", + "linux-raw-sys 0.3.8", + "windows-sys", +] + +[[package]] +name = "rustix" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aabcb0461ebd01d6b79945797c27f8529082226cb630a9865a71870ff63532a4" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc 0.2.147", + "linux-raw-sys 0.4.3", + "windows-sys", ] [[package]] @@ -2119,9 +2233,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ "base64", ] @@ -2139,9 +2253,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" [[package]] name = "same-file" @@ -2154,11 +2268,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -2186,7 +2300,7 @@ dependencies = [ "bitflags 1.3.2", "core-foundation", "core-foundation-sys", - "libc 0.2.146", + "libc 0.2.147", "security-framework-sys", ] @@ -2197,7 +2311,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" dependencies = [ "core-foundation-sys", - "libc 0.2.146", + "libc 0.2.147", ] [[package]] @@ -2206,44 +2320,44 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "604b71b8fc267e13bb3023a2c901126c8f349393666a6d98ac1ae5729b701798" dependencies = [ - "libc 0.2.146", + "libc 0.2.147", "tokio", ] [[package]] name = "serde" -version = "1.0.164" +version = "1.0.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "d01b7404f9d441d3ad40e6a636a7782c377d2abdbe4fa2440e2edcc2f4f10db8" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.9" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +checksum = "f3c5113243e4a3a1c96587342d067f3e6b0f50790b6cf40d2868eb647a3eef0e" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.23", ] [[package]] name = "serde_json" -version = "1.0.97" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf3bf93142acad5821c99197022e170842cdbc1c30482b98750c688c640842a" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ "itoa", "ryu", @@ -2278,7 +2392,7 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ - "libc 0.2.146", + "libc 0.2.147", ] [[package]] @@ -2308,7 +2422,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ - "libc 0.2.146", + "libc 0.2.147", "winapi", ] @@ -2356,9 +2470,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.18" +version = "2.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" dependencies = [ "proc-macro2", "quote", @@ -2372,7 +2486,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c" dependencies = [ "cc", - "libc 0.2.146", + "libc 0.2.147", ] [[package]] @@ -2440,8 +2554,8 @@ dependencies = [ "cfg-if", "fastrand", "redox_syscall", - "rustix", - "windows-sys 0.48.0", + "rustix 0.37.22", + "windows-sys", ] [[package]] @@ -2476,7 +2590,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.23", ] [[package]] @@ -2523,13 +2637,14 @@ dependencies = [ [[package]] name = "tokio" -version = "1.28.2" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", - "libc 0.2.146", + "libc 0.2.147", "mio", "num_cpus", "parking_lot", @@ -2538,7 +2653,7 @@ dependencies = [ "socket2", "tokio-macros", "tracing", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -2549,7 +2664,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.23", ] [[package]] @@ -2649,13 +2764,13 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8803eee176538f94ae9a14b55b2804eb7e1441f8210b1c31290b3bccdccff73b" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.23", ] [[package]] @@ -2752,9 +2867,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" [[package]] name = "untrusted" @@ -2764,9 +2879,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "uuid" -version = "1.3.4" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81" +checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" dependencies = [ "getrandom", ] @@ -2835,7 +2950,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.23", "wasm-bindgen-shared", ] @@ -2857,7 +2972,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.23", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2895,7 +3010,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", - "libc 0.2.146", + "libc 0.2.147", "once_cell", ] @@ -2939,21 +3054,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -2965,97 +3065,55 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" diff --git a/profiling/Cargo.toml b/profiling/Cargo.toml index 926a801b1a2..a9c8047ce50 100644 --- a/profiling/Cargo.toml +++ b/profiling/Cargo.toml @@ -12,10 +12,12 @@ bench = false # disables cargo build in libtest bench # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +ahash = { version = "0.8" } anyhow = { version = "1.0" } +bumpalo = { version = "3.12", features = ["collections"] } cfg-if = { version = "1.0" } -crossbeam-channel = { version = "0.5", default-features = false, features = ["std"] } cpu-time = { version = "1.0" } +crossbeam-channel = { version = "0.5", default-features = false, features = ["std"] } datadog-profiling = { git = "https://github.com/DataDog/libdatadog", tag = "v2.2.0" } ddcommon = { git = "https://github.com/DataDog/libdatadog", tag = "v2.2.0" } env_logger = { version = "0.10" } @@ -25,9 +27,10 @@ libc = "0.2" # TRACE set to max to support runtime configuration. log = { version = "0.4", features = ["max_level_trace", "release_max_level_trace"]} once_cell = { version = "1.12" } -uuid = { version = "1.0", features = ["v4"] } +ouroboros = { version = "0.17.0" } rand = { version = "0.8.5" } rand_distr = { version = "0.4.3" } +uuid = { version = "1.0", features = ["v4"] } [dev-dependencies] criterion = { version = "0.4" } diff --git a/profiling/benches/stack_walking.rs b/profiling/benches/stack_walking.rs index 25b0393853b..75ea37a8c0f 100644 --- a/profiling/benches/stack_walking.rs +++ b/profiling/benches/stack_walking.rs @@ -16,7 +16,7 @@ fn benchmark(c: &mut Criterion) { let stack = unsafe { zend::ddog_php_test_create_fake_zend_execute_data(99) }; group.throughput(criterion::Throughput::Elements(*depth as u64)); group.bench_with_input(BenchmarkId::from_parameter(depth), depth, |b, &_depth| { - b.iter(|| unsafe { collect_stack_sample(black_box(stack)) }) + b.iter(|| collect_stack_sample(black_box(stack))) }); } group.finish(); diff --git a/profiling/build.rs b/profiling/build.rs index cc8e2de14b3..5f58e0f0a44 100644 --- a/profiling/build.rs +++ b/profiling/build.rs @@ -25,9 +25,10 @@ fn main() { let vernum = php_config_vernum(); let preload = cfg_preload(vernum); + let run_time_cache = cfg_run_time_cache(vernum); generate_bindings(php_config_includes); - build_zend_php_ffis(php_config_includes, preload); + build_zend_php_ffis(php_config_includes, preload, run_time_cache); cfg_php_major_version(vernum); cfg_php_feature_flags(vernum); @@ -68,7 +69,7 @@ const ZAI_H_FILES: &[&str] = &[ "../zend_abstract_interface/json/json.h", ]; -fn build_zend_php_ffis(php_config_includes: &str, preload: bool) { +fn build_zend_php_ffis(php_config_includes: &str, preload: bool, run_time_cache: bool) { println!("cargo:rerun-if-changed=src/php_ffi.h"); println!("cargo:rerun-if-changed=src/php_ffi.c"); println!("cargo:rerun-if-changed=../ext/handlers_api.c"); @@ -98,6 +99,7 @@ fn build_zend_php_ffis(php_config_includes: &str, preload: bool) { let files = ["src/php_ffi.c", "../ext/handlers_api.c"]; let preload = if preload { "1" } else { "0" }; + let run_time_cache = if run_time_cache { "1" } else { "0" }; #[cfg(feature = "stack_walking_tests")] let stack_walking_tests = "1"; @@ -108,6 +110,7 @@ fn build_zend_php_ffis(php_config_includes: &str, preload: bool) { cc::Build::new() .files(files.into_iter().chain(zai_c_files.into_iter())) .define("CFG_PRELOAD", preload) + .define("CFG_RUN_TIME_CACHE", run_time_cache) .define("CFG_STACK_WALKING_TESTS", stack_walking_tests) .includes([Path::new("../ext")]) .includes( @@ -212,6 +215,15 @@ fn cfg_preload(vernum: u64) -> bool { } } +fn cfg_run_time_cache(vernum: u64) -> bool { + if vernum >= 80000 { + println!("cargo:rustc-cfg=php_run_time_cache"); + true + } else { + false + } +} + fn cfg_php_major_version(vernum: u64) { let major_version = match vernum { 70000..=79999 => 7, diff --git a/profiling/src/bindings/mod.rs b/profiling/src/bindings/mod.rs index 292c521d12a..23aa6511bf6 100644 --- a/profiling/src/bindings/mod.rs +++ b/profiling/src/bindings/mod.rs @@ -286,6 +286,23 @@ extern "C" { /// strings will be converted into a string view to a static empty string /// (single byte of null, len of 0). pub fn ddog_php_prof_zend_string_view(zstr: Option<&mut zend_string>) -> zai_string_view; + + /// Registers the run_time_cache slot with the engine. Must be done in + /// module init or extension startup. + pub fn ddog_php_prof_function_run_time_cache_init(module_name: *const c_char); + + /// Gets the address of a function's run_time_cache slot. May return None + /// if it detects incomplete initialization, which is always a bug but + /// none-the-less has been seen in the wild. It may also return None if + /// the run_time_cache is not available on this function type. + #[cfg(not(feature = "stack_walking_tests"))] + pub fn ddog_php_prof_function_run_time_cache(func: &zend_function) -> Option<&mut [usize; 2]>; + + /// mock for testing + #[cfg(feature = "stack_walking_tests")] + pub fn ddog_test_php_prof_function_run_time_cache( + func: &zend_function, + ) -> Option<&mut [usize; 2]>; } #[cfg(php_preload)] @@ -525,3 +542,21 @@ pub struct ZaiConfigMemoizedEntry { ) -> c_int, >, } + +#[cfg(test)] +mod tests { + + // If this fails, then ddog_php_prof_function_run_time_cache needs to be + // adjusted accordingly. + #[test] + fn test_sizeof_fixed_size_slice_is_same_as_pointer() { + assert_eq!( + std::mem::size_of::<&[usize; 2]>(), + std::mem::size_of::<*mut usize>() + ); + assert_eq!( + std::mem::align_of::<&[usize; 2]>(), + std::mem::align_of::<*mut usize>() + ); + } +} diff --git a/profiling/src/lib.rs b/profiling/src/lib.rs index 446dde4baf7..be2b4229c3b 100644 --- a/profiling/src/lib.rs +++ b/profiling/src/lib.rs @@ -5,6 +5,7 @@ mod logging; mod pcntl; pub mod profiling; mod sapi; +mod string_table; #[cfg(feature = "allocation_profiling")] mod allocation; @@ -48,16 +49,18 @@ static PROFILER: Mutex> = Mutex::new(None); /// interior null bytes and must be null terminated. static PROFILER_NAME: &[u8] = b"datadog-profiling\0"; +/// Name of the profiling module and zend_extension, but as a &CStr. +// Safety: null terminated, contains no interior null bytes. +static PROFILER_NAME_CSTR: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(PROFILER_NAME) }; + /// Version of the profiling module and zend_extension. Must not contain any /// interior null bytes and must be null terminated. static PROFILER_VERSION: &[u8] = concat!(env!("CARGO_PKG_VERSION"), "\0").as_bytes(); lazy_static! { // Safety: PROFILER_NAME is a byte slice that satisfies the safety requirements. - static ref PROFILER_NAME_STR: &'static str = unsafe { CStr::from_ptr(PROFILER_NAME.as_ptr() as *const c_char) } - .to_str() - // Panic: we own this string and it should be UTF8 (see PROFILER_NAME above). - .unwrap(); + // Panic: we own this string and it should be UTF8 (see PROFILER_NAME above). + static ref PROFILER_NAME_STR: &'static str = PROFILER_NAME_CSTR.to_str().unwrap(); // Safety: PROFILER_VERSION is a byte slice that satisfies the safety requirements. static ref PROFILER_VERSION_STR: &'static str = unsafe { CStr::from_ptr(PROFILER_VERSION.as_ptr() as *const c_char) } @@ -110,7 +113,7 @@ pub extern "C" fn get_module() -> &'static mut zend::ModuleEntry { ]; let module = zend::ModuleEntry { - name: PROFILER_NAME.as_ptr() as *const u8, + name: PROFILER_NAME.as_ptr(), module_startup_func: Some(minit), module_shutdown_func: Some(mshutdown), request_startup_func: Some(rinit), @@ -214,7 +217,7 @@ extern "C" fn minit(r#type: c_int, module_number: c_int) -> ZendResult { * At the time of this writing, PHP 8.2 isn't out yet so it's possible * it may get reverted if issues are found. */ - let str = PROFILER_NAME.as_ptr(); + let str = PROFILER_NAME_CSTR.as_ptr(); let len = PROFILER_NAME.len() - 1; // ignore trailing null byte // Safety: str is valid for at least len values. @@ -250,6 +253,7 @@ extern "C" fn minit(r#type: c_int, module_number: c_int) -> ZendResult { copyright: b"Copyright Datadog\0".as_ptr(), startup: Some(startup), shutdown: Some(shutdown), + activate: Some(activate), ..Default::default() }; @@ -348,6 +352,11 @@ fn runtime_id() -> &'static Uuid { .get_or_init(|| unsafe { ddtrace_runtime_id.as_ref() }.map_or_else(Uuid::new_v4, |u| *u)) } +extern "C" fn activate() { + // Safety: calling in activate as required. + unsafe { profiling::activate_run_time_cache() }; +} + /* If Failure is returned the VM will do a C exit; try hard to avoid that, * using it for catastrophic errors only. */ @@ -629,6 +638,15 @@ extern "C" fn rshutdown(r#type: c_int, module_number: c_int) -> ZendResult { #[cfg(debug_assertions)] trace!("RSHUTDOWN({}, {})", r#type, module_number); + #[cfg(php_run_time_cache)] + { + profiling::FUNCTION_CACHE_STATS.with(|cell| { + let stats = cell.borrow(); + let hit_rate = stats.hit_rate(); + debug!("Process cumulative {stats:?} hit_rate: {hit_rate}"); + }); + } + REQUEST_LOCALS.with(|cell| { let mut locals = cell.borrow_mut(); @@ -810,6 +828,12 @@ extern "C" fn startup(extension: *mut ZendExtension) -> ZendResult { // Safety: called during startup hook with correct params. unsafe { zend::datadog_php_profiling_startup(extension) }; + #[cfg(php_run_time_cache)] + // Safety: calling this in startup/minit as required. + unsafe { + bindings::ddog_php_prof_function_run_time_cache_init(PROFILER_NAME_CSTR.as_ptr()) + }; + // Ignore a failure as ZEND_VERSION.get() will return an Option if it's not set. let _ = ZEND_VERSION.get_or_try_init(|| { // Safety: CStr string is null-terminated without any interior null bytes. diff --git a/profiling/src/php_ffi.c b/profiling/src/php_ffi.c index a6027a4224f..400ac5aa54d 100644 --- a/profiling/src/php_ffi.c +++ b/profiling/src/php_ffi.c @@ -65,7 +65,22 @@ static post_startup_cb_result ddog_php_prof_post_startup_cb(void) { } #endif + +#if CFG_RUN_TIME_CACHE // defined by build.rs +/** + * Currently used to ignore run_time_cache on CLI SAPI as a precaution against + * unbounded memory growth. Unbounded growth is more likely there since it's + * always one PHP request, and we only reset it on each new request. + */ +static bool _ignore_run_time_cache = false; +#endif + void datadog_php_profiling_startup(zend_extension *extension) { + +#if CFG_RUN_TIME_CACHE // defined by build.rs + _ignore_run_time_cache = strcmp(sapi_module.name, "cli") == 0; +#endif + datadog_php_profiling_get_profiling_context = noop_get_profiling_context; /* Due to the optional dependency on ddtrace, the profiling module will be @@ -91,8 +106,8 @@ void datadog_php_profiling_startup(zend_extension *extension) { void *datadog_php_profiling_vm_interrupt_addr(void) { return &EG(vm_interrupt); } -zend_module_entry *datadog_get_module_entry(const uint8_t *str, uintptr_t len) { - return zend_hash_str_find_ptr(&module_registry, (const char *)str, len); +zend_module_entry *datadog_get_module_entry(const char *str, uintptr_t len) { + return zend_hash_str_find_ptr(&module_registry, str, len); } ddtrace_profiling_context (*datadog_php_profiling_get_profiling_context)(void) = @@ -144,8 +159,7 @@ zai_string_view ddog_php_prof_zend_string_view(zend_string *zstr) { void ddog_php_prof_zend_mm_set_custom_handlers(zend_mm_heap *heap, void* (*_malloc)(size_t), void (*_free)(void*), - void* (*_realloc)(void*, size_t)) -{ + void* (*_realloc)(void*, size_t)) { zend_mm_set_custom_handlers(heap, _malloc, _free, _realloc); #if PHP_VERSION_ID < 70300 if (!_malloc && !_free && !_realloc) { @@ -154,11 +168,114 @@ void ddog_php_prof_zend_mm_set_custom_handlers(zend_mm_heap *heap, #endif } -zend_execute_data* ddog_php_prof_get_current_execute_data() -{ +zend_execute_data* ddog_php_prof_get_current_execute_data() { return EG(current_execute_data); } +#if CFG_RUN_TIME_CACHE // defined by build.rs +static int ddog_php_prof_run_time_cache_handle = -1; +#endif + +void ddog_php_prof_function_run_time_cache_init(const char *module_name) { +#if CFG_RUN_TIME_CACHE // defined by build.rs + // Grab 2, one for function name and one for filename. +#if PHP_VERSION_ID < 80200 + ddog_php_prof_run_time_cache_handle = + zend_get_op_array_extension_handle(module_name); + int second = zend_get_op_array_extension_handle(module_name); + ZEND_ASSERT(ddog_php_prof_run_time_cache_handle + 1 == second); +#else + ddog_php_prof_run_time_cache_handle = + zend_get_op_array_extension_handles(module_name, 2); +#endif +#else + (void)module_name; +#endif + + /* It's possible to work on PHP 7.4 as well, but there are opcache bugs + * that weren't truly fixed until PHP 8: + * https://github.com/php/php-src/pull/5871 + * I would rather avoid these bugs for now. + */ +} + +#if CFG_RUN_TIME_CACHE // defined by build.rs +static bool has_invalid_run_time_cache(zend_function const *func) { + if (UNEXPECTED(_ignore_run_time_cache) || UNEXPECTED(ddog_php_prof_run_time_cache_handle < 0)) + return true; + + // Trampolines use the extension slot for internal things. + bool is_trampoline = func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE; + +#if PHP_VERSION_ID < 80200 + // Internal functions don't have a runtime cache until PHP 8.2. + bool is_internal = func->type == ZEND_INTERNAL_FUNCTION; + + // The bitwise-or is intentional. Branch prediction is not going to be great + // on either of these, so reducing the number of branches is preferred. + return is_trampoline | is_internal; +#else + return is_trampoline; +#endif +} +#endif + +uintptr_t *ddog_php_prof_function_run_time_cache(zend_function const *func) { +#if CFG_STACK_WALKING_TESTS + return NULL; +#endif +#if CFG_RUN_TIME_CACHE + if (UNEXPECTED(has_invalid_run_time_cache(func))) return NULL; + +#if PHP_VERSION_ID < 80200 + // Internal functions don't have a runtime cache until PHP 8.2. + uintptr_t *cache_addr = RUN_TIME_CACHE(&func->op_array); +#else + uintptr_t *cache_addr = RUN_TIME_CACHE(&func->common); +#endif + + /* The above checks, including has_invalid_run_time_cache, protect this. + * It's better to fail now on the null, than to wait for the returned addr + * to get used, in the event future code changes screw this up. + */ + ZEND_ASSERT(cache_addr); + + return cache_addr + ddog_php_prof_run_time_cache_handle; + +#else + /* It's possible to work on PHP 7.4 as well, but there are opcache bugs + * that weren't truly fixed until PHP 8: + * https://github.com/php/php-src/pull/5871 + * I would rather avoid these bugs for now. + */ + return NULL; +#endif +} + +#if CFG_STACK_WALKING_TESTS +uintptr_t *ddog_test_php_prof_function_run_time_cache(zend_function const *func) { +#if CFG_RUN_TIME_CACHE + if (_ignore_run_time_cache) return NULL; + zend_function *non_const_func = (zend_function *)func; +#if PHP_VERSION_ID < 80200 + if (non_const_func->op_array.run_time_cache__ptr == NULL) { + non_const_func->op_array.run_time_cache__ptr = calloc(1, sizeof(uintptr_t)); + *non_const_func->op_array.run_time_cache__ptr = calloc(2, sizeof(uintptr_t)); + } + return *non_const_func->op_array.run_time_cache__ptr; +#else + if (non_const_func->common.run_time_cache__ptr == NULL) { + non_const_func->common.run_time_cache__ptr = calloc(1, sizeof(uintptr_t)); + *non_const_func->common.run_time_cache__ptr = calloc(2, sizeof(uintptr_t)); + } + return *non_const_func->common.run_time_cache__ptr; +#endif +#else + return NULL; +#endif +} +#endif + #if CFG_STACK_WALKING_TESTS static int (*og_snprintf)(char *, size_t, const char *, ...); diff --git a/profiling/src/php_ffi.h b/profiling/src/php_ffi.h index 990c66de3eb..80fe42fc941 100644 --- a/profiling/src/php_ffi.h +++ b/profiling/src/php_ffi.h @@ -35,11 +35,10 @@ const char *datadog_module_build_id(void); /** * Lookup module by name in the module registry. Returns NULL if not found. - * This is meant to be called from Rust, so it uses types that are easy to use - * in Rust. In Rust, strings are validated byte-slices instead of `char` slices - * and array lengths use uintptr_t, not size_t. + * This is meant to be called from Rust, so it uses uintptr_t, not size_t, for + * the length for convenience. */ -zend_module_entry *datadog_get_module_entry(const uint8_t *str, uintptr_t len); +zend_module_entry *datadog_get_module_entry(const char *str, uintptr_t len); /** * Fetches the VM interrupt address of the calling PHP thread. diff --git a/profiling/src/profiling/mod.rs b/profiling/src/profiling/mod.rs index 4b1a406ed54..77bbc9bbcb0 100644 --- a/profiling/src/profiling/mod.rs +++ b/profiling/src/profiling/mod.rs @@ -4,7 +4,7 @@ mod thread_utils; mod uploader; pub use interrupts::*; -use stalk_walking::*; +pub use stalk_walking::*; use uploader::*; use crate::bindings::{datadog_php_profiling_get_profiling_context, zend_execute_data}; @@ -322,7 +322,7 @@ impl TimeCollector { .expect("entry to exist; just inserted it") }; - let mut locations = vec![]; + let mut locations = Vec::with_capacity(message.value.frames.len()); let values = message.value.sample_values; let labels: Vec = message @@ -336,7 +336,7 @@ impl TimeCollector { let location = Location { lines: vec![Line { function: Function { - name: frame.function.as_str(), + name: frame.function.as_ref(), system_name: "", filename: frame.file.as_deref().unwrap_or(""), start_line: 0, @@ -760,7 +760,7 @@ impl Profiler { match self.send_sample(Profiler::prepare_sample_message( vec![ZendFrame { function: "[eval]".into(), - file: Some(filename), + file: Some(Cow::Owned(filename)), line, }], SampleValues { @@ -813,7 +813,7 @@ impl Profiler { match self.send_sample(Profiler::prepare_sample_message( vec![ZendFrame { - function: format!("[{include_type}]"), + function: format!("[{include_type}]").into(), file: None, line: 0, }], @@ -879,7 +879,7 @@ impl Profiler { match self.send_sample(Profiler::prepare_sample_message( vec![ZendFrame { - function: "[gc]".to_string(), + function: "[gc]".into(), file: None, line: 0, }], @@ -998,8 +998,8 @@ mod tests { fn get_frames() -> Vec { vec![ZendFrame { - function: "foobar()".to_string(), - file: Some("foobar.php".to_string()), + function: "foobar()".into(), + file: Some("foobar.php".into()), line: 42, }] } diff --git a/profiling/src/profiling/stalk_walking.rs b/profiling/src/profiling/stalk_walking.rs index 2a0aa19d627..04f07fd3784 100644 --- a/profiling/src/profiling/stalk_walking.rs +++ b/profiling/src/profiling/stalk_walking.rs @@ -2,14 +2,51 @@ use crate::bindings::{ ddog_php_prof_zend_string_view, zend_execute_data, zend_function, zend_string, ZEND_USER_FUNCTION, }; +use crate::string_table::{OwnedStringTable, StringTable}; +use std::borrow::Cow; +use std::cell::{RefCell, RefMut}; +use std::mem::transmute; use std::str::Utf8Error; +/// Used to help track the function run_time_cache hit rate. It glosses over +/// the fact that there are two cache slots used, and they don't have to be in +/// sync. However, they usually are, so we simplify. +#[cfg(php_run_time_cache)] +#[derive(Debug, Default)] +pub struct FunctionRunTimeCacheStats { + hit: usize, + missed: usize, + not_applicable: usize, +} + +#[cfg(php_run_time_cache)] +impl FunctionRunTimeCacheStats { + pub fn hit_rate(&self) -> f64 { + let denominator = (self.hit + self.missed + self.not_applicable) as f64; + self.hit as f64 / denominator + } +} + +#[cfg(php_run_time_cache)] +thread_local! { + static CACHED_STRINGS: RefCell = RefCell::new(OwnedStringTable::new()); + pub static FUNCTION_CACHE_STATS: RefCell = RefCell::new(Default::default()) +} + +/// # Safety +/// Must be called in Zend Extension activate. +#[inline] +pub unsafe fn activate_run_time_cache() { + #[cfg(php_run_time_cache)] + CACHED_STRINGS.with(|cell| cell.replace(OwnedStringTable::new())); +} + #[derive(Default, Debug)] pub struct ZendFrame { // Most tools don't like frames that don't have function names, so use a - // fake name if you need to like "". - pub function: String, - pub file: Option, + // fake name if you need to like ", + pub file: Option>, pub line: u32, // use 0 for no line info } @@ -59,6 +96,69 @@ unsafe fn extract_function_name(func: &zend_function) -> Option { Some(String::from_utf8_lossy(buffer.as_slice()).into_owned()) } +unsafe fn handle_file_cache_slot_helper( + execute_data: &zend_execute_data, + string_table: &mut RefMut, + cache_slots: &mut [usize; 2], +) -> Option> { + let offset = if cache_slots[1] > 0 { + cache_slots[1] + } else { + // Safety: if we have cache slots, we definitely have a func. + let func = &*execute_data.func; + let file = if func.type_ == ZEND_USER_FUNCTION as u8 { + let bytes = zend_string_to_bytes(func.op_array.filename.as_mut()); + String::from_utf8_lossy(bytes) + } else { + return None; + }; + let offset = string_table.insert(file.as_ref()); + cache_slots[1] = offset; + offset + }; + let str = string_table.get_offset(offset); + + // Safety: changing the lifetime to 'static is safe because + // the other threads using it are joined before this thread + // ever dies. + // todo: this is _not_ ZTS safe. + Some(Cow::Borrowed(transmute(str))) +} + +unsafe fn handle_file_cache_slot( + execute_data: &zend_execute_data, + string_table: &mut RefMut, + cache_slots: &mut [usize; 2], +) -> (Option>, u32) { + match handle_file_cache_slot_helper(execute_data, string_table, cache_slots) { + Some(filename) => { + let lineno = match execute_data.opline.as_ref() { + Some(opline) => opline.lineno, + None => 0, + }; + (Some(filename), lineno) + } + None => (None, 0), + } +} + +unsafe fn handle_function_cache_slot( + func: &zend_function, + string_table: &mut RefMut, + cache_slots: &mut [usize; 2], +) -> Option> { + if cache_slots[0] > 0 { + let offset = cache_slots[0]; + let str = string_table.get_offset(offset); + Some(Cow::Owned(str.to_string())) + } else { + let name = extract_function_name(func)?; + let offset = string_table.insert(name.as_ref()); + cache_slots[0] = offset; + Some(Cow::Owned(name)) + } +} + unsafe fn extract_file_and_line(execute_data: &zend_execute_data) -> (Option, u32) { // This should be Some, just being cautious. match execute_data.func.as_ref() { @@ -75,6 +175,58 @@ unsafe fn extract_file_and_line(execute_data: &zend_execute_data) -> (Option Option { + #[cfg(not(feature = "stack_walking_tests"))] + use crate::bindings::ddog_php_prof_function_run_time_cache; + #[cfg(feature = "stack_walking_tests")] + use crate::bindings::ddog_test_php_prof_function_run_time_cache as ddog_php_prof_function_run_time_cache; + + let func = execute_data.func.as_ref()?; + CACHED_STRINGS.with(|cell| { + let mut string_table = cell.borrow_mut(); + let (function, file, line) = match ddog_php_prof_function_run_time_cache(func) { + Some(cache_slots) => { + FUNCTION_CACHE_STATS.with(|cell| { + let mut stats = cell.borrow_mut(); + if cache_slots[0] == 0 { + stats.missed += 1; + } else { + stats.hit += 1; + } + }); + let function = handle_function_cache_slot(func, &mut string_table, cache_slots); + let (file, line) = + handle_file_cache_slot(execute_data, &mut string_table, cache_slots); + + (function, file, line) + } + + None => { + FUNCTION_CACHE_STATS.with(|cell| { + let mut stats = cell.borrow_mut(); + stats.not_applicable += 1; + }); + let function = extract_function_name(func).map(Cow::Owned); + let (file, line) = extract_file_and_line(execute_data); + let file = file.map(Cow::Owned); + (function, file, line) + } + }; + + if function.is_some() || file.is_some() { + Some(ZendFrame { + function: function.unwrap_or(Cow::Borrowed(" Option { if let Some(func) = execute_data.func.as_ref() { let function = extract_function_name(func); @@ -83,10 +235,10 @@ unsafe fn collect_call_frame(execute_data: &zend_execute_data) -> Option { + pub vec: Vec<&'a str>, + pub map: HashMap<&'a str, usize, RandomState>, +} + +impl<'a> Default for BorrowedStringTable<'a> { + fn default() -> Self { + /// The initial size of the Vec. At the time of writing, Vec would + /// choose size 4. This is expected to be much too small for the + /// use-case, so use a larger initial capacity to save a few + /// re-allocations in the beginning. + /// This is just an educated estimate, not a finely tuned value. + const INITIAL_VEC_CAPACITY: usize = 1024 / std::mem::size_of::<&str>(); + + /// A HashMap is less straight-forward, but it uses more memory for + /// the same number of elements compared to a Vec, but not twice as + /// much for our situation, so dividing by 2 should be okay, at least + /// until further measurement is done. + const INITIAL_MAP_CAPACITY: usize = INITIAL_VEC_CAPACITY / 2; + + let mut vec = Vec::with_capacity(INITIAL_VEC_CAPACITY); + vec.push(""); + let mut map = HashMap::with_capacity_and_hasher(INITIAL_MAP_CAPACITY, Default::default()); + map.insert("", 0); + Self { vec, map } + } +} + +impl<'a> super::StringTable for BorrowedStringTable<'a> { + #[inline] + fn len(&self) -> usize { + self.vec.len() + } + + #[inline] + fn is_empty(&self) -> bool { + self.vec.is_empty() + } + + fn insert_full(&mut self, str: &str) -> (usize, bool) { + match self.map.get(str) { + None => { + let id = self.vec.len(); + // Safety: DEFINITELY NOT SAFE. The caller _must_ + let borrowed = unsafe { std::mem::transmute(str) }; + self.vec.push(borrowed); + + self.map.insert(borrowed, id); + debug_assert_eq!(self.map.len(), self.vec.len()); + (id, true) + } + Some(offset) => (*offset, false), + } + } + + #[inline] + fn get_offset(&self, offset: usize) -> &str { + self.vec[offset] + } + + #[inline] + fn get_range(&self, range: Range) -> &[&str] { + &self.vec[range] + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + pub fn borrowed_string_table() { + let set = BorrowedStringTable::<'static>::default(); + super::super::tests::basic(set); + } +} diff --git a/profiling/src/string_table/bump_owned.rs b/profiling/src/string_table/bump_owned.rs new file mode 100644 index 00000000000..3ed2eb4a69d --- /dev/null +++ b/profiling/src/string_table/bump_owned.rs @@ -0,0 +1,70 @@ +use bumpalo::{collections, Bump}; +use std::ops::Range; + +pub struct BorrowedStringTable<'b> { + arena: &'b Bump, + pub set: super::borrowed::BorrowedStringTable<'b>, +} + +impl<'b> BorrowedStringTable<'b> { + #[inline] + pub fn new(arena: &'b Bump) -> Self { + Self { + arena, + set: Default::default(), + } + } +} + +impl<'b> super::StringTable for BorrowedStringTable<'b> { + #[inline] + fn len(&self) -> usize { + self.set.len() + } + + fn insert_full(&mut self, str: &str) -> (usize, bool) { + match self.set.map.get(str) { + None => { + let owned = collections::String::from_str_in(str, self.arena); + + /* Consume the string but retain a reference to its data in + * the arena. The reference is valid as long as the arena + * doesn't get reset. This is partly the reason for the unsafe + * marker on `StringTable::new`. + */ + let bumped_str = owned.into_bump_str(); + + let id = self.set.vec.len(); + self.set.vec.push(bumped_str); + + self.set.map.insert(bumped_str, id); + assert_eq!(self.set.vec.len(), self.set.map.len()); + (id, true) + } + Some(offset) => (*offset, false), + } + } + + #[inline] + fn get_offset(&self, offset: usize) -> &str { + self.set.get_offset(offset) + } + + #[inline] + fn get_range(&self, range: Range) -> &[&str] { + self.set.get_range(range) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + pub fn bump_owned_string_table() { + // small size, to allow testing re-alloc. + let bump = Bump::with_capacity(16); + let set = BorrowedStringTable::new(&bump); + super::super::tests::basic(set); + } +} diff --git a/profiling/src/string_table/mod.rs b/profiling/src/string_table/mod.rs new file mode 100644 index 00000000000..0d6fb938eb7 --- /dev/null +++ b/profiling/src/string_table/mod.rs @@ -0,0 +1,74 @@ +use std::ops::Range; + +mod borrowed; +mod bump_owned; +mod owned; + +pub use borrowed::*; +pub use owned::*; + +pub trait StringTable { + fn len(&self) -> usize; + + #[inline] + fn is_empty(&self) -> bool { + self.len() == 0 + } + + #[inline] + fn insert(&mut self, item: &str) -> usize { + self.insert_full(item).0 + } + + fn insert_full(&mut self, item: &str) -> (usize, bool); + + fn get_offset(&self, offset: usize) -> &str; + fn get_range(&self, range: Range) -> &[&str]; +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Pass in an empty set, which should only include the empty string at 0. + pub fn basic(mut set: S) { + // the empty string must always be included in the set at 0. + let empty_str = set.get_offset(0); + assert_eq!("", empty_str); + + let cases = &[ + (0, ""), + (1, "local root span id"), + (2, "span id"), + (3, "trace endpoint"), + (4, "samples"), + (5, "count"), + (6, "wall-time"), + (7, "nanoseconds"), + (8, "cpu-time"), + (9, ", +} + +pub struct OwnedStringTable { + inner: StringTableCell, +} + +impl OwnedStringTable { + #[inline] + pub fn new() -> Self { + Self::with_capacity(4000) + } + + #[inline] + pub fn with_capacity(capacity: usize) -> Self { + let arena = Bump::with_capacity(capacity); + let inner = StringTableCell::new(arena, |arena| BorrowedStringTable::new(arena)); + Self { inner } + } +} + +impl Default for OwnedStringTable { + fn default() -> Self { + Self::new() + } +} + +impl super::StringTable for OwnedStringTable { + #[inline] + fn len(&self) -> usize { + self.inner.with_dependent(|table| table.len()) + } + + #[inline] + fn insert_full(&mut self, str: &str) -> (usize, bool) { + self.inner + .with_dependent_mut(|table| table.insert_full(str)) + } + + #[inline] + fn get_offset(&self, offset: usize) -> &str { + self.inner.with_dependent(|table| table.get_offset(offset)) + } + + #[inline] + fn get_range(&self, range: Range) -> &[&str] { + self.inner.with_dependent(|table| table.get_range(range)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// If this fails, bumpalo may have changed its allocation patterns, and + /// [OwnedStringTable::new] may need adjusted. + #[test] + fn test_bump() { + let arena = Bump::with_capacity(4000); + assert_eq!(4096 - 64, arena.chunk_capacity()); + } + + #[test] + fn owned_string_table() { + // small size, to allow testing re-alloc. + let set = OwnedStringTable::with_capacity(64); + super::super::tests::basic(set); + } +} diff --git a/profiling/tests/phpt/trampolines_01.phpt b/profiling/tests/phpt/trampolines_01.phpt new file mode 100644 index 00000000000..13daa04e158 --- /dev/null +++ b/profiling/tests/phpt/trampolines_01.phpt @@ -0,0 +1,49 @@ +--TEST-- +[profiling] sampling trampolines can cause crashes. +--DESCRIPTION-- +The ZEND_OP_ARRAY_EXTENSION shouldn't be used if the function flags have +`ZEND_ACC_CALL_VIA_TRAMPOLINE` set because trampolines use the run_time_cache +for internal things. This very sharp edge was not documented. + +See also: +https://github.com/php/php-src/commit/213248a0b91ef1a77aa91e4c91e7927328dcc839 +https://github.com/DataDog/dd-trace-php/issues/1993#issuecomment-1491105610 +--SKIPIF-- + +--INI-- +datadog.profiling.enabled=1 +datadog.profiling.experimental_allocation_enabled=1 +max_execution_time=10 +--FILE-- +castSpell(); +} + +echo "Done.\n"; +?> +--EXPECTF-- +Fatal error: Maximum execution time of %d seconds exceeded in %s on line %d