diff --git a/lisa/trace.py b/lisa/trace.py index 801d9c60266c22304f305013fa53a13a9090ea51..4ce6211df3580d9156171c8e4d12e9b6382c69ff 100644 --- a/lisa/trace.py +++ b/lisa/trace.py @@ -5534,12 +5534,17 @@ class _Trace(Loggable, _InternalTraceBase): elif key == 'symbols-address': # Unzip the dict into a list of keys and list of values, since # that will be cheaper to deserialize and serialize to JSON - value = tuple(unzip_into( + addrs, names = tuple(unzip_into( 2, # Turn to a list to allow JSON caching, since JSON cannot # have non-string keys dict(value).items() )) + names = [ + [name] if isinstance(name, str) else name + for name in names + ] + value = (addrs, names) return value @@ -5602,6 +5607,33 @@ class _Trace(Loggable, _InternalTraceBase): # Note that this will not take into account meta-events. self._source_events_known = True + elif key == 'symbols-address': + # The parsers can provide a list of names for each address, but + # our API only exposes a single name, so we pick the best one + def pick(names): + # If we can, we choose from the names that are valid + # identifiers. This will weed-out strange symbols like arm + # mapping symbols and the likes. + best_names = sorted( + ( + name + for name in names + if name.isidentifier() + ), + key=len, + ) + if best_names: + # Return the longest name, as it's less likely to be a + # less descriptive section name or something like that. + return best_names[-1] + else: + return names[0] + + value = { + addr: pick(names) + for addr, names in value.items() + } + return value def _get(key): diff --git a/tests/test_trace.py b/tests/test_trace.py index 9b1c96aa48f8bb12f8911c88d1a23076d2fdde03..04fb7039262c2ce7019401dfecd4659bd27d0b3a 100644 --- a/tests/test_trace.py +++ b/tests/test_trace.py @@ -386,6 +386,63 @@ class TraceTestCase(StorageTestCase): # Proxy check for detecting delta computation changes assert df.delta.sum() == pytest.approx(134.568219) + def test_metadata_symbols_address(self): + trace = self.get_trace('doc') + syms = trace.get_metadata('symbols-address') + assert len(syms) == 138329 + assert all( + isinstance(key, int) and isinstance(value, str) + for key, value in syms.items() + ) + assert syms[18446603336539106032] == 'sunrpc_net_id' + + def test_metadata_time_range(self): + trace = self.get_trace('doc') + time_range = trace.get_metadata('time-range') + assert time_range[0].as_nanoseconds == 470783168860 + assert time_range[1].as_nanoseconds == 473280164600 + + def test_metadata_cpus_count(self): + trace = self.get_trace('doc') + count = trace.get_metadata('cpus-count') + assert count == 6 + + def test_metadata_available_events(self): + trace = self.get_trace('doc') + events = trace.get_metadata('available-events') + assert set(events) == { + 'cpu_frequency', + 'cpu_idle', + 'print', + 'sched_cpu_capacity', + 'sched_migrate_task', + 'sched_overutilized', + 'sched_pelt_cfs', + 'sched_pelt_dl', + 'sched_pelt_irq', + 'sched_pelt_rt', + 'sched_pelt_se', + 'sched_process_exec', + 'sched_process_exit', + 'sched_process_fork', + 'sched_process_free', + 'sched_process_wait', + 'sched_stat_runtime', + 'sched_switch', + 'sched_util_est_cfs', + 'sched_util_est_se', + 'sched_wakeup', + 'sched_wakeup_new', + 'sched_waking', + 'task_newtask', + 'task_rename', + } + + def test_metadata_trace_id(self): + trace = self.get_trace('doc') + trace_id = trace.get_metadata('trace-id') + assert trace_id == 'trace.dat-8785260356321690258' + class TestTrace(TraceTestCase): """Smoke tests for LISA's Trace class""" diff --git a/tools/recipes/trace-tools.recipe b/tools/recipes/trace-tools.recipe index 279cab9af8b4028f709072bca787d114f3c953bf..160adaf36446afb307f395edec95b3af6eebe9c2 100644 --- a/tools/recipes/trace-tools.recipe +++ b/tools/recipes/trace-tools.recipe @@ -1,6 +1,6 @@ #! /bin/bash -ALPINE_VERSION=v3.21 +ALPINE_VERSION=v3.21.3 ALPINE_BUILD_DEPENDENCIES=(bash git curl musl-dev clang lld) BROKEN_CROSS_COMPILATION=0 @@ -43,6 +43,7 @@ install_rust() { build_tracedump() { cd trace-parser/trace-tools && + export RUSTC_BOOTSTRAP=1 time RUSTFLAGS="$RUSTFLAGS -C target-feature=+crt-static" cargo build --locked --profile release-lisa --target="$(make_triplet)" } diff --git a/tools/trace-parser/trace-tools/Cargo.lock b/tools/trace-parser/trace-tools/Cargo.lock index 5c1e709934acaaba7afbfa5a3c3c3d9f931ec512..178d51e73662bb59b37e250aaea9ad303b858311 100644 --- a/tools/trace-parser/trace-tools/Cargo.lock +++ b/tools/trace-parser/trace-tools/Cargo.lock @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "arrow" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755b6da235ac356a869393c23668c663720b8749dd6f15e52b6c214b4b964cc7" +checksum = "84ef243634a39fb6e9d1710737e7a5ef96c9bacabd2326859ff889bc9ef755e5" dependencies = [ "arrow-arith", "arrow-array", @@ -110,9 +110,9 @@ dependencies = [ [[package]] name = "arrow-arith" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64656a1e0b13ca766f8440752e9a93e11014eec7b67909986f83ed0ab1fe37b8" +checksum = "8f420c6aef51dad2e4a96ce29c0ec90ad84880bdb60b321c74c652a6be07b93f" dependencies = [ "arrow-array", "arrow-buffer", @@ -124,9 +124,9 @@ dependencies = [ [[package]] name = "arrow-array" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a4a6d2896083cfbdf84a71a863b22460d0708f8206a8373c52e326cc72ea1a" +checksum = "24bda5ff6461a4ff9739959b3d57b377f45e3f878f7be1a4f28137c0a8f339fa" dependencies = [ "ahash", "arrow-buffer", @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "arrow-buffer" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef870583ce5e4f3b123c181706f2002fb134960f9a911900f64ba4830c7a43a" +checksum = "bc6ed265c73f134a583d02c3cab5e16afab9446d8048ede8707e31f85fad58a0" dependencies = [ "bytes", "half", @@ -151,9 +151,9 @@ dependencies = [ [[package]] name = "arrow-cast" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac7eba5a987f8b4a7d9629206ba48e19a1991762795bbe5d08497b7736017ee" +checksum = "01c648572391edcef10e5fd458db70ba27ed6f71bcaee04397d0cfb100b34f8b" dependencies = [ "arrow-array", "arrow-buffer", @@ -171,9 +171,9 @@ dependencies = [ [[package]] name = "arrow-data" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b095e8a4f3c309544935d53e04c3bfe4eea4e71c3de6fe0416d1f08bb4441a83" +checksum = "5f2cebf504bb6a92a134a87fff98f01b14fbb3a93ecf7aef90cd0f888c5fffa4" dependencies = [ "arrow-buffer", "arrow-schema", @@ -183,9 +183,9 @@ dependencies = [ [[package]] name = "arrow-ipc" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65c63da4afedde2b25ef69825cd4663ca76f78f79ffe2d057695742099130ff6" +checksum = "8e6405b287671c88846e7751f7291f717b164911474cabac6d3d8614d5aa7374" dependencies = [ "arrow-array", "arrow-buffer", @@ -196,9 +196,9 @@ dependencies = [ [[package]] name = "arrow-ord" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c07223476f8219d1ace8cd8d85fa18c4ebd8d945013f25ef5c72e85085ca4ee" +checksum = "e103c13d4b80da28339c1d7aa23dd85bd59f42158acc45d39eeb6770627909ce" dependencies = [ "arrow-array", "arrow-buffer", @@ -209,9 +209,9 @@ dependencies = [ [[package]] name = "arrow-row" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91b194b38bfd89feabc23e798238989c6648b2506ad639be42ec8eb1658d82c4" +checksum = "170549a11b8534f3097a0619cfe89c42812345dc998bcf81128fc700b84345b8" dependencies = [ "arrow-array", "arrow-buffer", @@ -222,15 +222,15 @@ dependencies = [ [[package]] name = "arrow-schema" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f40f6be8f78af1ab610db7d9b236e21d587b7168e368a36275d2e5670096735" +checksum = "a5c53775bba63f319189f366d2b86e9a8889373eb198f07d8544938fc9f8ed9a" [[package]] name = "arrow-select" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac265273864a820c4a179fc67182ccc41ea9151b97024e1be956f0f2369c2539" +checksum = "0a99003b2eb562b8d9c99dfb672306f15e94b20d3734179d596895703e821dcf" dependencies = [ "ahash", "arrow-array", @@ -242,9 +242,9 @@ dependencies = [ [[package]] name = "arrow-string" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d44c8eed43be4ead49128370f7131f054839d3d6003e52aebf64322470b8fbd0" +checksum = "90fdb130ee8325f4cd8262e19bb6baa3cbcef2b2573c4bee8c6fda7ea08199d7" dependencies = [ "arrow-array", "arrow-buffer", @@ -286,9 +286,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "bumpalo" @@ -304,9 +304,9 @@ checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "bytemuck" -version = "1.21.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" [[package]] name = "byteorder" @@ -316,15 +316,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.14" +version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ "jobserver", "libc", @@ -339,21 +339,21 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.39" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", - "windows-targets", + "windows-link", ] [[package]] name = "clap" -version = "4.5.30" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d" +checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff" dependencies = [ "clap_builder", "clap_derive", @@ -361,9 +361,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.30" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c" +checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489" dependencies = [ "anstream", "anstyle", @@ -373,14 +373,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.28" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -491,9 +491,9 @@ checksum = "bf8ff09d6fe1e38d661703c924aff384cb95b131b989eda24ee036c6f4fc36da" [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "flatbuffers" @@ -548,9 +548,9 @@ dependencies = [ [[package]] name = "half" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" dependencies = [ "cfg-if", "crunchy", @@ -571,14 +571,15 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b2fd658b06e56721792c5df4475705b6cda790e9298d19d2f8af083457bcd127" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -615,9 +616,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" @@ -704,24 +705,24 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.169" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libdeflate-sys" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413b667c8a795fcbe6287a75a8ce92b1dae928172c716fe95044cb2ec7877941" +checksum = "38b72ad3fbf5ac78f2df7b36075e48adf2459b57c150b9e63937d0204d0f9cd7" dependencies = [ "cc", ] [[package]] name = "libdeflater" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78376c917eec0550b9c56c858de50e1b7ebf303116487562e624e63ce51453a" +checksum = "013344b17f9dceddff4872559ae19378bd8ee0479eccdd266d2dd2e894b4792f" dependencies = [ "libdeflate-sys", ] @@ -734,9 +735,9 @@ checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libmimalloc-sys" -version = "0.1.39" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +checksum = "07d0e07885d6a754b9c7993f2625187ad694ee985d60f23355ff0e7077261502" dependencies = [ "cc", "libc", @@ -744,9 +745,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.25" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "lz4_flex" @@ -774,9 +775,9 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +checksum = "99585191385958383e13f6b822e6b6d8d9cf928e7d286ceb092da92b43c87bc1" dependencies = [ "libmimalloc-sys", ] @@ -886,9 +887,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "ordered-float" @@ -901,9 +902,9 @@ dependencies = [ [[package]] name = "parquet" -version = "54.2.0" +version = "54.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "761c44d824fe83106e0600d2510c07bf4159a4985bf0569b513ea4288dc1b4fb" +checksum = "94243778210509a5a5e9e012872127180c155d73a9cd6e2df9243d213e81e100" dependencies = [ "ahash", "arrow-array", @@ -927,7 +928,6 @@ dependencies = [ "thrift", "twox-hash", "zstd", - "zstd-sys", ] [[package]] @@ -938,9 +938,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "proc-macro-error" @@ -976,18 +976,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -1032,53 +1032,53 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "ryu" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "semver" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "seq-macro" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" [[package]] name = "serde" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] name = "serde_json" -version = "1.0.138" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -1092,18 +1092,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "smartstring" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" -dependencies = [ - "autocfg", - "serde", - "static_assertions", - "version_check", -] - [[package]] name = "snap" version = "1.1.1" @@ -1135,9 +1123,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.98" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -1157,22 +1145,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -1220,7 +1208,6 @@ dependencies = [ "parquet", "serde", "serde_json", - "smartstring", "thiserror", "traceevent", ] @@ -1229,7 +1216,7 @@ dependencies = [ name = "traceevent" version = "0.1.0" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "bumpalo", "bytemuck", "deref-map", @@ -1258,9 +1245,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "utf8parse" @@ -1302,7 +1289,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", "wasm-bindgen-shared", ] @@ -1324,7 +1311,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1347,6 +1334,12 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + [[package]] name = "windows-sys" version = "0.59.0" @@ -1437,32 +1430,32 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] name = "zstd" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.2.1" +version = "7.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" +version = "2.0.15+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" dependencies = [ "cc", "pkg-config", diff --git a/tools/trace-parser/trace-tools/Cargo.toml b/tools/trace-parser/trace-tools/Cargo.toml index 729f4fa354d82d0b5a5000989ef1f73ec949915a..c28f7795e2b37e2d2a20ea93b390abb37342143b 100644 --- a/tools/trace-parser/trace-tools/Cargo.toml +++ b/tools/trace-parser/trace-tools/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "trace-tools" version = "0.1.0" -edition = "2021" +edition = "2024" [lib] name = "lib" @@ -13,7 +13,6 @@ path = "src/lib/lib.rs" traceevent = { path = "../traceevent", optional = true } thiserror = "2.0" -smartstring = {version = "1.0", features = ["serde"]} arrow = { version = "54.0", default-features = false } arrow-schema = { version = "54.0", default-features = false } arrow-array = { version = "54.0" } diff --git a/tools/trace-parser/trace-tools/src/bin/trace-dump.rs b/tools/trace-parser/trace-tools/src/bin/trace-dump.rs index ccf9b6bb594a56b9e5a37dba0ea16672f18d221d..1802c88e838a990a3ab3b5f683d1e0d2ba094606 100644 --- a/tools/trace-parser/trace-tools/src/bin/trace-dump.rs +++ b/tools/trace-parser/trace-tools/src/bin/trace-dump.rs @@ -164,11 +164,7 @@ fn _main() -> Result<(), Box> { if let Some(path) = &cli.errors_json { let errors = match &res { - Err(err) => err - .errors() - .into_iter() - .map(|err| err.to_string()) - .collect(), + Err(err) => err.errors().map(|err| err.to_string()).collect(), Ok(_) => Vec::new(), }; let mut file = File::create(path)?; diff --git a/tools/trace-parser/trace-tools/src/lib/error.rs b/tools/trace-parser/trace-tools/src/lib/error.rs index ed38ea70f9da78131467e4dbe777f75792cb4a14..4c034741395def94737ba64c923a5a2c8bf1ee3c 100644 --- a/tools/trace-parser/trace-tools/src/lib/error.rs +++ b/tools/trace-parser/trace-tools/src/lib/error.rs @@ -28,8 +28,8 @@ impl MultiError { } } - pub fn errors(&self) -> impl IntoIterator { - &self.errors + pub fn errors(&self) -> impl Iterator { + self.errors.iter() } } @@ -61,8 +61,8 @@ impl DynMultiError { }) } - pub fn errors(&self) -> impl IntoIterator { - self.0.errors().into_iter().map(AsRef::as_ref) + pub fn errors(&self) -> impl Iterator { + self.0.errors().map(AsRef::as_ref) } } diff --git a/tools/trace-parser/trace-tools/src/lib/tracedat/parquet/dump.rs b/tools/trace-parser/trace-tools/src/lib/tracedat/parquet/dump.rs index 2642dca37d9facd6032359a55eade4d6d74ea232..70fad5d1bbdbeb77a3db3f09d4a48404cea157bd 100644 --- a/tools/trace-parser/trace-tools/src/lib/tracedat/parquet/dump.rs +++ b/tools/trace-parser/trace-tools/src/lib/tracedat/parquet/dump.rs @@ -20,7 +20,7 @@ use core::{ ops::{Deref, DerefMut}, }; use std::{ - collections::{btree_map::Entry, BTreeMap}, + collections::{BTreeMap, btree_map::Entry}, fs::File, io::Write, path::PathBuf, @@ -30,18 +30,18 @@ use std::{ use arrow::datatypes::{DataType, Field, Fields, Schema}; use arrow_array::{ + RecordBatch, array::Array, builder::{ - ArrayBuilder, BinaryBuilder, BooleanBuilder, Int16Builder, Int32Builder, Int64Builder, - Int8Builder, ListBuilder, StringBuilder, UInt16Builder, UInt32Builder, UInt64Builder, - UInt8Builder, + ArrayBuilder, BinaryBuilder, BooleanBuilder, Int8Builder, Int16Builder, Int32Builder, + Int64Builder, ListBuilder, StringBuilder, UInt8Builder, UInt16Builder, UInt32Builder, + UInt64Builder, }, - RecordBatch, }; use arrow_schema::ArrowError; use crossbeam::{ - channel::{bounded, Sender}, - thread::{scope, Scope, ScopedJoinHandle}, + channel::{Sender, bounded}, + thread::{Scope, ScopedJoinHandle, scope}, }; use nom::{Finish as _, Parser as _}; use parquet::{ @@ -58,7 +58,7 @@ use serde::Serialize; use traceevent::{ buffer::{BufferError, EventVisitor}, cinterp::{EvalEnv, EvalError, Value}, - cparser::{identifier, ArrayKind, Type}, + cparser::{ArrayKind, Type, identifier}, header::{Address, EventDesc, EventId, FieldFmt, Header, HeaderError, LongSize, Timestamp}, io::BorrowingReadCore, print::{PrintArg, PrintAtom, PrintFmtError, PrintFmtStr, VBinSpecifier}, @@ -169,9 +169,9 @@ impl Metadata<'_> { let time_range = self.time_range; let mut json_value = serde_json::json!({ - "pid-comms": header.pid_comms().into_iter().collect::>(), + "pid-comms": header.pid_comms().collect::>(), "cpus-count": header.nr_cpus(), - "symbols-address": header.kallsyms().into_iter().collect::>(), + "symbols-address": header.kallsyms().map(|(addr, syms)| (addr, syms.collect())).collect::)>>(), // We cannot provide all events the kernel support here, as most of them // were not enabled during the trace. // "available-events": header.event_descs().into_iter().map(|desc| desc.name.deref()).collect::>(), @@ -296,7 +296,7 @@ where x => { break Err(MainError::DataMismatchingSchema( x.into_static().map(Box::new).ok(), - )) + )); } } } @@ -343,8 +343,7 @@ where ReadState::new(header, event_desc, chunk_size, &event_desc.name, make_props_builder(), scope, max_errors) }; - let state = EventCtx::Selected(SharedState::new(state)); - state + EventCtx::Selected(SharedState::new(state)) } else { EventCtx::NotSelected }; @@ -1009,7 +1008,10 @@ where visitor: &'ret EventVisitor<'i, 'h, 'edm, InitDescF, Ctx>, mut f: F, only_events: &Option>, - ) -> Result> + 'ret, MainError> + ) -> Result< + impl DerefMut> + 'ret + use<'scope, 'ret, InitDescF, Ctx, F>, + MainError, + > where 'i: 'ret, 'h: 'ret, @@ -1229,7 +1231,7 @@ where } } - fn drain_states(self) -> impl Iterator> { + fn drain_states(self) -> impl Iterator> + use<'scope> { match self.variant { ReadStateVariant::Generic(state) => { Box::new([state].into_iter()) as Box> @@ -1359,7 +1361,7 @@ where fields.push(("common_pid".into(), Type::I32)); let event_name = event_name.ok_or(MainError::NotAMetaEvent)?; let (full_schema, fields_schema) = Self::make_schemas(&event_name, header, fields)?; - Ok((event_name.into(), full_schema, fields_schema)) + Ok((event_name, full_schema, fields_schema)) } fn make_schemas( diff --git a/tools/trace-parser/trace-tools/src/lib/tracedat/print.rs b/tools/trace-parser/trace-tools/src/lib/tracedat/print.rs index 7e572658683a03fd8e8462e7a592c7f5d740f84e..5a64c913316a64718b2ad210de7fc33890960347 100644 --- a/tools/trace-parser/trace-tools/src/lib/tracedat/print.rs +++ b/tools/trace-parser/trace-tools/src/lib/tracedat/print.rs @@ -17,7 +17,7 @@ use std::{io::Write, ops::Deref as _}; use traceevent::{ - buffer::{flyrecord, BufferError, EventVisitor}, + buffer::{BufferError, EventVisitor, flyrecord}, cinterp::{BufferEnv, CompileError, Value}, header::{EventDesc, FieldFmt, Header, HeaderError}, io::BorrowingReadCore, @@ -43,6 +43,9 @@ pub enum MainError { #[error("Error while parsing pretty printing: {0}")] PrintError(#[from] PrintError), + #[error("Error while compiling pretty printing: {0}")] + CompileError(#[from] CompileError), + #[error("Unexpected type for PID value {}", match .0 { Some(val) => val.to_string(), None => "".into() @@ -67,16 +70,21 @@ pub fn print_events( .unwrap_or(0); struct EventCtx<'h> { - pid_fmt: Option<&'h FieldFmt>, + // We cannot clone MainError, so instead we keep a closure that can re-materialize the + // error. + pid_fmt: Result<&'h FieldFmt, Box MainError + 'h>>, } impl<'h> EventCtx<'h> { fn from_event_desc(_header: &'h Header, desc: &'h EventDesc) -> Self { let get = || { - let struct_fmt = &desc.event_fmt().ok()?.struct_fmt().ok()?; - let pid_fmt = struct_fmt.field_by_name("common_pid")?; - Some(pid_fmt) + let struct_fmt = &desc.event_fmt()?.struct_fmt()?; + let pid_fmt = struct_fmt + .field_by_name("common_pid") + .ok_or_else(|| CompileError::UnknownField("common_pid".into()))?; + Ok(pid_fmt) }; - let pid_fmt = get(); + let pid_fmt = get() + .map_err(|_| Box::new(move || get().unwrap_err()) as Box MainError>); EventCtx { pid_fmt } } @@ -94,11 +102,7 @@ pub fn print_events( let desc = visitor.event_desc()?; let ctx: &EventCtx = visitor.event_ctx()?; - let pid_fmt = ctx.pid_fmt.ok_or_else(|| { - let err: BufferError = CompileError::UnknownField("common_pid".into()).into(); - err - })?; - + let pid_fmt = ctx.pid_fmt.as_ref().map_err(|err| err())?; let pid = visitor.field_by_fmt(pid_fmt)?; let pid = match pid { Value::I64Scalar(x) => Ok(x.try_into().unwrap()), @@ -246,6 +250,6 @@ pub fn print_events( } let res: Result<_, MainError> = flyrecord(buffers, print_event!(), EventCtx::from_event_desc).map_err(Into::into); - res?.into_iter().collect::>()?; + res?.collect::>()?; Ok(()) } diff --git a/tools/trace-parser/traceevent/Cargo.lock b/tools/trace-parser/traceevent/Cargo.lock index c9586460680fdc912295d83cc2fe12affcfae2e3..5c7c18479a53593bee4713f6c45f5946825f20b1 100644 --- a/tools/trace-parser/traceevent/Cargo.lock +++ b/tools/trace-parser/traceevent/Cargo.lock @@ -10,9 +10,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "bumpalo" @@ -28,15 +28,15 @@ checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "bytemuck" -version = "1.21.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" [[package]] name = "cc" -version = "1.2.14" +version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ "jobserver", "libc", @@ -57,9 +57,9 @@ checksum = "bf8ff09d6fe1e38d661703c924aff384cb95b131b989eda24ee036c6f4fc36da" [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "genawaiter" @@ -111,24 +111,24 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.169" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libdeflate-sys" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413b667c8a795fcbe6287a75a8ce92b1dae928172c716fe95044cb2ec7877941" +checksum = "38b72ad3fbf5ac78f2df7b36075e48adf2459b57c150b9e63937d0204d0f9cd7" dependencies = [ "cc", ] [[package]] name = "libdeflater" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78376c917eec0550b9c56c858de50e1b7ebf303116487562e624e63ce51453a" +checksum = "013344b17f9dceddff4872559ae19378bd8ee0479eccdd266d2dd2e894b4792f" dependencies = [ "libdeflate-sys", ] @@ -179,15 +179,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "proc-macro-error" @@ -223,18 +223,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -275,9 +275,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.98" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -297,22 +297,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -349,9 +349,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "version_check" @@ -361,27 +361,27 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "zstd" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.2.1" +version = "7.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" +version = "2.0.15+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" dependencies = [ "cc", "pkg-config", diff --git a/tools/trace-parser/traceevent/Cargo.toml b/tools/trace-parser/traceevent/Cargo.toml index d6936724012646f3b7d7bd202e2a773655248cbc..7fc0bbdd05c3db9500b649ee8c76c28de09d69ae 100644 --- a/tools/trace-parser/traceevent/Cargo.toml +++ b/tools/trace-parser/traceevent/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "traceevent" version = "0.1.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/trace-parser/traceevent/src/buffer.rs b/tools/trace-parser/traceevent/src/buffer.rs index 13d34ec5b1579895be5affc4eacab9dcfde7a18c..f5c8d96eb668ea9ea43dd89710f33da0f1d751c1 100644 --- a/tools/trace-parser/traceevent/src/buffer.rs +++ b/tools/trace-parser/traceevent/src/buffer.rs @@ -23,14 +23,14 @@ use core::{ ops::{Deref, DerefMut as _}, }; use std::{ - collections::{btree_map::Entry, BTreeMap}, + collections::{BTreeMap, btree_map::Entry}, io, sync::{Arc, Mutex}, }; use bytemuck::cast_slice; use deref_map::DerefMap; -use genawaiter::{sync::gen, yield_}; +use genawaiter::{sync::r#gen as gen_, yield_}; use once_cell::unsync::OnceCell; use crate::{ @@ -41,9 +41,9 @@ use crate::{ cparser::{ArrayKind, DynamicKind, Type}, error::convert_err_impl, header::{ - buffer_locations, Abi, BufferId, Cpu, EventDesc, EventId, FieldFmt, FileSize, Header, - HeaderError, HeaderV6, HeaderV7, LongSize, MemAlign, MemOffset, MemSize, Options, - Signedness, Timestamp, + Abi, BufferId, Cpu, EventDesc, EventId, FieldFmt, FileSize, Header, HeaderError, HeaderV6, + HeaderV7, LongSize, MemAlign, MemOffset, MemSize, Options, Signedness, Timestamp, + buffer_locations, }, io::{BorrowingRead, BorrowingReadCore}, iterator::MergedIterator, @@ -85,11 +85,7 @@ where fn new(header: &'h Header, make_ctx: Arc>) -> Self { EventDescMap { header, - cold_map: header - .event_descs() - .into_iter() - .map(|desc| (desc.id, desc)) - .collect(), + cold_map: header.event_descs().map(|desc| (desc.id, desc)).collect(), hot_map: BTreeMap::new(), make_ctx, } @@ -216,23 +212,14 @@ impl<'i, 'h, 'edm, MakeCtx, Ctx> EventVisitor<'i, 'h, 'edm, MakeCtx, Ctx> { } } -/// Capture a lifetime syntactically to avoid E0700 when using impl in return position -pub trait CaptureLifetime<'a> {} -impl CaptureLifetime<'_> for T {} - impl<'i, 'h, 'edm, MakeCtx, Ctx> EventVisitor<'i, 'h, 'edm, MakeCtx, Ctx> where MakeCtx: 'h + FnMut(&'h Header, &'h EventDesc) -> Ctx, { pub fn fields<'a>( &'a self, - ) -> Result< - impl Iterator, BufferError>)> - + CaptureLifetime<'h> - + CaptureLifetime<'edm> - + CaptureLifetime<'i>, - BufferError, - > { + ) -> Result, BufferError>)>, BufferError> + { let event_desc = self.event_desc()?; let struct_fmt = &event_desc.event_fmt()?.struct_fmt()?; let mut fields = struct_fmt.fields.iter(); @@ -863,12 +850,12 @@ impl HeaderV6 { #[inline] unsafe fn transmute_lifetime<'b, T: ?Sized>(x: &T) -> &'b T { - core::mem::transmute(x) + unsafe { core::mem::transmute(x) } } #[inline] unsafe fn transmute_lifetime_mut<'b, T: ?Sized>(x: &mut T) -> &'b mut T { - core::mem::transmute(x) + unsafe { core::mem::transmute(x) } } /// Parse the flyrecord buffers. @@ -886,7 +873,7 @@ pub fn flyrecord<'i, 'h, R, F, IntoIter, MakeCtx, Ctx>( buffers: IntoIter, mut f: F, make_ctx: MakeCtx, -) -> Result + 'h + CaptureLifetime<'i>, BufferError> +) -> Result + 'h, BufferError> where IntoIter: IntoIterator>, F: 'h @@ -907,7 +894,7 @@ where // in the header and is shared. This ensures we will not parse event // format more than once, which is the main cost here. let mut desc_map = EventDescMap::new(header, make_ctx); - gen!({ + gen_!({ let buf_id = buffer.id; let page_size = buffer.page_size; loop { @@ -1162,6 +1149,7 @@ where } } +#[allow(clippy::type_complexity)] fn extract_page<'a, 'b: 'a, 'h, I>( header: &'h Header, buf_id: &'a BufferId, @@ -1169,7 +1157,7 @@ fn extract_page<'a, 'b: 'a, 'h, I>( page_size: MemSize, ) -> Result< Option<( - impl Deref + 'a, + impl Deref + 'a + use<'a, I>, Timestamp, Option, )>, @@ -1422,7 +1410,7 @@ impl PrintFmtStr { header: &'a Header, scratch: &'a ScratchAlloc, input: &'a [u32], - ) -> impl IntoIterator, BufferError>> { + ) -> impl Iterator, BufferError>> { let mut i = 0; let mut decoders = self.vbin_decoders(header).iter(); let mut failed = false; diff --git a/tools/trace-parser/traceevent/src/cinterp.rs b/tools/trace-parser/traceevent/src/cinterp.rs index abbd96ccb6709012098c32f8f29bc05307a08874..160dcc7ce5f516cbaab2028753e381ff98deb7d3 100644 --- a/tools/trace-parser/traceevent/src/cinterp.rs +++ b/tools/trace-parser/traceevent/src/cinterp.rs @@ -73,7 +73,7 @@ pub enum CompileError { #[error("Size of this type is unknown: {0:?}")] UnknownSize(Type), - #[error("Non arithmetic operand used with arithmetic operator")] + #[error("Non arithmetic operand used with arithmetic operator: {0:?}")] NonArithmeticOperand(Type), #[error("Mismatching types in operands of {0:?}: {1:?} and {2:?}")] @@ -85,6 +85,9 @@ pub enum CompileError { #[error("The field \"{0}\" does not exist")] UnknownField(String), + #[error("Unknown variable: {0}")] + UnknownVariable(String), + #[error("Values of this type cannot be decoded from a buffer: {0:?}")] NonDecodableType(Type), } @@ -119,6 +122,9 @@ pub enum EvalError { #[error("Event data not available")] NoEventData, + #[error("Unknown variable: {0}")] + UnknownVariable(String), + #[error("No header available")] NoHeader, @@ -640,7 +646,7 @@ impl<'a> Value<'a> { /// Iterate over the bytes of array-like values, including [Value::Raw]. /// [Value::Str] iterator will yield the null terminator of the C string. - pub fn to_bytes(&self) -> Option + '_> { + pub fn to_bytes(&self) -> Option + '_> { use Value::*; let (add_null, slice) = match self { @@ -796,9 +802,7 @@ impl<'a> Value<'a> { impl fmt::Display for Value<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { macro_rules! display { - ($x:expr) => {{ - fmt::Display::fmt(&$x, f) - }}; + ($x:expr) => {{ fmt::Display::fmt(&$x, f) }}; } match self { @@ -840,6 +844,8 @@ where { /// Provide an [Evaluator] that will give the value of the `id` event field when evaluated. fn field_getter(&self, id: &str) -> Result, CompileError>; + + fn as_dyn(&self) -> &dyn CompileEnv<'ce>; } /// Evaluation environment. @@ -850,7 +856,11 @@ where /// Dereference a static value at the given address. /// /// This could for example be a string in the string table stored in the header. - fn deref_static(&self, _addr: u64) -> Result, EvalError>; + fn deref_static(&self, addr: u64) -> Result, EvalError>; + + /// Get the value of the given variable. + fn variable_value(&self, id: &str) -> Result, EvalError>; + /// Binary content of the current event record being processed. fn event_data(&self) -> Result<&[u8], EvalError>; @@ -861,52 +871,6 @@ where fn header(&self) -> Result<&Header, EvalError>; } -impl<'ee, 'eeref> EvalEnv<'eeref> for &'eeref (dyn CompileEnv<'ee> + 'ee) { - #[inline] - fn deref_static(&self, addr: u64) -> Result, EvalError> { - (*self).deref_static(addr) - } - - #[inline] - fn event_data(&self) -> Result<&[u8], EvalError> { - (*self).event_data() - } - - #[inline] - fn scratch(&self) -> &ScratchAlloc { - (*self).scratch() - } - - #[inline] - fn header(&self) -> Result<&Header, EvalError> { - (*self).header() - } -} - -impl ParseEnv for &(dyn ParseEnv + '_) { - fn field_typ(&self, id: &str) -> Result { - (*self).field_typ(id) - } - fn abi(&self) -> &Abi { - (*self).abi() - } -} - -impl<'ce> ParseEnv for &(dyn CompileEnv<'ce> + 'ce) { - fn field_typ(&self, id: &str) -> Result { - (*self).field_typ(id) - } - fn abi(&self) -> &Abi { - (*self).abi() - } -} - -impl<'ce, 'ceref> CompileEnv<'ceref> for &'ceref (dyn CompileEnv<'ce> + 'ce) { - fn field_getter(&self, id: &str) -> Result, CompileError> { - (*self).field_getter(id) - } -} - pub(crate) struct BasicEnv<'pe, PE: ?Sized> { scratch: ScratchAlloc, penv: &'pe PE, @@ -937,6 +901,11 @@ where fn deref_static(&self, addr: Address) -> Result, EvalError> { Err(EvalError::CannotDeref(addr)) } + + fn variable_value(&self, id: &str) -> Result, EvalError> { + Err(EvalError::UnknownVariable(id.to_owned())) + } + fn event_data(&self) -> Result<&[u8], EvalError> { Err(EvalError::NoEventData) } @@ -950,6 +919,12 @@ where fn field_typ(&self, id: &str) -> Result { self.penv.field_typ(id) } + + #[inline] + fn variable_typ(&self, id: &str) -> Result { + self.penv.variable_typ(id) + } + #[inline] fn abi(&self) -> &Abi { self.penv.abi() @@ -964,6 +939,11 @@ where fn field_getter(&self, id: &str) -> Result, CompileError> { Err(CompileError::UnknownField(id.into())) } + + #[inline] + fn as_dyn(&self) -> &dyn CompileEnv<'ce> { + self + } } /// [EvalEnv] used to manipulate [Value] (e.g. call [Value::deref_ptr]) in the context of a given @@ -995,6 +975,11 @@ impl<'ee> EvalEnv<'ee> for BufferEnv<'ee> { self.header.deref_static(addr) } + #[inline] + fn variable_value(&self, id: &str) -> Result, EvalError> { + self.header.constant_value(id) + } + fn event_data(&self) -> Result<&[u8], EvalError> { Ok(self.data) } @@ -1193,7 +1178,7 @@ fn convert_arith_op<'ce, CE>( expr: &Expr, ) -> Result<(Type, Box), CompileError> where - CE: CompileEnv<'ce>, + CE: ?Sized + CompileEnv<'ce>, { let typ = expr.typ(cenv)?; let promoted = typ.promote(); @@ -1204,16 +1189,17 @@ impl Type { /// Byte-size of the type. pub fn size(&self, abi: &Abi) -> Result { let typ = self.resolve_wrapper(); - use Type::*; match typ { - Pointer(_) => Ok(abi.long_size.into()), - Array(typ, size) => match size { + Type::Pointer(_) => Ok(abi.long_size.into()), + Type::Array(typ, size) => match size { ArrayKind::Fixed(Ok(size)) => { let item = typ.size(abi)?; Ok(size * item) } _ => Err(CompileError::UnknownSize(*typ.clone())), }, + // GNU extension + Type::Void => Ok(1), _ => { let info = typ .arith_info() @@ -1443,7 +1429,7 @@ impl Expr { fn _simplify<'ce, CE>(self, cenv: &'ce CE) -> Expr where - CE: CompileEnv<'ce>, + CE: ?Sized + CompileEnv<'ce>, { let compiled = self.clone()._compile(cenv); self._do_simplify(cenv, compiled) @@ -1455,11 +1441,11 @@ impl Expr { compiled: Result, CompileError>, ) -> Expr where - CE: CompileEnv<'ce>, + CE: ?Sized + CompileEnv<'ce>, { match compiled { Ok(eval) => match self.typ(cenv) { - Ok(typ) => match eval.eval(cenv) { + Ok(typ) => match eval.eval(cenv.as_dyn()) { Ok(value) => match value.into_static() { Ok(value) => Expr::Evaluated(typ, value), Err(_) => self, @@ -1479,7 +1465,7 @@ impl Expr { /// the same expression over and over again. pub fn compile<'ce, CE>(self, cenv: &'ce CE) -> Result, CompileError> where - CE: CompileEnv<'ce>, + CE: ?Sized + CompileEnv<'ce>, { // Type check the AST. This should be done only once on the root node, so any recursive // compilation invocations are done via _compile() to avoid re-doing it and avoid an O(N^2) @@ -1490,7 +1476,7 @@ impl Expr { fn _compile<'ce, CE>(self, cenv: &'ce CE) -> Result, CompileError> where - CE: CompileEnv<'ce>, + CE: ?Sized + CompileEnv<'ce>, { use Expr::*; let abi = cenv.abi(); @@ -1653,8 +1639,10 @@ impl Expr { let eval = match self { Evaluated(_typ, value) => Ok(new_dyn_evaluator(move |_| Ok(value.clone()))), - Variable(_typ, id) => Ok(new_dyn_evaluator(move |_| Ok(Value::Variable(id.clone())))), - + Variable(_typ, id) => Ok(new_dyn_evaluator(move |env| match id.deref() { + "REC" => Ok(Value::Variable(id.clone())), + _ => env.variable_value(&id), + })), MemberAccess(expr, member) => { let expr = simplify(*expr); match &expr { @@ -1782,7 +1770,7 @@ impl Expr { } let eval = recurse(*expr)?; - match eval.eval(cenv) { + match eval.eval(cenv.as_dyn()) { Err(_) => Ok(new_dyn_evaluator(move |env| { let value = eval.eval(env)?; negate!(value) @@ -1883,7 +1871,7 @@ impl Expr { let eval_idx = recurse(*idx)?; let eval_expr = recurse(expr.clone())?; - match eval_idx.eval(cenv) { + match eval_idx.eval(cenv.as_dyn()) { // If we access element 0 at compile time, that is simply // dereferencing the value as a pointer. Ok(Value::U64Scalar(0) | Value::I64Scalar(0)) => { @@ -1960,14 +1948,14 @@ impl Expr { ExtensionMacroKind::FunctionLike { .. } => cannot_handle(ExtensionMacro(desc)), } } - ExtensionMacroCall(call) => (call.compiler.compiler)(cenv), + ExtensionMacroCall(call) => (call.compiler.compiler)(cenv.as_dyn()), expr @ FuncCall(..) => cannot_handle(expr), }?; // Compile-time evaluation, if that succeeds we simply replace the evaluator // by a closure that clones the precomputed value. - match eval.eval(cenv) { + match eval.eval(cenv.as_dyn()) { Ok(value) => match value.into_static() { Err(_) => Ok(eval), Ok(value) => Ok(new_dyn_evaluator(move |_| Ok(value.clone()))), @@ -2028,6 +2016,14 @@ mod tests { id => Err(CompileError::UnknownField(id.into())), } } + + #[inline] + fn variable_typ(&self, id: &str) -> Result { + match id { + "forty_two" => Ok(Type::Pointer(Box::new(Type::Void))), + _ => Err(CompileError::UnknownVariable(id.to_owned())), + } + } } impl<'ce> CompileEnv<'ce> for TestEnv { @@ -2079,14 +2075,14 @@ mod tests { id => Err(CompileError::UnknownField(id.into())), } } - } - impl<'ee> EvalEnv<'ee> for TestEnv { - // #[inline] - // fn field_getter(&self, id: &str) -> Result Result>, CompileError> { - // Ok(Box::new(|_| Ok(Value::U64Scalar(42)))) - // } + #[inline] + fn as_dyn(&self) -> &dyn CompileEnv<'ce> { + self + } + } + impl EvalEnv<'_> for TestEnv { fn header(&self) -> Result<&Header, EvalError> { Err(EvalError::NoHeader) } @@ -2103,6 +2099,13 @@ mod tests { } } + fn variable_value(&self, id: &str) -> Result, EvalError> { + match id { + "forty_two" => Ok(Value::U64Scalar(42)), + _ => Err(EvalError::UnknownVariable(id.to_owned())), + } + } + fn event_data(&self) -> Result<&[u8], EvalError> { Err(EvalError::NoEventData) } @@ -2171,6 +2174,10 @@ mod tests { test(b"true", signed(1)); test(b"false", signed(0)); + // Global variables + test(b"forty_two", unsigned(42)); + test(b"forty_two + 1", unsigned(43)); + // Basic arithmetic test(b"(-1)", signed(-1)); test(b"1+2", signed(3)); @@ -2341,6 +2348,7 @@ mod tests { test(b"((__u16)(__le16)1)", unsigned(1)); // Sizeof type + test(b"sizeof(void)", unsigned(1)); test(b"sizeof(char)", unsigned(1)); test(b"sizeof(int)", unsigned(4)); test(b"sizeof(unsigned long)", unsigned(8)); @@ -2537,6 +2545,14 @@ mod tests { test(b"(1 && 2) ? '*' : ' '", signed(42)); test(b"1 && 2 ? '*' : ' '", signed(42)); test(b"(int) 1 && (int) 2 ? '*' : ' '", signed(42)); + test(b"((unsigned int)((void *)42)) + 1", unsigned(43)); + test(b"((unsigned int)forty_two) + 1", unsigned(43)); + test(b"((unsigned int)forty_two + 1)", unsigned(43)); + test(b"(void *)((unsigned int)forty_two + 1)", unsigned(43)); + + // Check the ambiguity between cast syntax and variables + test(b"((unsigned int)(forty_two))", unsigned(42)); + test(b"((unsigned int)(forty_two) + 1)", unsigned(43)); // Extension macros test(b"__builtin_expect(42) + 1", signed(43)); diff --git a/tools/trace-parser/traceevent/src/compress.rs b/tools/trace-parser/traceevent/src/compress.rs index c8bf174e033d55681771ea5b89342f7ebf7e166d..b0d7c7315c24deb2d58ea711324e7fafa767ad63 100644 --- a/tools/trace-parser/traceevent/src/compress.rs +++ b/tools/trace-parser/traceevent/src/compress.rs @@ -110,10 +110,10 @@ impl Decompressor for ZstdDecompressor { if count == dst.len() { Ok(()) } else { - Err(io::Error::new( - io::ErrorKind::Other, - format!("Zstd expected {} bytes, decompressed {count}", dst.len()), - )) + Err(io::Error::other(format!( + "Zstd expected {} bytes, decompressed {count}", + dst.len() + ))) } } } @@ -173,14 +173,14 @@ impl Decompressor for ZlibDecompressor { .inner() .borrow_mut() .zlib_decompress(src, dst) - .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?; + .map_err(io::Error::other)?; if count == dst.len() { Ok(()) } else { - Err(io::Error::new( - io::ErrorKind::Other, - format!("Zlib expected {} bytes, decompressed {count}", dst.len()), - )) + Err(io::Error::other(format!( + "Zlib expected {} bytes, decompressed {count}", + dst.len() + ))) } } } diff --git a/tools/trace-parser/traceevent/src/cparser.rs b/tools/trace-parser/traceevent/src/cparser.rs index dd6e1c57a2f5264c80a91ff42fe0be3b4e4de673..6a339728d436bb8b45626d97fc70d2e7aa295806 100644 --- a/tools/trace-parser/traceevent/src/cparser.rs +++ b/tools/trace-parser/traceevent/src/cparser.rs @@ -28,28 +28,28 @@ use std::{rc::Rc, string::String as StdString, sync::Arc}; use bytemuck::cast_slice; use itertools::Itertools as _; use nom::{ + AsBytes, Finish as _, Parser, branch::alt, bytes::complete::{is_not, tag, take}, character::complete::{alpha1, alphanumeric1, char, u64 as dec_u64}, combinator::{all_consuming, cut, fail, map_res, not, opt, recognize, success}, - error::{context, FromExternalError}, - multi::{fold_many1, many0, many0_count, many1, many_m_n, separated_list0, separated_list1}, + error::{FromExternalError, context}, + multi::{fold_many1, many_m_n, many0, many0_count, many1, separated_list0, separated_list1}, number::complete::u8, sequence::{delimited, pair, preceded, separated_pair, terminated}, - AsBytes, Finish as _, Parser, }; use crate::{ cinterp::{ - new_dyn_evaluator, BasicEnv, Bitmap, CompileEnv, CompileError, EvalEnv, EvalError, - Evaluator, InterpError, Value, + BasicEnv, Bitmap, CompileEnv, CompileError, EvalEnv, EvalError, Evaluator, InterpError, + Value, new_dyn_evaluator, }, error::convert_err_impl, - grammar::{grammar, PackratGrammar as _}, + grammar::{PackratGrammar as _, grammar}, header::{Abi, Endianness, FileSize, Identifier, LongSize}, parser::{ - error, failure, hex_u64, lexeme, map_res_cut, parenthesized, success_with, FromParseError, - VerboseParseError, + FromParseError, VerboseParseError, error, failure, hex_u64, lexeme, map_res_cut, + parenthesized, success_with, }, scratch::{OwnedScratchBox, ScratchVec}, str::{Str, String}, @@ -154,6 +154,9 @@ pub trait ParseEnv: Send + Sync { /// fixed size ones (such as `u8`) to avoid having to manipulate multiple type systems /// downstream. It will also use the abi to know if a `char` is signed or not. fn abi(&self) -> &Abi; + + /// Get the type of the variable named `var`. + fn variable_typ(&self, id: &str) -> Result; } /// C declarator. @@ -476,12 +479,10 @@ pub enum CParseError { DataLocArrayWithoutIdentifier(Type), #[error("Found no identifier in the scalar __data_loc declaration")] DataLocWithoutIdentifier, - #[error( - "Found ambiguous identifiers in the scalar __data_loc declaration: \"{0}\" or \"{1}\"" - )] + #[error("Found ambiguous identifiers in the scalar __data_loc declaration: \"{0}\" or \"{1}\"")] DataLocAmbiguousIdentifier(Identifier, Identifier), - #[error("Invalid type name (incompatible int/long/short/char usage)")] + #[error("Invalid type name")] InvalidTypeName, #[error( @@ -492,7 +493,9 @@ pub enum CParseError { #[error("Character value is out of range ({0}), only 8 bit values are supported")] CharOutOfRange(u64), - #[error("Invalid variable identifier \"{0}\". Only the REC identifier is recognized as a variable, every other identifier is assumed to be an enumeration constant")] + #[error( + "Invalid variable identifier \"{0}\". Only the REC identifier is recognized as a variable, every other identifier is assumed to be an enumeration constant" + )] InvalidVariableIdentifier(Identifier), #[error("Could not guess the type of the expression: {0:?}")] @@ -561,8 +564,8 @@ fn print_array_hex(separator: &'static str) -> Result| { - let cval = val.clone().compile(&cenv)?; - let carray_size = array_size.clone().compile(&cenv)?; + let cval = val.clone().compile(cenv)?; + let carray_size = array_size.clone().compile(cenv)?; let eval = new_dyn_evaluator(move |env: &_| { let array_size = match carray_size.eval(env)? { @@ -706,14 +709,14 @@ fn print_symbolic() -> Result, InterpError>>()?; let compiler = Arc::new(move |cenv: &dyn CompileEnv<'_>| { - let cval = val.clone().compile(&cenv)?; + let cval = val.clone().compile(cenv)?; #[allow(clippy::type_complexity)] let cdelim: Box< dyn Fn(&dyn EvalEnv) -> Result + Send + Sync, > = if EXACT_MATCH { Box::new(|_env| Ok("".into())) } else { - let cdelim = delim.clone().compile(&cenv)?; + let cdelim = delim.clone().compile(cenv)?; Box::new(move |env| { let cdelim = cdelim.eval(env)?; let cdelim = cdelim.deref_ptr(env)?; @@ -746,7 +749,7 @@ fn print_symbolic() -> Result Result Result Result Result Result Resultfield", since the compiler // of REC->field will take care of getting the value and present // it as an array already. - Expr::record_field(field.clone()).compile(&cenv) + Expr::record_field(field.clone()).compile(cenv) }), }) }) @@ -996,7 +999,7 @@ fn resolve_extension_macro(name: &str) -> Result Ok(arr.len()), @@ -1038,8 +1041,7 @@ fn resolve_extension_macro(name: &str) -> Result Result| { - let cval = val.clone().compile(&cenv)?; - let carray_size = array_size.clone().compile(&cenv)?; - let citem_size = item_size.clone().compile(&cenv)?; + let cval = val.clone().compile(cenv)?; + let carray_size = array_size.clone().compile(cenv)?; + let citem_size = item_size.clone().compile(cenv)?; let eval = new_dyn_evaluator(move |env: &_| { let item_size: usize = match citem_size.eval(env)? { @@ -1239,7 +1241,9 @@ fn resolve_extension_macro(name: &str) -> Result Result| { let endianness = cenv.abi().endianness; - let cprefix_str = prefix_str.clone().compile(&cenv)?; - let cprefix_type = prefix_type.clone().compile(&cenv)?; - let crow_size = row_size.clone().compile(&cenv)?; + let cprefix_str = prefix_str.clone().compile(cenv)?; + let cprefix_type = prefix_type.clone().compile(cenv)?; + let crow_size = row_size.clone().compile(cenv)?; // Group size is ignored, as using any group size // different than the underlying buffer type is // undefined behavior. Therefore we can simply look at // the kind of array we get at runtime and format it // normally. - let cbuf = buf.clone().compile(&cenv)?; - let clength = length.clone().compile(&cenv)?; - let cascii = ascii.clone().compile(&cenv)?; + let cbuf = buf.clone().compile(cenv)?; + let clength = length.clone().compile(cenv)?; + let cascii = ascii.clone().compile(cenv)?; let eval = new_dyn_evaluator(move |env: &_| { macro_rules! eval_int { @@ -1703,7 +1707,7 @@ where return error( input, CParseError::DecodeUtf8(err.to_string()), - ) + ); } Ok(s) => s, }; @@ -2079,45 +2083,55 @@ grammar! { ), context( "scalar", - Self::identifier().map(|id| { - match id.as_ref() { - "void" => Type::Void, - "_Bool" => Type::Bool, - _ => { + |input| { + let penv = Self::get_ctx(&input).penv; + let (input, id) = Self::identifier().parse(input)?; + + match penv.variable_typ(&id) { + // If we recognize that identifier as a variable, then it is + // not a type name. + Ok(_) => error(input, CParseError::InvalidTypeName), + Err(_) => { let typ = match id.as_ref() { - "caddr_t" => Type::Pointer(Box::new(char_typ.clone())), - "bool" => Type::Bool, + "void" => Type::Void, + "_Bool" => Type::Bool, + _ => { + let typ = match id.as_ref() { + "caddr_t" => Type::Pointer(Box::new(char_typ.clone())), + "bool" => Type::Bool, - "s8" | "__s8" | "int8_t" => Type::I8, - "u8" | "__u8" | "uint8_t" | "u_char" | "unchar" | "u_int8_t" => Type::U8, + "s8" | "__s8" | "int8_t" => Type::I8, + "u8" | "__u8" | "uint8_t" | "u_char" | "unchar" | "u_int8_t" => Type::U8, - "s16" | "__s16" | "int16_t" => Type::I16, - "u16" | "__u16" | "uint16_t" | "u_short" | "ushort" | "u_int16_t" | "__le16" | "__be16" | "__sum16" => Type::U16, + "s16" | "__s16" | "int16_t" => Type::I16, + "u16" | "__u16" | "uint16_t" | "u_short" | "ushort" | "u_int16_t" | "__le16" | "__be16" | "__sum16" => Type::U16, - "s32" | "__s32" | "int32_t" => Type::I32, - "u32" | "__u32" | "uint32_t" | "u_int" | "uint" | "u_int32_t" | "gfp_t" | "slab_flags_t" | "fmode_t" | "OM_uint32" | "dev_t" | "nlink_t" | "__le32" | "__be32" | "__wsum" | "__poll_t" => Type::U32, + "s32" | "__s32" | "int32_t" => Type::I32, + "u32" | "__u32" | "uint32_t" | "u_int" | "uint" | "u_int32_t" | "gfp_t" | "slab_flags_t" | "fmode_t" | "OM_uint32" | "dev_t" | "nlink_t" | "__le32" | "__be32" | "__wsum" | "__poll_t" => Type::U32, - "s64" | "__s64" | "int64_t" | "loff_t" => Type::I64, - "u64" | "__u64" | "uint64_t" | "u_int64_t" | "sector_t" | "blkcnt_t" | "__le64" | "__be64" => Type::U64, + "s64" | "__s64" | "int64_t" | "loff_t" => Type::I64, + "u64" | "__u64" | "uint64_t" | "u_int64_t" | "sector_t" | "blkcnt_t" | "__le64" | "__be64" => Type::U64, - "pid_t" => Type::I32, + "pid_t" => Type::I32, - "u_long" | "ulong" | "off_t" | "ssize_t" | "ptrdiff_t" | "clock_t" | "irq_hw_number_t" => match long_size { - LongSize::Bits32 => Type::I32, - LongSize::Bits64 => Type::I64, - }, + "u_long" | "ulong" | "off_t" | "ssize_t" | "ptrdiff_t" | "clock_t" | "irq_hw_number_t" => match long_size { + LongSize::Bits32 => Type::I32, + LongSize::Bits64 => Type::I64, + }, - "uintptr_t" | "size_t" => match long_size { - LongSize::Bits32 => Type::U32, - LongSize::Bits64 => Type::U64, - }, + "uintptr_t" | "size_t" => match long_size { + LongSize::Bits32 => Type::U32, + LongSize::Bits64 => Type::U64, + }, - _ => Type::Unknown, + _ => Type::Unknown, + }; + Type::Typedef(Box::new(typ), id) + } }; - Type::Typedef(Box::new(typ), id) + Ok((input, typ)) } - } - }), + } } ), ))) .parse(input), @@ -3156,7 +3170,12 @@ grammar! { rule enum_constant() -> Expr { lexeme(context("enum constant", - Self::identifier().map(|id| Expr::EnumConstant(Type::I32, id)) + map_res( + Self::identifier(), + // We currently do not support any enum constant, so it's never the right + // parse. Instead, we parse lexeme as type names or variable names. + |id| Err(CParseError::InvalidVariableIdentifier(id)), + ) )) } @@ -3179,9 +3198,10 @@ grammar! { Self::expr() ), Self::string_literal(), - map_res( - Self::identifier(), - |id| match id.deref() { + |input| { + let penv = Self::get_ctx(&input).penv; + let (input, id) = Self::identifier().parse(input)?; + let expr = match id.deref() { "REC" => { // Make a REC variable and then take its // address, rather than making a pointer-typed @@ -3190,21 +3210,25 @@ grammar! { // that will get turned into "(*&REC).x" and // then "REC.x". Doing it this way plays nicely // with constant folding. - let typ = Type::Variable(id.clone()); - Ok(Expr::Addr(Box::new(Expr::Variable(typ, id)))) + let typ = Type::Variable("REC".into()); + Expr::Addr(Box::new(Expr::Variable(typ, "REC".into()))) }, - _ => { - let kind = resolve_extension_macro(&id)?; - - Ok(Expr::ExtensionMacro(Arc::new( + _ => match resolve_extension_macro(&id) { + Ok(kind) => Expr::ExtensionMacro(Arc::new( ExtensionMacroDesc { name: id, kind, } - ))) - }, - } - ), + )), + Err(_) => Expr::Variable( + penv.variable_typ(&id).unwrap_or(Type::Unknown), + id + ) + } + }; + + Ok((input, expr)) + }, Self::constant(), )) ) @@ -3509,14 +3533,14 @@ mod tests { test( b"f(1)", FuncCall( - Box::new(EnumConstant(Type::I32, "f".into())), + Box::new(Variable(Type::Unknown, "f".into())), vec![IntConstant(Type::I32, 1)], ), ); test( b" f (1, 2, 3) ", FuncCall( - Box::new(EnumConstant(Type::I32, "f".into())), + Box::new(Variable(Type::Unknown, "f".into())), vec![ IntConstant(Type::I32, 1), IntConstant(Type::I32, 2), @@ -3774,7 +3798,8 @@ mod tests { // This is genuinely ambiguous: it can be either a cast to type "type" // of "+2" or the addition of a "type" variable and 2. // We parse it as a cast as the expressions we are interested in only - // contain one variable (REC). + // contain one variable (REC), unless "type" was recognized as a variable by + // ParseEnv::variable_typ(), in which case it would be parsed as a variable. test( b" (type) + (2) ", Cast( @@ -4060,7 +4085,7 @@ mod tests { Box::new(u64_typ.clone()), ArrayKind::Fixed(Err(Box::new(InterpError::CompileError(Box::new( CompileError::ExprNotHandled(Expr::EnumConstant( - Type::I32, + Type::Unknown, "static_bar".into(), )), ))))), diff --git a/tools/trace-parser/traceevent/src/grammar.rs b/tools/trace-parser/traceevent/src/grammar.rs index a595532c61e5078956db0d26fbc640b70fc95c5b..f94e9cbc2d932d195398bb7896474cefee44250f 100644 --- a/tools/trace-parser/traceevent/src/grammar.rs +++ b/tools/trace-parser/traceevent/src/grammar.rs @@ -64,8 +64,8 @@ pub trait PackratGrammar { /// context. #[allow(clippy::type_complexity)] #[inline] - fn grammar_ctx<'i, E>( - ) -> fn(Span<'i, Self>) -> nom::IResult, &'i Self::Ctx<'i>, E> { + fn grammar_ctx<'i, E>() + -> fn(Span<'i, Self>) -> nom::IResult, &'i Self::Ctx<'i>, E> { move |input: Span<'i, Self>| { let ctx = Self::get_ctx(&input); Ok((input, ctx)) diff --git a/tools/trace-parser/traceevent/src/header.rs b/tools/trace-parser/traceevent/src/header.rs index 46b245b57a513af07a937449b2511e7639352704..11ff28c287ae17b73274c5986a1548e04782a957 100644 --- a/tools/trace-parser/traceevent/src/header.rs +++ b/tools/trace-parser/traceevent/src/header.rs @@ -37,8 +37,9 @@ use std::{ sync::{Arc, RwLock}, }; -use itertools::izip; +use itertools::{Itertools as _, izip}; use nom::{ + Finish as _, Parser, branch::alt, bytes::complete::{is_a, is_not, tag}, character::complete::{ @@ -48,7 +49,6 @@ use nom::{ error::context, multi::{fold_many0, many0, separated_list0}, sequence::{delimited, pair, preceded, separated_pair, terminated}, - Finish as _, Parser, }; use once_cell::sync::OnceCell; @@ -56,21 +56,21 @@ use crate::{ array::Array, buffer::{Buffer, BufferError, FieldDecoder}, cinterp::{ - new_dyn_evaluator, BasicEnv, CompileEnv, CompileError, EvalEnv, EvalError, Evaluator, Value, + BasicEnv, CompileEnv, CompileError, EvalEnv, EvalError, Evaluator, Value, new_dyn_evaluator, }, closure::closure, compress::{Decompressor, DynDecompressor, ZlibDecompressor, ZstdDecompressor}, cparser::{ - identifier, is_identifier, string_literal, ArrayKind, CGrammar, CGrammarCtx, Declaration, - Expr, ExtensionMacroCall, ExtensionMacroCallCompiler, ExtensionMacroDesc, ParseEnv, Type, + ArrayKind, CGrammar, CGrammarCtx, Declaration, Expr, ExtensionMacroCall, + ExtensionMacroCallCompiler, ExtensionMacroDesc, ParseEnv, Type, identifier, string_literal, }, error::convert_err_impl, grammar::PackratGrammar as _, io::{BorrowingCursor, BorrowingRead}, nested_pointer::NestedPointer, parser::{ - error, failure, hex_u64, lexeme, map_res_cut, to_str, FromParseError, NomError, - NomParserExt as _, VerboseParseError, + FromParseError, NomError, NomParserExt as _, VerboseParseError, error, failure, hex_u64, + lexeme, map_res_cut, to_str, }, print::{PrintAtom, PrintFmtError, PrintFmtStr, PrintSpecifier, StringWriter}, scratch::{ScratchAlloc, ScratchVec}, @@ -307,6 +307,10 @@ impl ParseEnv for Abi { fn field_typ(&self, id: &str) -> Result { Err(CompileError::UnknownField(id.into())) } + + fn variable_typ(&self, id: &str) -> Result { + Err(CompileError::UnknownVariable(id.to_owned())) + } } /// ID of a buffer in a trace.dat file. @@ -336,7 +340,7 @@ pub(crate) struct HeaderV6 { pub(crate) kernel_abi: Abi, pub(crate) page_size: FileSize, pub(crate) event_descs: Vec, - pub(crate) kallsyms: BTreeMap, + pub(crate) kallsyms: BTreeMap>, pub(crate) str_table: BTreeMap, pub(crate) pid_comms: BTreeMap, pub(crate) options: Vec, @@ -351,7 +355,7 @@ pub(crate) struct HeaderV7 { pub(crate) kernel_abi: Abi, pub(crate) page_size: FileSize, pub(crate) event_descs: Vec, - pub(crate) kallsyms: BTreeMap, + pub(crate) kallsyms: BTreeMap>, pub(crate) str_table: BTreeMap, pub(crate) pid_comms: BTreeMap, pub(crate) options: Vec, @@ -407,24 +411,28 @@ impl Header { } } + /// Provide the value of a global variable that some events rely on. + pub fn constant_value(&self, id: &str) -> Result, EvalError> { + match self.sym_addr(id) { + None => Err(EvalError::UnknownVariable(id.to_owned())), + Some(addr) => Ok(Value::U64Scalar(addr)), + } + } + /// Returns an iterator of [EventDesc] for all the ftrace events defined in the header. #[inline] - pub fn event_descs(&self) -> impl IntoIterator { - attr!(self, event_descs) + pub fn event_descs(&self) -> impl Iterator { + attr!(self, event_descs).iter() } #[inline] pub fn event_desc_by_id(&self, id: EventId) -> Option<&EventDesc> { - self.event_descs() - .into_iter() - .find(move |desc| desc.id == id) + self.event_descs().find(move |desc| desc.id == id) } #[inline] pub fn event_desc_by_name(&self, name: &str) -> Option<&EventDesc> { - self.event_descs() - .into_iter() - .find(move |desc| desc.name == name) + self.event_descs().find(move |desc| desc.name == name) } /// ABI of the kernel that generated the ftrace this header is representing. @@ -454,14 +462,26 @@ impl Header { .map(|(addr, _)| addr); map.range((Unbounded, Included(addr))) .last() - .map(|(base, s)| { - let size = next_addr.map(|next| next - addr); + .map(|(base, syms)| { + let size = next_addr.map(|next| next - base); let offset = addr - base; - (offset, size, s.deref()) + let sym = syms.last().expect("No symbol name"); + (offset, size, sym.deref()) }) } } + pub fn sym_addr(&self, sym: &str) -> Option { + let map = attr!(self, kallsyms); + map.iter().find_map(|(addr, syms)| { + if syms.iter().any(|_sym| _sym == sym) { + Some(*addr) + } else { + None + } + }) + } + /// Number of CPUs with a buffer in that trace. #[inline] pub fn nr_cpus(&self) -> Cpu { @@ -470,8 +490,8 @@ impl Header { /// Header options encoded in the header. #[inline] - pub fn options(&self) -> impl IntoIterator { - attr!(self, options) + pub fn options(&self) -> impl Iterator { + attr!(self, options).iter() } /// Parsed content of `/proc/kallsyms` encoded in the header. @@ -479,18 +499,20 @@ impl Header { /// Note: The addresses may not be the real addresses for security reasons depending on the /// kernel configuration. #[inline] - pub fn kallsyms(&self) -> impl IntoIterator { - attr!(self, kallsyms).iter().map(|(k, v)| (*k, v.deref())) + pub fn kallsyms(&self) -> impl Iterator)> { + attr!(self, kallsyms) + .iter() + .map(|(k, v)| (*k, v.iter().map(|sym| &**sym))) } /// Content of the PID/task name table as an iterator. #[inline] - pub fn pid_comms(&self) -> impl IntoIterator { + pub fn pid_comms(&self) -> impl Iterator { attr!(self, pid_comms).iter().map(|(k, v)| (*k, v.deref())) } /// Returns a timestamp fixup closure based on he header options that can affect it. - pub(crate) fn timestamp_fixer(&self) -> impl Fn(Timestamp) -> Timestamp { + pub(crate) fn timestamp_fixer(&self) -> impl Fn(Timestamp) -> Timestamp + use<> { let mut offset_signed: i64 = 0; let mut offset_unsigned: u64 = 0; let mut _multiplier: u32 = 1; @@ -954,10 +976,9 @@ impl EventFmt { /// Evaluators for the arguments to interpolate in the printk-style format of the event. pub fn print_args( &self, - ) -> Result, CompileError>>, HeaderError> - { + ) -> Result, CompileError>>, HeaderError> { match &self.print_fmt_args { - Ok(x) => Ok(&x.1), + Ok(x) => Ok(x.1.iter()), Err(err) => Err(err.clone()), } } @@ -1058,6 +1079,11 @@ impl<'h> EvalEnv<'h> for HeaderEnv<'h> { fn event_data(&self) -> Result<&[u8], EvalError> { Err(EvalError::NoEventData) } + + #[inline] + fn variable_value(&self, id: &str) -> Result, EvalError> { + self.header.constant_value(id) + } } impl<'h> HeaderEnv<'h> { @@ -1080,6 +1106,15 @@ impl ParseEnv for HeaderEnv<'_> { } Err(CompileError::UnknownField(id.into())) } + + #[inline] + fn variable_typ(&self, id: &str) -> Result { + match self.header.sym_addr(id) { + None => Err(CompileError::UnknownVariable(id.to_owned())), + Some(_) => Ok(Type::Pointer(Box::new(Type::Void))), + } + } + #[inline] fn abi(&self) -> &Abi { self.header.kernel_abi() @@ -1118,6 +1153,11 @@ impl<'ce> CompileEnv<'ce> for HeaderEnv<'ce> { } Err(CompileError::UnknownField(id.into())) } + + #[inline] + fn as_dyn(&self) -> &dyn CompileEnv<'ce> { + self + } } /// Parse event format as found in `/sys/kernel/tracing/events/*/*/format` @@ -1349,7 +1389,6 @@ fn parse_event_fmt<'a>( print_args.into_iter(), print_fmt.atoms.iter() ) - .into_iter() .map(fixup_arg) .map(|expr| Ok( Arc::from(expr.compile(&cenv)?)) @@ -1421,7 +1460,7 @@ fn parse_event_desc(input: &[u8]) -> nom::IResult<&[u8], EventDesc, HeaderNomErr #[inline(never)] fn parse_kallsyms( input: &[u8], -) -> nom::IResult<&[u8], BTreeMap, HeaderNomError<'_>> { +) -> nom::IResult<&[u8], BTreeMap>, HeaderNomError<'_>> { context("kallsyms", move |input| { let line = terminated( separated_pair( @@ -1438,20 +1477,20 @@ fn parse_kallsyms( |(name, module)| match from_utf8(name) { // Filter-out symbols starting with "$" as they are probably just mapping // symbols that can sometimes have the same value as real function symbols, - // thereby breaking the output. (see "ELF for the Arm© 64-bit Architecture + // thereby breaking the output. (see "ELF for the Arm© 64-bit Architecture // (AArch64)" document). // Also filter out all the compiler-generated symbols, e.g. ones that have // a suffix as a result of some optimization pass. - Ok(name) if is_identifier(name) => Ok(Some(match module.map(from_utf8) { + Ok(name) if name.contains('$') => Ok(None), + Ok(name) => Ok(Some(match module.map(from_utf8) { Some(Ok(module)) => { let mut full: SymbolName = name.into(); - full.push_str(" "); + full.push(' '); full.push_str(module); full } _ => name.into(), })), - Ok(_) => Ok(None), Err(err) => Err(HeaderError::DecodeUtf8(err.to_string())), }, ), @@ -1463,10 +1502,14 @@ fn parse_kallsyms( let parsed = it .by_ref() .filter_map(|item| match item { - (addr, Some(name)) => Some(Ok((addr, name))), + (addr, Some(name)) => Some((addr, name)), _ => None, }) - .collect::, _>>()?; + .sorted() + .chunk_by(|(addr, _)| *addr) + .into_iter() + .map(|(addr, names)| (addr, names.map(|(_, name)| name).collect())) + .collect::>(); let (input, _) = it.finish()?; Ok((input, parsed)) }) @@ -1562,7 +1605,9 @@ pub enum HeaderError { size: u64, }, - #[error("Sign of type \"{typ:?}\" was inferred to be {inferred_signedness:?} but kernel reported {signedness}")] + #[error( + "Sign of type \"{typ:?}\" was inferred to be {inferred_signedness:?} but kernel reported {signedness}" + )] InvalidTypeSign { typ: Type, inferred_signedness: Signedness, @@ -2400,7 +2445,7 @@ where fn parse_kallsyms_section( abi: &Abi, input: &mut I, -) -> Result, HeaderError> +) -> Result>, HeaderError> where I: BorrowingRead, { diff --git a/tools/trace-parser/traceevent/src/io.rs b/tools/trace-parser/traceevent/src/io.rs index e20d1210fa8e813c3a699182f07c3a6a04a558d4..83bd10002436d646ad70044441897d2575852bbd 100644 --- a/tools/trace-parser/traceevent/src/io.rs +++ b/tools/trace-parser/traceevent/src/io.rs @@ -467,16 +467,18 @@ impl MmapFileInner { where T: AsRawFd, { - // Try to map all the remainder of the file range of interest. - let len = if offset > self.offset { - self.len - (offset - self.offset) - } else { - self.len + (self.offset - offset) - }; + unsafe { + // Try to map all the remainder of the file range of interest. + let len = if offset > self.offset { + self.len - (offset - self.offset) + } else { + self.len + (self.offset - offset) + }; - // Saturate at the max size possible for a mmap - let len: MemSize = len.try_into().unwrap_or(MemSize::MAX); - Mmap::new(self.file.lock().unwrap().deref(), offset, len) + // Saturate at the max size possible for a mmap + let len: MemSize = len.try_into().unwrap_or(MemSize::MAX); + Mmap::new(self.file.lock().unwrap().deref(), offset, len) + } } } @@ -497,10 +499,12 @@ impl MmapFile { where T: AsRawFd + Seek, { - let offset = 0; - let len = file_len(&mut file)?; - let file = Arc::new(Mutex::new(file)); - Self::from_cell(file, offset, None, len) + unsafe { + let offset = 0; + let len = file_len(&mut file)?; + let file = Arc::new(Mutex::new(file)); + Self::from_cell(file, offset, None, len) + } } unsafe fn from_cell( @@ -512,27 +516,29 @@ impl MmapFile { where T: AsRawFd, { - let len = len.unwrap_or(file_len - offset); + unsafe { + let len = len.unwrap_or(file_len - offset); - // Check that we are not trying to mmap past the end of the - // file, as mmap() will let us do it but we will get SIGBUS upon - // access. - if offset + len > file_len { - Err(ErrorKind::UnexpectedEof.into()) - } else { - let mmap_len = len.try_into().unwrap_or(MemSize::MAX); - let mmap = Mmap::new(file.lock().unwrap().deref(), offset, mmap_len)?; - - Ok(MmapFile { - inner: MmapFileInner { - file, - len, - file_len, - mmap, - offset, - }, - scratch: ScratchAlloc::new(), - }) + // Check that we are not trying to mmap past the end of the + // file, as mmap() will let us do it but we will get SIGBUS upon + // access. + if offset + len > file_len { + Err(ErrorKind::UnexpectedEof.into()) + } else { + let mmap_len = len.try_into().unwrap_or(MemSize::MAX); + let mmap = Mmap::new(file.lock().unwrap().deref(), offset, mmap_len)?; + + Ok(MmapFile { + inner: MmapFileInner { + file, + len, + file_len, + mmap, + offset, + }, + scratch: ScratchAlloc::new(), + }) + } } } @@ -1008,4 +1014,6 @@ macro_rules! impl_DecodeBinary { } } -impl_DecodeBinary!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); +impl_DecodeBinary!( + u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize +); diff --git a/tools/trace-parser/traceevent/src/lib.rs b/tools/trace-parser/traceevent/src/lib.rs index 43a42849ccf25fcfe8ef3982b48f58aab637dc7e..44a49fc07e5d321800f38eca6ab0efa4139d94ae 100644 --- a/tools/trace-parser/traceevent/src/lib.rs +++ b/tools/trace-parser/traceevent/src/lib.rs @@ -13,6 +13,7 @@ // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#![feature(trait_upcasting)] //! This crate implements a parser for //! [trace.dat](https://www.trace-cmd.org/Documentation/trace-cmd/trace-cmd.dat.v7.5.html) file diff --git a/tools/trace-parser/traceevent/src/parser.rs b/tools/trace-parser/traceevent/src/parser.rs index 2401466b6141590a2b5b31b553a016e20e7f60aa..89bfaefa466cb4fbbdfe92f7603ef476f9a98413 100644 --- a/tools/trace-parser/traceevent/src/parser.rs +++ b/tools/trace-parser/traceevent/src/parser.rs @@ -23,12 +23,12 @@ use core::{ use std::string::String as StdString; use nom::{ + Finish as _, Parser, bytes::complete::is_a, character::complete::{char, multispace0}, combinator::all_consuming, error::{ContextError, ErrorKind, FromExternalError, ParseError}, sequence::delimited, - Finish as _, Parser, }; pub trait FromParseError: Sized { @@ -374,14 +374,14 @@ where /// This allows correct error handling for all cases where the grammar is non-ambiguous and `f` is /// doing semantic checking. In such situation, a semantic error is not expected to trigger a /// backtrack in the parser, leading to much worse error messages. -pub fn map_res_cut, E2, F, G>( +pub fn map_res_cut( mut parser: F, mut f: G, ) -> impl nom::Parser where F: Parser, G: FnMut(O1) -> Result, - E: ParseError, + E: ParseError + FromExternalError, { move |input: I| { let i = input.clone(); @@ -473,7 +473,7 @@ where #[cfg(test)] pub(crate) mod tests { use nom::Finish as _; - use nom_language::error::{convert_error, VerboseError}; + use nom_language::error::{VerboseError, convert_error}; use super::*; diff --git a/tools/trace-parser/traceevent/src/print.rs b/tools/trace-parser/traceevent/src/print.rs index c64593832a7a7fe2107bdd2bc3d41c6a392f9414..1a615739eac709b2b0cd7b74a1f3ae0323a52170 100644 --- a/tools/trace-parser/traceevent/src/print.rs +++ b/tools/trace-parser/traceevent/src/print.rs @@ -20,21 +20,21 @@ use core::{ cmp::Ordering, fmt, fmt::{Debug, Write as _}, - str::{from_utf8, Utf8Error}, + str::{Utf8Error, from_utf8}, }; use std::{error::Error, io, string::String as StdString}; use bitflags::bitflags; use itertools::Itertools as _; use nom::{ + Parser, branch::alt, bytes::complete::{is_not, tag}, character::complete::{char, u64 as txt_u64}, combinator::{cut, opt, success}, - error::{context, ContextError, FromExternalError, ParseError}, + error::{ContextError, FromExternalError, ParseError, context}, multi::{many0, many1}, sequence::{preceded, separated_pair}, - Parser, }; use once_cell::sync::OnceCell; @@ -44,7 +44,7 @@ use crate::{ cparser::{CParseError, Expr}, error::convert_err_impl, header::{Abi, Endianness, Header, LongSize, Signedness}, - parser::{map_res_cut, FromParseError, NomParserExt as _, VerboseParseError}, + parser::{FromParseError, NomParserExt as _, VerboseParseError, map_res_cut}, str::{InnerStr, Str, String}, }; @@ -664,11 +664,11 @@ impl PrintFmtStr { PrintSpecifier::SymbolWithOffset => Ok(print_symbol(out, val, true)?), PrintSpecifier::HexBuffer(sep) => { let val = val.deref_ptr(env)?; - let res = match val.to_bytes() { + + match val.to_bytes() { Some(arr) => print_hex_buffer!(out, arr, *sep), _ => Err(PrintError::NotABuffer(val.clone().into_static().ok()))?, - }; - res + } } PrintSpecifier::IpGeneric(endianness) => { @@ -886,7 +886,7 @@ impl PrintAtom { >( mut args: I1, mut atoms: I2, - ) -> impl IntoIterator)> { + ) -> impl Iterator)> { let mut count = 0; core::iter::from_fn(move || { let arg = args.next()?; @@ -898,9 +898,7 @@ impl PrintAtom { match atoms.next() { Some(PrintAtom::Fixed(_)) => continue, curr @ Some(PrintAtom::Variable { - ref width, - ref precision, - .. + width, precision, .. }) => { count = 0; count += match width { @@ -1039,15 +1037,6 @@ where char('x').map(|_| Ok((VBinSpecifier::U32, PrintSpecifier::Hex))), char('X').map(|_| Ok((VBinSpecifier::U32, PrintSpecifier::UpperHex))), )), - alt(( - tag("ld"), - tag("li"), - tag("Ld"), - tag("Li"), - tag("z"), - tag("zd"), - )) - .map(|_| Ok((vbin_long.clone(), PrintSpecifier::Dec))), alt(( alt((tag("lu"), tag("Lu"), tag("zu"))) .map(|_| Ok((vbin_ulong.clone(), PrintSpecifier::Dec))), @@ -1058,6 +1047,17 @@ where alt((tag("lo"), tag("Lo"), tag("zo"))) .map(|_| Ok((vbin_ulong.clone(), PrintSpecifier::Oct))), )), + alt(( + tag("ld"), + tag("li"), + tag("Ld"), + tag("Li"), + tag("zd"), + // This must be tried after all the other %z, otherwise it will match + // greedily and we will not parse the following e.g. "u" or "x". + tag("z"), + )) + .map(|_| Ok((vbin_long.clone(), PrintSpecifier::Dec))), alt(( alt((tag("lld"), tag("lli"))) .map(|_| Ok((VBinSpecifier::I64, PrintSpecifier::Dec))), diff --git a/tools/trace-parser/traceevent/src/scratch.rs b/tools/trace-parser/traceevent/src/scratch.rs index 28119def0b890961a5a4a40a4cdf7cb52d67a5b1..6fea584cc02e1b5d81486f9360f4c8b968914a45 100644 --- a/tools/trace-parser/traceevent/src/scratch.rs +++ b/tools/trace-parser/traceevent/src/scratch.rs @@ -26,7 +26,7 @@ use core::{ }; use std::{io, sync::Arc}; -use bumpalo::{boxed::Box as BumpaloBox, collections::Vec as BumpaloVec, Bump}; +use bumpalo::{Bump, boxed::Box as BumpaloBox, collections::Vec as BumpaloVec}; use thread_local::ThreadLocal; /// Allocator used for quick processing that will not need persistent memory allocation. @@ -298,7 +298,9 @@ macro_rules! nodrop_impl { )* }; } -nodrop_impl!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, f64, bool, str); +nodrop_impl!( + u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, f64, bool, str +); impl NoopDrop for [T] {} impl NoopDrop for [T; N] {} impl NoopDrop for &T {} diff --git a/tools/trace-parser/traceevent/src/str.rs b/tools/trace-parser/traceevent/src/str.rs index 3ea521e506e79b6de7307e80d6d5bdc0e7eb9eba..13551bd8e7950b0471c6caa26a7623560b6c5f4c 100644 --- a/tools/trace-parser/traceevent/src/str.rs +++ b/tools/trace-parser/traceevent/src/str.rs @@ -27,17 +27,16 @@ use core::{ }; use std::sync::Arc; +#[cfg(not(feature = "smartstring"))] +pub use String; +#[cfg(feature = "smartstring")] +pub use smartstring::alias::String; + use crate::{ memo::Memo, scratch::{OwnedScratchBox, OwnedScratchBox_as_dyn, ScratchAlloc}, }; -#[cfg(feature = "smartstring")] -pub use smartstring::alias::String; - -#[cfg(not(feature = "smartstring"))] -pub use String; - /// String type with various ownership model available. #[derive(Debug, Clone)] pub struct Str<'a> {