Skip to content

Commit da9f641

Browse files
simulation: more syscalls, fix tests
1 parent 4e8416d commit da9f641

File tree

6 files changed

+149
-32
lines changed

6 files changed

+149
-32
lines changed

internal/gosimviewer/index.html.tmpl

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ a {
1414
}
1515
</style>
1616
</head>
17-
<body>
18-
<div id="root" style="display: flex; overflow: hide; height: 100%">
17+
<body style="overflow: hidden;">
18+
<div id="root" style="display: flex; height: 100%">
1919
<div style="width: 50%; display: flex; flex-direction: column;">
2020
<div>
2121
{{ $level := .LogLevel }}

internal/gosimviewer/main.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,12 @@ var funcs = template.FuncMap{
6262
return template.HTML(buf.String()), nil
6363
},
6464
"ShortValue": func(value string) string {
65-
if len(value) > 120 {
66-
// XXX: make this unicode aware
67-
return value[:120]
65+
n := 0
66+
for idx := range value {
67+
n++
68+
if n >= 120 {
69+
return value[:idx] + "…"
70+
}
6871
}
6972
return value
7073
},

internal/gosimviewer/related.html.tmpl

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
<div style="margin: 0; font-family: monospace;">
33
{{ .Step }}
44
<a href="#" onclick="setFilter({focus: 'machine:{{ .Machine }}'})">{{ .Machine }}</a>/<a href="#" onclick="setFilter({focus: 'goroutine:{{ .Goroutine }}'})">{{.Goroutine}}</a>
5-
{{.Time | Time }}
6-
{{ .Level }}
5+
{{ .Time | Time }}
6+
{{ .Level | Level }}
77
<a href="#" onclick="show({index: {{ .Index }}, source: {{ .Source }} })">{{ .Source | Source }}</a>
88
&gt;
99
<span style="white-space-collapse: preserve;">{{ .Msg }}</span>

internal/simulation/os_linux.go

+129-13
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ func (l *LinuxOS) PollOpen(fd int, desc syscallabi.ValueView[syscallabi.PollDesc
163163
return 0
164164
}
165165

166+
func (customSyscallLogger) LogEntryPollOpen(fd int, desc *syscallabi.PollDesc, syscall *syscallabi.Syscall) {
167+
// logSyscallEntry("PollOpen", syscall, "fd", fd)
168+
}
169+
170+
func (customSyscallLogger) LogExitPollOpen(fd int, desc *syscallabi.PollDesc, syscall *syscallabi.Syscall, code int) {
171+
// logSyscallExit("PollOpen", syscall, "code", code)
172+
}
173+
166174
func (l *LinuxOS) PollClose(fd int, desc syscallabi.ValueView[syscallabi.PollDesc], invocation *syscallabi.Syscall) int {
167175
l.mu.Lock()
168176
defer l.mu.Unlock()
@@ -183,6 +191,14 @@ func (l *LinuxOS) PollClose(fd int, desc syscallabi.ValueView[syscallabi.PollDes
183191
return 0
184192
}
185193

194+
func (customSyscallLogger) LogEntryPollClose(fd int, desc *syscallabi.PollDesc, syscall *syscallabi.Syscall) {
195+
// logSyscallEntry("PollClose", syscall, "fd", fd)
196+
}
197+
198+
func (customSyscallLogger) LogExitPollClose(fd int, desc *syscallabi.PollDesc, syscall *syscallabi.Syscall, code int) {
199+
// logSyscallExit("PollClose", syscall, "code", code)
200+
}
201+
186202
type (
187203
RawSockaddrAny = syscall.RawSockaddrAny
188204
Utsname = syscall.Utsname
@@ -265,9 +281,6 @@ func (l *LinuxOS) SysOpenat(dirfd int, path string, flags int, mode uint32, invo
265281
// just get rid of this
266282
flags &= ^syscall.O_CLOEXEC
267283

268-
// logf("openat %d %s %d %d", dirfd, path, flags, mode)
269-
// l.logfFor(invocation, "openat %d %s %d %d", dirfd, path, flags, mode)
270-
271284
// TODO: some rules about paths; component length; total length; allow characters?
272285
// TODO: check mode
273286

@@ -462,13 +475,52 @@ func (l *LinuxOS) SysGetdents64(fd int, data syscallabi.ByteSliceView, invocatio
462475
retn += reclen
463476
}
464477

465-
l.logfFor(invocation, "getdents64 %d %d", fd, data.Len() /*, data*/)
466-
467478
f.didReaddir = true
468479

469480
return retn, nil
470481
}
471482

483+
func (customSyscallLogger) LogEntrySysGetdents64(fd int, buf []byte, syscall *syscallabi.Syscall) {
484+
logSyscallEntry("SysGetdents64", syscall, "fd", fd, "len(buf)", len(buf))
485+
}
486+
487+
type Dentry struct {
488+
Inode uint64
489+
Offset uint64
490+
Reclen uint16
491+
Type string
492+
Name string
493+
}
494+
495+
var dtType = &gosimlog.BitflagFormatter{
496+
Choices: []gosimlog.BitflagChoice{
497+
{
498+
Mask: 0xf,
499+
Values: map[int]string{
500+
syscall.DT_REG: "DT_REG",
501+
syscall.DT_DIR: "DT_DIR",
502+
},
503+
},
504+
},
505+
}
506+
507+
func (customSyscallLogger) LogExitSysGetdents64(fd int, buf []byte, syscall *syscallabi.Syscall, n int, err error) {
508+
var entries []*Dentry
509+
buf = buf[:n]
510+
for len(buf) > 19 {
511+
var entry Dentry
512+
entry.Inode = binary.LittleEndian.Uint64(buf[0:8])
513+
entry.Offset = binary.LittleEndian.Uint64(buf[8:16])
514+
entry.Reclen = binary.LittleEndian.Uint16(buf[16:18])
515+
entry.Type = dtType.Format(int(buf[18]))
516+
nameLen := entry.Reclen - 19 - 1
517+
entry.Name = string(buf[19 : 19+nameLen])
518+
entries = append(entries, &entry)
519+
buf = buf[entry.Reclen:]
520+
}
521+
logSyscallExit("SysGetdents64", syscall, "n", n, "err", err, "entries", entries)
522+
}
523+
472524
func (l *LinuxOS) SysWrite(fd int, data syscallabi.ByteSliceView, invocation *syscallabi.Syscall) (int, error) {
473525
l.mu.Lock()
474526
defer l.mu.Unlock()
@@ -513,7 +565,6 @@ func (l *LinuxOS) SysWrite(fd int, data syscallabi.ByteSliceView, invocation *sy
513565
retn := l.machine.filesystem.Write(f.inode, f.pos, data)
514566
f.pos += int64(retn)
515567

516-
l.logfFor(invocation, "write %d %d %q", fd, data.Len(), data)
517568
return retn, nil
518569

519570
case *Socket:
@@ -532,14 +583,22 @@ func (l *LinuxOS) SysWrite(fd int, data syscallabi.ByteSliceView, invocation *sy
532583
return retn, syscall.EBADFD
533584
}
534585

535-
l.logfFor(invocation, "write %d %d %q", fd, data.Len(), data)
536586
return retn, nil
537587

538588
default:
539589
return 0, syscall.EBADFD
540590
}
541591
}
542592

593+
func (customSyscallLogger) LogEntrySysWrite(fd int, p []byte, syscall *syscallabi.Syscall) {
594+
// TODO: format these []byte attrs nicer: handle both ascii and binary gracefully
595+
logSyscallEntry("SysWrite", syscall, "fd", fd, "p", string(p))
596+
}
597+
598+
func (customSyscallLogger) LogExitSysWrite(fd int, p []byte, syscall *syscallabi.Syscall, n int, err error) {
599+
logSyscallExit("SysWrite", syscall, "n", n, "err", err)
600+
}
601+
543602
func (l *LinuxOS) SysRead(fd int, data syscallabi.ByteSliceView, invocation *syscallabi.Syscall) (int, error) {
544603
l.mu.Lock()
545604
defer l.mu.Unlock()
@@ -561,8 +620,6 @@ func (l *LinuxOS) SysRead(fd int, data syscallabi.ByteSliceView, invocation *sys
561620
retn := l.machine.filesystem.Read(f.inode, f.pos, data)
562621
f.pos += int64(retn)
563622

564-
l.logfFor(invocation, "read %d %d", fd, data.Len() /*, data[:retn]*/)
565-
566623
return retn, nil
567624

568625
case *Socket:
@@ -581,15 +638,21 @@ func (l *LinuxOS) SysRead(fd int, data syscallabi.ByteSliceView, invocation *sys
581638
return 0, syscall.EBADFD
582639
}
583640

584-
l.logfFor(invocation, "read %d %d", fd, data.Len() /*, data[:retn]*/)
585-
586641
return retn, nil
587642

588643
default:
589644
return 0, syscall.EBADFD
590645
}
591646
}
592647

648+
func (customSyscallLogger) LogEntrySysRead(fd int, p []byte, syscall *syscallabi.Syscall) {
649+
logSyscallEntry("SysRead", syscall, "fd", fd, "len(p)", len(p))
650+
}
651+
652+
func (customSyscallLogger) LogExitSysRead(fd int, p []byte, syscall *syscallabi.Syscall, n int, err error) {
653+
logSyscallExit("SysRead", syscall, "n", n, "err", err, "p[:n]", string(p[:n]))
654+
}
655+
593656
func (l *LinuxOS) SysFallocate(fd int, mode uint32, off int64, len int64, invocation *syscallabi.Syscall) (err error) {
594657
l.mu.Lock()
595658
defer l.mu.Unlock()
@@ -723,6 +786,14 @@ func (l *LinuxOS) SysPwrite64(fd int, data syscallabi.ByteSliceView, offset int6
723786
return retn, nil
724787
}
725788

789+
func (customSyscallLogger) LogEntrySysPwrite64(fd int, p []byte, offset int64, syscall *syscallabi.Syscall) {
790+
logSyscallEntry("SysPwrite64", syscall, "fd", fd, "offset", offset, "p", string(p))
791+
}
792+
793+
func (customSyscallLogger) LogExitSysPwrite64(fd int, p []byte, offset int64, syscall *syscallabi.Syscall, n int, err error) {
794+
logSyscallExit("SysPwrite64", syscall, "n", n, "err", err)
795+
}
796+
726797
func (l *LinuxOS) SysPread64(fd int, data syscallabi.ByteSliceView, offset int64, invocation *syscallabi.Syscall) (int, error) {
727798
l.mu.Lock()
728799
defer l.mu.Unlock()
@@ -751,6 +822,14 @@ func (l *LinuxOS) SysPread64(fd int, data syscallabi.ByteSliceView, offset int64
751822
return retn, nil
752823
}
753824

825+
func (customSyscallLogger) LogEntrySysPread64(fd int, p []byte, offset int64, syscall *syscallabi.Syscall) {
826+
logSyscallEntry("SysPread64", syscall, "fd", fd, "offset", offset, "len(p)", len(p))
827+
}
828+
829+
func (customSyscallLogger) LogExitSysPread64(fd int, p []byte, offset int64, syscall *syscallabi.Syscall, n int, err error) {
830+
logSyscallExit("SysPread64", syscall, "n", n, "err", err, "p[:n]", string(p[:n]))
831+
}
832+
754833
func (l *LinuxOS) SysFsync(fd int, invocation *syscallabi.Syscall) error {
755834
// XXX: janky way to crash on sync
756835
l.machine.sometimesCrashOnSyncMu.Lock()
@@ -1491,8 +1570,6 @@ func (l *LinuxOS) SysGetpeername(fd int, rsa syscallabi.ValueView[RawSockaddrAny
14911570
return syscall.EINVAL
14921571
}
14931572

1494-
l.logfFor(invocation, "getpeername %d %d", fd, len.Get())
1495-
14961573
fdInternal, ok := l.files[fd]
14971574
if !ok {
14981575
return syscall.EBADFD
@@ -1514,6 +1591,14 @@ func (l *LinuxOS) SysGetpeername(fd int, rsa syscallabi.ValueView[RawSockaddrAny
15141591
return nil
15151592
}
15161593

1594+
func (customSyscallLogger) LogEntrySysGetpeername(fd int, rsa *RawSockaddrAny, addrlen *Socklen, syscall *syscallabi.Syscall) {
1595+
logSyscallEntry("SysGetpeername", syscall, "fd", fd)
1596+
}
1597+
1598+
func (customSyscallLogger) LogExitSysGetpeername(fd int, rsa *RawSockaddrAny, addrlen *Socklen, syscall *syscallabi.Syscall, err error) {
1599+
logSyscallExit("SysGetpeername", syscall, addrAttr(unsafe.Pointer(rsa), *addrlen), "err", err)
1600+
}
1601+
15171602
func (l *LinuxOS) SysFcntl(fd int, cmd int, arg int, invocation *syscallabi.Syscall) (val int, err error) {
15181603
l.mu.Lock()
15191604
defer l.mu.Unlock()
@@ -1622,6 +1707,14 @@ func (l *LinuxOS) SysGetpid(invocation *syscallabi.Syscall) int {
16221707
return 42
16231708
}
16241709

1710+
func (customSyscallLogger) LogEntrySysGetpid(syscall *syscallabi.Syscall) {
1711+
logSyscallEntry("SysGetpid", syscall)
1712+
}
1713+
1714+
func (customSyscallLogger) LogExitSysGetpid(syscall *syscallabi.Syscall, pid int) {
1715+
logSyscallExit("SysGetpid", syscall, "pid", pid)
1716+
}
1717+
16251718
func (l *LinuxOS) SysUname(buf syscallabi.ValueView[Utsname], invocation *syscallabi.Syscall) (err error) {
16261719
ptr := (*Utsname)(buf.UnsafePointer())
16271720
name := syscallabi.NewSliceView(&ptr.Nodename[0], uintptr(len(ptr.Nodename)))
@@ -1635,6 +1728,29 @@ func (l *LinuxOS) SysUname(buf syscallabi.ValueView[Utsname], invocation *syscal
16351728
return nil
16361729
}
16371730

1731+
func int8ArrayToString(key string, value []int8) slog.Attr {
1732+
n := 0
1733+
for i, c := range value {
1734+
if c == 0 {
1735+
n = i
1736+
break
1737+
}
1738+
}
1739+
b := make([]byte, n)
1740+
for i := range n {
1741+
b[i] = byte(value[i])
1742+
}
1743+
return slog.String(key, string(b))
1744+
}
1745+
1746+
func (customSyscallLogger) LogEntrySysUname(buf *Utsname, syscall *syscallabi.Syscall) {
1747+
logSyscallEntry("SysUname", syscall)
1748+
}
1749+
1750+
func (customSyscallLogger) LogExitSysUname(buf *Utsname, syscall *syscallabi.Syscall, err error) {
1751+
logSyscallExit("SysUname", syscall, slog.Group("buf", int8ArrayToString("nodename", buf.Nodename[:])), "err", err)
1752+
}
1753+
16381754
func (l *LinuxOS) SysMadvise(b syscallabi.SliceView[byte], advice int, invocation *syscallabi.Syscall) (err error) {
16391755
l.logfFor(invocation, "madvise %d %d %d", uintptr(unsafe.Pointer(unsafe.SliceData(b.Ptr))), b.Len(), advice)
16401756
// ignore? check args for some sanity?

internal/tests/behavior/log_meta_test.go

+8-10
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,14 @@ func TestLogTraceSyscall(t *testing.T) {
161161
if diff := cmp.Diff(metatesting.SimplifyParsedLog(metatesting.ParseLog(run.LogOutput)), []string{
162162
"INFO unsupported syscall unknown (9999) 0 0 0 0 0 0",
163163
// TODO: check flags
164-
"INFO invoking SysOpenat",
165-
"INFO SysOpenat returned",
166-
"INFO invoking SysFcntl",
167-
"INFO SysFcntl returned",
168-
"INFO invoking SysWrite",
169-
`INFO write 5 5 {"world"}`,
170-
"INFO SysWrite returned",
171-
"INFO invoking SysClose",
172-
"INFO close 5",
173-
"INFO SysClose returned",
164+
"INFO call SysOpenat",
165+
"INFO ret SysOpenat",
166+
"INFO call SysFcntl",
167+
"INFO ret SysFcntl",
168+
"INFO call SysWrite",
169+
"INFO ret SysWrite",
170+
"INFO call SysClose",
171+
"INFO ret SysClose",
174172
}); diff != "" {
175173
t.Error("diff", diff)
176174
}

internal/tests/script/testdata/simtrace.txtar

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# running gosim with -simtrace
22
exec gosim test -run TestSyscall -simtrace= -v .
33
! stdout 'SysOpenat'
4-
! stdout 'write'
4+
! stdout 'SysWrite'
55

66
exec gosim test -run TestSyscall -simtrace=syscall -v .
77
stdout 'SysOpenat.*hello'
8-
stdout 'write.*world'
8+
stdout 'SysWrite.*world'
99

1010
-- simtrace_test.go --
1111
package behavior_test

0 commit comments

Comments
 (0)