diff options
| author | Florent Revest <revest@chromium.org> | 2023-07-04 17:59:04 +0200 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2024-02-01 10:12:21 +0000 |
| commit | 810241190102eaf849f5744ca7eeb68ad34f01d7 (patch) | |
| tree | 941d2616ff4038ae1e4198ecbaa5fd708fd845eb /pkg/csource | |
| parent | c40f278e4d854c3b6341ec272dd3eb9b84fcff54 (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.go | 52 | ||||
| -rw-r--r-- | pkg/csource/csource_test.go | 19 |
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), } |
