Skip to content

Commit d15ea9d

Browse files
author
Ethan Graham
committed
pkg/kcov: cleanup and support for 32-bit arches
Use uintptr instead of uint64 to allow for non-64-bit arch support, and do some small cleanup and suggested in code review.
1 parent b0aa679 commit d15ea9d

File tree

3 files changed

+27
-33
lines changed

3 files changed

+27
-33
lines changed

pkg/kcov/cdefs.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@ package kcov
33
import "unsafe"
44

55
const (
6-
// sizeof(uintptr).
7-
sizeofUintPtr = 8
8-
)
6+
sizeofUintPtr = int(unsafe.Sizeof((*int)(nil)))
97

10-
const (
118
_IOC_NRBITS = 8
129
_IOC_TYPEBITS = 8
1310
_IOC_SIZEBITS = 14

pkg/kcov/kcov.go

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,27 @@ type KCOVState struct {
2121
cover []byte
2222
}
2323

24-
// Trace invokes `f` and returns its result, as well as collected kernel
25-
// coverage during its invocation.
26-
func (st *KCOVState) Trace(f func() error) ([]uintptr, error) {
24+
type KCOVTraceResult struct {
25+
Result error // Result of the call.
26+
Coverage []uintptr // Collected program counters.
27+
}
28+
29+
// Trace invokes `f` and returns a KCOVTraceResult.
30+
func (st *KCOVState) Trace(f func() error) KCOVTraceResult {
2731
// First 8 bytes holds the number of collected PCs since last poll.
28-
countPtr := (*uint64)(unsafe.Pointer(&st.cover[0]))
32+
countPtr := (*uintptr)(unsafe.Pointer(&st.cover[0]))
2933
// Reset coverage for this run.
30-
atomic.StoreUint64(countPtr, 0)
34+
atomic.StoreUintptr(countPtr, 0)
3135
// Trigger call.
3236
err := f()
3337
// Load the number of PCs that were hit during trigger.
34-
n := atomic.LoadUint64(countPtr)
35-
if n == 0 {
36-
return nil, nil
37-
}
38+
n := atomic.LoadUintptr(countPtr)
3839

3940
pcDataPtr := (*uintptr)(unsafe.Pointer(&st.cover[sizeofUintPtr]))
4041
pcs := unsafe.Slice(pcDataPtr, n)
4142
pcsCopy := make([]uintptr, n)
4243
copy(pcsCopy, pcs)
43-
return pcsCopy, err
44+
return KCOVTraceResult{Result: err, Coverage: pcsCopy}
4445
}
4546

4647
// EnableTracingForCurrentGoroutine prepares the current goroutine for kcov tracing.
@@ -53,47 +54,42 @@ func EnableTracingForCurrentGoroutine() (*KCOVState, error) {
5354
if err != nil {
5455
return nil, err
5556
}
56-
57-
cleanupOnError := func() {
58-
file.Close()
59-
runtime.UnlockOSThread()
57+
st := KCOVState{
58+
file: file,
6059
}
61-
6260
fd := file.Fd()
6361

6462
// Setup trace mode and size.
6563
if err := unix.IoctlSetInt(int(fd), uint(KCOV_INIT_TRACE), kcovCoverSize); err != nil {
66-
cleanupOnError()
64+
st.DisableTracing()
6765
return nil, err
6866
}
6967

70-
// Mmap buffer shared between kernel- and user-space.
71-
coverageBuffer, err := unix.Mmap(
68+
// Mmap buffer shared between kernel- and user-space. For more information,
69+
// see the Linux KCOV documentation: https://docs.kernel.org/dev-tools/kcov.html.
70+
st.cover, err = unix.Mmap(
7271
int(fd),
73-
0, // offset
72+
0, // Offset.
7473
kcovCoverSize*sizeofUintPtr,
75-
unix.PROT_READ|unix.PROT_WRITE, // a read/write mapping
76-
unix.MAP_SHARED, // changes are shared with the kernel
74+
unix.PROT_READ|unix.PROT_WRITE,
75+
unix.MAP_SHARED,
7776
)
7877
if err != nil {
79-
cleanupOnError()
78+
st.DisableTracing()
8079
return nil, err
8180
}
8281

8382
// Enable coverage collection on the current thread.
8483
if err := unix.IoctlSetInt(int(fd), uint(KCOV_ENABLE), KCOV_TRACE_PC); err != nil {
85-
cleanupOnError()
86-
unix.Munmap(coverageBuffer)
84+
st.DisableTracing()
8785
return nil, err
8886
}
8987

90-
return &KCOVState{
91-
file: file,
92-
cover: coverageBuffer,
93-
}, nil
88+
return &st, nil
9489
}
9590

9691
func (st *KCOVState) DisableTracing() {
9792
runtime.UnlockOSThread()
9893
st.file.Close()
94+
unix.Munmap(st.cover)
9995
}

pkg/kfuzztest/kfuzztest.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,5 +186,6 @@ func ExecKFuzzTestCallLocal(st *kcov.KCOVState, call *prog.Call) ([]uintptr, err
186186
finalBlob := prog.MarshallKFuzztestArg(dataArg.Res)
187187
inputPath := path.Join("/sys/kernel/debug/kfuzztest/", testName, "input")
188188

189-
return st.Trace(func() error { return os.WriteFile(inputPath, finalBlob, 0644) })
189+
res := st.Trace(func() error { return os.WriteFile(inputPath, finalBlob, 0644) })
190+
return res.Coverage, res.Result
190191
}

0 commit comments

Comments
 (0)