Skip to content

Commit

Permalink
simulation: format byte buffers slightly nicer
Browse files Browse the repository at this point in the history
  • Loading branch information
jellevandenhooff committed Dec 6, 2024
1 parent da9f641 commit fb82171
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 49 deletions.
14 changes: 14 additions & 0 deletions internal/gosimlog/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package gosimlog

import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"log/slog"
"reflect"
"runtime"
"slices"
"strconv"
"strings"
"time"
)
Expand Down Expand Up @@ -77,6 +79,18 @@ func unmarshalWithExtraFields(data []byte, value any, extra *[]UnknownField, kno
if err := d.Decode(&value); err != nil {
return err
}

// decode base64 binary in values and make it easier to read
// TODO: make this less hacky, it would be nice to support
// "types" broadly (time, references to steps/machines/FDs,
// binary data, other stuff) and format them nicely
const base64Prefix = `"base64:`
if len(value) > 0 && bytes.HasPrefix(value, []byte(base64Prefix)) {
if maybeBytes, err := base64.StdEncoding.AppendDecode(nil, value[len(base64Prefix):len(value)-1]); err == nil {
*extra = append(*extra, UnknownField{Key: key, Value: strconv.QuoteToASCII(string(maybeBytes))})
continue
}
}
*extra = append(*extra, UnknownField{Key: key, Value: string(value)})
}
}
Expand Down
100 changes: 51 additions & 49 deletions internal/simulation/os_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package simulation

import (
"bytes"
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
Expand Down Expand Up @@ -92,6 +93,43 @@ func logSyscallExit(name string, invocation *syscallabi.Syscall, attrs ...any) {
slog.Info("ret "+name, attrs...)
}

func byteDataAttr(key string, value []byte) slog.Attr {
return slog.String(key, "base64:"+base64.StdEncoding.EncodeToString(value))
}

func fdAttr(name string, fd int) slog.Attr {
switch fd {
case _AT_FDCWD:
return slog.String(name, "AT_FDCWD")
default:
return slog.Int(name, fd)
}
}

func addrAttr(addr unsafe.Pointer, addrlen Socklen) slog.Attr {
parsedAddr, parseErr := readAddr(addr, addrlen)
if parseErr != 0 {
return slog.Any("addr", parseErr)
} else {
return slog.Any("addr", parsedAddr)
}
}

func int8ArrayToString(key string, value []int8) slog.Attr {
n := 0
for i, c := range value {
if c == 0 {
n = i
break
}
}
b := make([]byte, n)
for i := range n {
b[i] = byte(value[i])
}
return slog.String(key, string(b))
}

// logfFor logs the given format and args on the goroutine from the passed
// invocation.
func (l *LinuxOS) logfFor(invocation *syscallabi.Syscall, format string, args ...any) {
Expand Down Expand Up @@ -327,15 +365,6 @@ func (l *LinuxOS) SysOpenat(dirfd int, path string, flags int, mode uint32, invo
return fd, nil
}

func fdAttr(name string, fd int) slog.Attr {
switch fd {
case _AT_FDCWD:
return slog.String(name, "AT_FDCWD")
default:
return slog.Int(name, fd)
}
}

var openatFlags = &gosimlog.BitflagFormatter{
Choices: []gosimlog.BitflagChoice{
{
Expand Down Expand Up @@ -420,8 +449,6 @@ func (l *LinuxOS) SysGetdents64(fd int, data syscallabi.ByteSliceView, invocatio
return 0, syscall.EINVAL
}

l.logfFor(invocation, "getdents64 %d %d", fd, data.Len())

fdInternal, ok := l.files[fd]
if !ok {
return 0, syscall.EBADFD
Expand All @@ -436,6 +463,7 @@ func (l *LinuxOS) SysGetdents64(fd int, data syscallabi.ByteSliceView, invocatio
return 0, nil
}

// TODO: make this iteration work with some kind of pointer
entries, err := l.machine.filesystem.ReadDir(f.inode)
if err != nil {
return 0, syscall.EINVAL // XXX?
Expand Down Expand Up @@ -531,9 +559,7 @@ func (l *LinuxOS) SysWrite(fd int, data syscallabi.ByteSliceView, invocation *sy
if fd == syscall.Stdout || fd == syscall.Stderr {
buf := make([]byte, data.Len())
data.Read(buf)
// TODO: use a custom machine here?

// TODO: iterate over buf line-by-line?
buf = bytes.TrimSuffix(buf, []byte("\n"))

var source string
Expand Down Expand Up @@ -592,7 +618,7 @@ func (l *LinuxOS) SysWrite(fd int, data syscallabi.ByteSliceView, invocation *sy

func (customSyscallLogger) LogEntrySysWrite(fd int, p []byte, syscall *syscallabi.Syscall) {
// TODO: format these []byte attrs nicer: handle both ascii and binary gracefully
logSyscallEntry("SysWrite", syscall, "fd", fd, "p", string(p))
logSyscallEntry("SysWrite", syscall, "fd", fd, byteDataAttr("p", p))
}

func (customSyscallLogger) LogExitSysWrite(fd int, p []byte, syscall *syscallabi.Syscall, n int, err error) {
Expand Down Expand Up @@ -650,7 +676,7 @@ func (customSyscallLogger) LogEntrySysRead(fd int, p []byte, syscall *syscallabi
}

func (customSyscallLogger) LogExitSysRead(fd int, p []byte, syscall *syscallabi.Syscall, n int, err error) {
logSyscallExit("SysRead", syscall, "n", n, "err", err, "p[:n]", string(p[:n]))
logSyscallExit("SysRead", syscall, "n", n, "err", err, byteDataAttr("p", p[:n]))
}

func (l *LinuxOS) SysFallocate(fd int, mode uint32, off int64, len int64, invocation *syscallabi.Syscall) (err error) {
Expand Down Expand Up @@ -781,13 +807,11 @@ func (l *LinuxOS) SysPwrite64(fd int, data syscallabi.ByteSliceView, offset int6

retn := l.machine.filesystem.Write(f.inode, offset, data)

l.logfFor(invocation, "writeat %d %d %q %d", fd, retn, data, offset)

return retn, nil
}

func (customSyscallLogger) LogEntrySysPwrite64(fd int, p []byte, offset int64, syscall *syscallabi.Syscall) {
logSyscallEntry("SysPwrite64", syscall, "fd", fd, "offset", offset, "p", string(p))
logSyscallEntry("SysPwrite64", syscall, "fd", fd, "offset", offset, byteDataAttr("p", p))
}

func (customSyscallLogger) LogExitSysPwrite64(fd int, p []byte, offset int64, syscall *syscallabi.Syscall, n int, err error) {
Expand Down Expand Up @@ -817,8 +841,6 @@ func (l *LinuxOS) SysPread64(fd int, data syscallabi.ByteSliceView, offset int64

retn := l.machine.filesystem.Read(f.inode, offset, data)

l.logfFor(invocation, "readat %d %d %d", fd, data.Len() /*, data[:retn]*/, offset)

return retn, nil
}

Expand All @@ -827,7 +849,7 @@ func (customSyscallLogger) LogEntrySysPread64(fd int, p []byte, offset int64, sy
}

func (customSyscallLogger) LogExitSysPread64(fd int, p []byte, offset int64, syscall *syscallabi.Syscall, n int, err error) {
logSyscallExit("SysPread64", syscall, "n", n, "err", err, "p[:n]", string(p[:n]))
logSyscallExit("SysPread64", syscall, "n", n, "err", err, byteDataAttr("p", p[:n]))
}

func (l *LinuxOS) SysFsync(fd int, invocation *syscallabi.Syscall) error {
Expand Down Expand Up @@ -1212,15 +1234,6 @@ func (l *LinuxOS) SysBind(fd int, addrPtr unsafe.Pointer, addrlen Socklen, invoc
return nil
}

func addrAttr(addr unsafe.Pointer, addrlen Socklen) slog.Attr {
parsedAddr, parseErr := readAddr(addr, addrlen)
if parseErr != 0 {
return slog.Any("addr", parseErr)
} else {
return slog.Any("addr", parsedAddr)
}
}

func (customSyscallLogger) LogEntrySysBind(s int, addr unsafe.Pointer, addrlen Socklen, syscall *syscallabi.Syscall) {
logSyscallEntry("SysBind", syscall, "fd", s, addrAttr(addr, addrlen))
}
Expand Down Expand Up @@ -1490,8 +1503,6 @@ func (l *LinuxOS) SysChdir(path string, invocation *syscallabi.Syscall) (err err
return syscall.EINVAL
}

l.logfFor(invocation, "chdir %s", path)

newDirinode, err := l.machine.filesystem.Getdirinode(l.workdirInode, path)
if err != nil {
return err
Expand Down Expand Up @@ -1685,8 +1696,6 @@ func (l *LinuxOS) SysGetrandom(ptr syscallabi.ByteSliceView, flags int, invocati
return 0, syscall.EINVAL
}

l.logfFor(invocation, "getrandom %d %d", ptr.Len(), flags)

if flags != 0 {
return 0, syscall.EINVAL
}
Expand All @@ -1702,6 +1711,14 @@ func (l *LinuxOS) SysGetrandom(ptr syscallabi.ByteSliceView, flags int, invocati
return n, nil
}

func (customSyscallLogger) LogEntrySysGetrandom(buf []byte, flags int, syscall *syscallabi.Syscall) {
// logSyscallEntry("SysGetrandom", syscall)
}

func (customSyscallLogger) LogExitSysGetrandom(buf []byte, flags int, syscall *syscallabi.Syscall, n int, err error) {
// logSyscallExit("SysGetrandom", syscall)
}

func (l *LinuxOS) SysGetpid(invocation *syscallabi.Syscall) int {
// TODO: return some random number instead?
return 42
Expand All @@ -1728,21 +1745,6 @@ func (l *LinuxOS) SysUname(buf syscallabi.ValueView[Utsname], invocation *syscal
return nil
}

func int8ArrayToString(key string, value []int8) slog.Attr {
n := 0
for i, c := range value {
if c == 0 {
n = i
break
}
}
b := make([]byte, n)
for i := range n {
b[i] = byte(value[i])
}
return slog.String(key, string(b))
}

func (customSyscallLogger) LogEntrySysUname(buf *Utsname, syscall *syscallabi.Syscall) {
logSyscallEntry("SysUname", syscall)
}
Expand Down

0 comments on commit fb82171

Please sign in to comment.