aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/csource
diff options
context:
space:
mode:
authorFlorent Revest <revest@chromium.org>2023-07-04 17:59:04 +0200
committerAleksandr Nogikh <nogikh@google.com>2024-02-01 10:12:21 +0000
commit810241190102eaf849f5744ca7eeb68ad34f01d7 (patch)
tree941d2616ff4038ae1e4198ecbaa5fd708fd845eb /pkg/csource
parentc40f278e4d854c3b6341ec272dd3eb9b84fcff54 (diff)
pkg/csource: annotate syscall() args with their pretty-printed values
This factorizes const arguments into the shortest flags OR bitmask possible so they are easy to read. E.g: /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul
Diffstat (limited to 'pkg/csource')
-rw-r--r--pkg/csource/csource.go52
-rw-r--r--pkg/csource/csource_test.go19
2 files changed, 70 insertions, 1 deletions
diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go
index a56a738c5..b1cc2368b 100644
--- a/pkg/csource/csource.go
+++ b/pkg/csource/csource.go
@@ -26,6 +26,7 @@ package csource
import (
"bytes"
"fmt"
+ "math/bits"
"regexp"
"sort"
"strconv"
@@ -501,8 +502,57 @@ func (ctx *context) copyout(w *bytes.Buffer, call prog.ExecCall, resCopyout bool
}
}
+func (ctx *context) factorizeAsFlags(value uint64, flags []string, attemptsLeft *int) ([]string, uint64) {
+ if len(flags) == 0 || value == 0 || *attemptsLeft == 0 {
+ return nil, value
+ }
+
+ *attemptsLeft -= 1
+ currentFlag := flags[0]
+ subset, remainder := ctx.factorizeAsFlags(value, flags[1:], attemptsLeft)
+
+ if flagMask, ok := ctx.p.Target.ConstMap[currentFlag]; ok && (value&flagMask == flagMask) {
+ subsetIfTaken, remainderIfTaken := ctx.factorizeAsFlags(value & ^flagMask, flags[1:], attemptsLeft)
+ subsetIfTaken = append(subsetIfTaken, currentFlag)
+
+ bits, bitsIfTaken := bits.OnesCount64(remainder), bits.OnesCount64(remainderIfTaken)
+ if (bitsIfTaken < bits) || (bits == bitsIfTaken && len(subsetIfTaken) < len(subset)) {
+ return subsetIfTaken, remainderIfTaken
+ }
+ }
+
+ return subset, remainder
+}
+
+func (ctx *context) prettyPrintValue(field prog.Field, arg prog.ExecArgConst) string {
+ mask := (uint64(1) << (arg.Size * 8)) - 1
+ v := arg.Value & mask
+
+ f := ctx.p.Target.FlagsMap[field.Type.Name()]
+ if len(f) == 0 {
+ return ""
+ }
+
+ maxFactorizationAttempts := 256
+ flags, remainder := ctx.factorizeAsFlags(v, f, &maxFactorizationAttempts)
+ if len(flags) == 0 {
+ return ""
+ }
+ if remainder != 0 {
+ flags = append(flags, fmt.Sprintf("0x%x", remainder))
+ }
+
+ return strings.Join(flags, "|")
+}
+
func (ctx *context) argComment(field prog.Field, arg prog.ExecArg) string {
- return "/*" + field.Name + "=" + "*/"
+ val := ""
+ constArg, isConstArg := arg.(prog.ExecArgConst)
+ if isConstArg {
+ val = ctx.prettyPrintValue(field, constArg)
+ }
+
+ return "/*" + field.Name + "=" + val + "*/"
}
func (ctx *context) constArgToStr(arg prog.ExecArgConst, suffix string) string {
diff --git a/pkg/csource/csource_test.go b/pkg/csource/csource_test.go
index eb85fd77b..957d2ebc9 100644
--- a/pkg/csource/csource_test.go
+++ b/pkg/csource/csource_test.go
@@ -223,6 +223,24 @@ syscall(SYS_csource6, /*buf=*/0x%xul);
target.DataOffset+0x100, target.DataOffset+0x100,
target.DataOffset+0x140, target.DataOffset+0x140),
},
+ {
+ input: `
+csource7(0x0)
+csource7(0x1)
+csource7(0x2)
+csource7(0x3)
+csource7(0x4)
+csource7(0x5)
+`,
+ output: `
+syscall(SYS_csource7, /*flag=*/0ul);
+syscall(SYS_csource7, /*flag=BIT_0*/1ul);
+syscall(SYS_csource7, /*flag=BIT_1*/2ul);
+syscall(SYS_csource7, /*flag=BIT_0_AND_1*/3ul);
+syscall(SYS_csource7, /*flag=*/4ul);
+syscall(SYS_csource7, /*flag=BIT_0|0x4*/5ul);
+`,
+ },
}
for i, test := range tests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
@@ -231,6 +249,7 @@ syscall(SYS_csource6, /*buf=*/0x%xul);
t.Fatal(err)
}
ctx := &context{
+ p: p,
target: target,
sysTarget: targets.Get(target.OS, target.Arch),
}