# pai-strace A strace-like tool created using [pai](https://github.com/rstenvi/pai) ## Install ~~~ cargo install --force pai-strace ~~~ To check if a new version is available: ~~~ pai-strace --check-update ~~~ To use on target where `cargo` is not installed, please see [releases](https://github.com/rstenvi/pai-strace/releases). ## Development status In development, expect some bugs. ## Compile [cargo-make](https://github.com/sagiegurari/cargo-make) is used to control the build process. [cross](https://github.com/cross-rs/cross) is used to support cross-compilation. To simplify the build process, `cross` is used even when compiling for host target. The command to build targets are: ~~~ cargo make [build|release] [target(s)] ~~~ The output will be placed in `output///pai-strace` If you don't specify any target it will be under `output//pai-strace` **Some other useful make targets** - `cargo make clippy` - Should be run before every commit - `cargo make publish` - Publish new version on crates.io - `cargo make release [target1 target2 targetN]` - Build release version for given targets - `cargo make releasecheck` - Run dependencies for `publish` and `release` targets without releasing or publishing anything. - Will not run with uncommited changes so not necessary to run this before commit - `cargo make update` - Update all dependencies in `Cargo.lock` - This is part of `releasecheck` ## How to use See `--help` for more commands, but below are some examples, each one simply spawns the `true` command. Most basic command is to just print all system calls to stdout. ~~~{.bash} pai-strace true ~~~ Below is an example which writes both raw format and json format to files, `calls.txt` and `calls.json`, respectively. ~~~ pai-strace --format json --format raw --output calls true ~~~ In the following previous example you might have seen, something like: ~~~ [594079]: openat(fd=0xffffff9c, file=0x7ff1d2a7121b, flags=0x80000, mode=0x0) = 0x3 ~~~ This doesn't give much information about how the file is opened. To provide some more contexts, we can provide the `--enrich` argument. ~~~ pai-strace --enrich basic true ~~~ Line now becomes. ~~~ [594137]: openat(fd=fd(AT_FDCWD), file=ptr(7f363802421b), flags=flags(O_CLOEXEC), mode=flags()) = fd(3) ~~~ Now we can see that the file descriptor is a constant and the names of the flags passed. We still don't know the filename however, to read pointers we can pass the `--enrich full` argument ~~~ pai-strace --enrich full true ~~~ Output now becomes: ~~~ [594176]: openat(fd=fd(AT_FDCWD), file="/etc/ld.so.cache", flags=flags(O_CLOEXEC), mode=flags()) = fd(3) ~~~ The only difference is that the filename has been resolved. The `raw` format does omit some information, the full info of the above command in `json` is included below. It includes the real values used to derive flags, strings, etc. and also includes direction of the argument. In this case, all arguments are input. ~~~{.json} { "tid": 594246, "sysno": 257, "name": "openat", "args": [ { "name": "fd", "value": { "raw_value": 4294967196, "parsed": { "FdConst": { "value": -100, "name": "AT_FDCWD" } } }, "dir": "In" }, { "name": "file", "value": { "raw_value": 139771623875099, "parsed": { "String": { "string": "/etc/ld.so.cache" } } }, "dir": "In" }, { "name": "flags", "value": { "raw_value": 524288, "parsed": { "Flag": { "set": [ "O_CLOEXEC" ] } } }, "dir": "In" }, { "name": "mode", "value": { "raw_value": 0, "parsed": { "Flag": { "set": [] } } }, "dir": "In" }], "output": { "raw_value": 3, "parsed": { "Fd": { "fd": 3 } } } } ~~~