#syscalls #strace #trace

app pai-strace

A strace-like tool created using pai

9 releases

0.1.8 Mar 9, 2024
0.1.7 Mar 4, 2024
0.1.5 Feb 13, 2024
0.1.2 Jan 31, 2024

#197 in Operating systems

Download history 4/week @ 2024-09-20

441 downloads per month

Custom license

24KB
494 lines

pai-strace

A strace-like tool created using 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.

Development status

In development, expect some bugs.

Compile

cargo-make is used to control the build process. 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/<target>/<debug|release>/pai-strace

If you don't specify any target it will be under output/<debug|release>/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.

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.

{
 "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
   }
  }
 }
}

Dependencies

~16–31MB
~504K SLoC