diff options
| -rw-r--r-- | pkg/csource/csource.go | 24 | ||||
| -rw-r--r-- | pkg/csource/csource_test.go | 11 | ||||
| -rw-r--r-- | sys/test/csource.txt | 1 |
3 files changed, 28 insertions, 8 deletions
diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go index 198ddf7df..d5da107b0 100644 --- a/pkg/csource/csource.go +++ b/pkg/csource/csource.go @@ -354,8 +354,7 @@ func (ctx *context) fmtCallBody(call prog.ExecCall) string { panic("string format in syscall argument") } com := ctx.argComment(call.Meta.Args[i], arg) - suf := ctx.literalSuffix(arg, native) - argsStrs = append(argsStrs, com+handleBigEndian(arg, ctx.constArgToStr(arg, suf))) + argsStrs = append(argsStrs, com+handleBigEndian(arg, ctx.constArgToStr(arg, native))) case prog.ExecArgResult: if arg.Format != prog.FormatNative && arg.Format != prog.FormatBigEndian { panic("string format in syscall argument") @@ -403,7 +402,7 @@ func (ctx *context) copyin(w *bytes.Buffer, csumSeq *int, copyin prog.ExecCopyin switch arg := copyin.Arg.(type) { case prog.ExecArgConst: if arg.BitfieldOffset == 0 && arg.BitfieldLength == 0 { - ctx.copyinVal(w, copyin.Addr, arg.Size, handleBigEndian(arg, ctx.constArgToStr(arg, "")), arg.Format) + ctx.copyinVal(w, copyin.Addr, arg.Size, handleBigEndian(arg, ctx.constArgToStr(arg, false)), arg.Format) } else { if arg.Format != prog.FormatNative && arg.Format != prog.FormatBigEndian { panic("bitfield+string format") @@ -417,7 +416,7 @@ func (ctx *context) copyin(w *bytes.Buffer, csumSeq *int, copyin prog.ExecCopyin bitfieldOffset = arg.Size*8 - arg.BitfieldOffset - arg.BitfieldLength } fmt.Fprintf(w, "\tNONFAILING(STORE_BY_BITMASK(uint%v, %v, 0x%x, %v, %v, %v));\n", - arg.Size*8, htobe, copyin.Addr, ctx.constArgToStr(arg, ""), + arg.Size*8, htobe, copyin.Addr, ctx.constArgToStr(arg, false), bitfieldOffset, arg.BitfieldLength) } case prog.ExecArgResult: @@ -550,12 +549,21 @@ func (ctx *context) argComment(field prog.Field, arg prog.ExecArg) string { return "/*" + field.Name + "=" + val + "*/" } -func (ctx *context) constArgToStr(arg prog.ExecArgConst, suffix string) string { +// enforceBitSize is necessary e.g. in the variadic arguments context of the syscall() function. +func (ctx *context) constArgToStr(arg prog.ExecArgConst, enforceBitSize bool) string { + suffix := "" + if enforceBitSize { + suffix = ctx.literalSuffix(arg) + } mask := (uint64(1) << (arg.Size * 8)) - 1 v := arg.Value & mask val := "" if v == ^uint64(0)&mask { - val = "-1" + if enforceBitSize { + val = "(intptr_t)-1" + } else { + val = "-1" + } } else if v >= 10 { val = fmt.Sprintf("0x%x%s", v, suffix) } else { @@ -567,8 +575,8 @@ func (ctx *context) constArgToStr(arg prog.ExecArgConst, suffix string) string { return val } -func (ctx *context) literalSuffix(arg prog.ExecArgConst, native bool) string { - if native && arg.Size == 8 { +func (ctx *context) literalSuffix(arg prog.ExecArgConst) string { + if arg.Size == 8 { // syscall() is variadic, so constant arguments must be explicitly // promoted. Otherwise the compiler is free to leave garbage in the // upper 32 bits of the argument value. In practice this can happen diff --git a/pkg/csource/csource_test.go b/pkg/csource/csource_test.go index 472e82225..16aef1b14 100644 --- a/pkg/csource/csource_test.go +++ b/pkg/csource/csource_test.go @@ -240,6 +240,17 @@ syscall(SYS_csource7, /*flag=*/4ul); syscall(SYS_csource7, /*flag=BIT_0|0x4*/5ul); `, }, + + { + input: ` +csource0(0xffffffff) +csource8(0xffffffffffffffff) +`, + output: ` +syscall(SYS_csource0, /*num=*/(intptr_t)-1); +syscall(SYS_csource8, /*num=*/(intptr_t)-1); +`, + }, } for i, test := range tests { t.Run(fmt.Sprint(i), func(t *testing.T) { diff --git a/sys/test/csource.txt b/sys/test/csource.txt index 4efdebb2f..de32bf206 100644 --- a/sys/test/csource.txt +++ b/sys/test/csource.txt @@ -15,3 +15,4 @@ csource4(buf ptr[in, array[const[0x30, int8], 10]]) csource5(buf ptr[in, array[const[0x3130, int16], 5]]) csource6(buf ptr[in, array[const[0x3130, int16be], 6]]) csource7(flag flags[bitmask]) +csource8(num int64) |
