#!/usr/bin/awk -f # # sydtrace.awk: # Feed the output of sydtrace.bt to this script. BEGIN { # Lookup command (override by setting CARGO_BIN_EXE_syd-sys in the environment) lookup_cmd = "syd-sys" if (ENVIRON["CARGO_BIN_EXE_syd-sys"] != "") lookup_cmd = ENVIRON["CARGO_BIN_EXE_syd-sys"] } { # Keep kstack/ustack and stack lines untouched. if ($0 ~ /^kstack:/ || $0 ~ /^ustack:/ || $0 ~ /^[ \t]*ยป/) { print next } # Extract sys=NUMBER and comm=TOKEN (if present) using RSTART/RLENGTH sysnum = "" commtok = "" if (match($0, /sys=[-]?[0-9]+/)) { # sys= starts at RSTART, length RLENGTH; value begins after "sys=" sysnum = substr($0, RSTART + 4, RLENGTH - 4) } if (match($0, /comm=[^ ]+/)) { # comm= starts at RSTART, length RLENGTH; value begins after "comm=" commtok = substr($0, RSTART + 5, RLENGTH - 5) } # If either missing, print unchanged. if (sysnum == "" || commtok == "") { print next } # If sys is negative, do not query and leave line as-is. if (substr(sysnum, 1, 1) == "-") { print next } # Defensive numeric check: require all digits if (sysnum !~ /^[0-9]+$/) { print next } # Lookup (cached). `seen` flags whether we've cached this sysnum. if (seen[sysnum]) { name = cache[sysnum] } else { name = "" cmd = lookup_cmd " " sysnum if ((cmd | getline out) == 1) { # parse first whitespace-separated token as the syscall name n = split(out, parts) if (n >= 1) name = parts[1] } close(cmd) cache[sysnum] = name seen[sysnum] = 1 } # If lookup failed (empty name), leave original line unchanged. if (name == "") { print next } line = $0 if (name == "ioctl") { line = replace_ioctl_request(line) } # Insert name= immediately after the comm=... token. if (match(line, /comm=[^ ]+/)) { prefix = substr($0, 1, RSTART - 1) token = substr($0, RSTART, RLENGTH) rest = substr($0, RSTART + RLENGTH) print prefix token " name=" name rest } else { # defensive fallback print } } function trim(s) { sub(/^[ \t\r\n]+/, "", s) sub(/[ \t\r\n]+$/, "", s) return s } # If line has args=[...], and there is a second element, try to map it via syd-sys -i function replace_ioctl_request(line, args_start, args_len, before, inside, after, n, i, req, names, arr, rebuilt) { if (!match(line, /args=\[[^]]*\]/)) return line args_start = RSTART args_len = RLENGTH before = substr(line, 1, args_start - 1) inside = substr(line, args_start + 6, args_len - 7) after = substr(line, args_start + args_len) n = split(inside, arr, /,[ \t]*/) if (n < 2) return line for (i = 1; i <= n; i++) arr[i] = trim(arr[i]) req = arr[2] names = ioctl_names(req) # no mapping -> keep as-is if (names == "") return line arr[2] = names # Rebuild args with a consistent ", " separator rebuilt = arr[1] for (i = 2; i <= n; i++) rebuilt = rebuilt ", " arr[i] return before "args=[" rebuilt "]" after } # Cache for ioctl request -> "NAME|NAME2|..." function ioctl_names(req, cmd, out, parts, n, names) { if (ioc_seen[req]) return ioc_cache[req] names = "" cmd = lookup_cmd " -i " req while ((cmd | getline out) > 0) { n = split(out, parts) if (n >= 1 && parts[1] != "") { if (names != "") names = names "|" parts[1] else names = parts[1] } } close(cmd) ioc_cache[req] = names ioc_seen[req] = 1 return names }