Better strace logging for epoll syscalls.
Example: epoll_ctl(0x3 anon_inode:[eventpoll], EPOLL_CTL_ADD, 0x6 anon_inode:[eventfd], 0x7efe2fd92a80 {events=EPOLLIN|EPOLLOUT data=0x10203040506070a}) = 0x0 (4.411µs) epoll_wait(0x3 anon_inode:[eventpoll], 0x7efe2fd92b50 {{events=EPOLLOUT data=0x102030405060708}{events=EPOLLOUT data=0x102030405060708}{events=EPOLLOUT data=0x102030405060708}}, 0x3, 0xffffffff) = 0x3 (29.891µs) PiperOrigin-RevId: 296258146
This commit is contained in:
parent
9a4e3e63ef
commit
9bad87339a
|
@ -14,6 +14,10 @@
|
|||
|
||||
package linux
|
||||
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/binary"
|
||||
)
|
||||
|
||||
// Event masks.
|
||||
const (
|
||||
EPOLLIN = 0x1
|
||||
|
@ -53,3 +57,6 @@ const (
|
|||
EPOLL_CTL_DEL = 0x2
|
||||
EPOLL_CTL_MOD = 0x3
|
||||
)
|
||||
|
||||
// SizeOfEpollEvent is the size of EpollEvent struct.
|
||||
var SizeOfEpollEvent = int(binary.Size(EpollEvent{}))
|
||||
|
|
|
@ -7,6 +7,7 @@ go_library(
|
|||
srcs = [
|
||||
"capability.go",
|
||||
"clone.go",
|
||||
"epoll.go",
|
||||
"futex.go",
|
||||
"linux64_amd64.go",
|
||||
"linux64_arm64.go",
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
// Copyright 2020 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package strace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
func epollEvent(t *kernel.Task, eventAddr usermem.Addr) string {
|
||||
var e linux.EpollEvent
|
||||
if _, err := t.CopyIn(eventAddr, &e); err != nil {
|
||||
return fmt.Sprintf("%#x {error reading event: %v}", eventAddr, err)
|
||||
}
|
||||
var sb strings.Builder
|
||||
fmt.Fprintf(&sb, "%#x ", eventAddr)
|
||||
writeEpollEvent(&sb, e)
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func epollEvents(t *kernel.Task, eventsAddr usermem.Addr, numEvents, maxBytes uint64) string {
|
||||
var sb strings.Builder
|
||||
fmt.Fprintf(&sb, "%#x {", eventsAddr)
|
||||
addr := eventsAddr
|
||||
for i := uint64(0); i < numEvents; i++ {
|
||||
var e linux.EpollEvent
|
||||
if _, err := t.CopyIn(addr, &e); err != nil {
|
||||
fmt.Fprintf(&sb, "{error reading event at %#x: %v}", addr, err)
|
||||
continue
|
||||
}
|
||||
writeEpollEvent(&sb, e)
|
||||
if uint64(sb.Len()) >= maxBytes {
|
||||
sb.WriteString("...")
|
||||
break
|
||||
}
|
||||
if _, ok := addr.AddLength(uint64(linux.SizeOfEpollEvent)); !ok {
|
||||
fmt.Fprintf(&sb, "{error reading event at %#x: EFAULT}", addr)
|
||||
continue
|
||||
}
|
||||
}
|
||||
sb.WriteString("}")
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func writeEpollEvent(sb *strings.Builder, e linux.EpollEvent) {
|
||||
events := epollEventEvents.Parse(uint64(e.Events))
|
||||
fmt.Fprintf(sb, "{events=%s data=[%#x, %#x]}", events, e.Data[0], e.Data[1])
|
||||
}
|
||||
|
||||
var epollCtlOps = abi.ValueSet{
|
||||
linux.EPOLL_CTL_ADD: "EPOLL_CTL_ADD",
|
||||
linux.EPOLL_CTL_DEL: "EPOLL_CTL_DEL",
|
||||
linux.EPOLL_CTL_MOD: "EPOLL_CTL_MOD",
|
||||
}
|
||||
|
||||
var epollEventEvents = abi.FlagSet{
|
||||
{Flag: linux.EPOLLIN, Name: "EPOLLIN"},
|
||||
{Flag: linux.EPOLLPRI, Name: "EPOLLPRI"},
|
||||
{Flag: linux.EPOLLOUT, Name: "EPOLLOUT"},
|
||||
{Flag: linux.EPOLLERR, Name: "EPOLLERR"},
|
||||
{Flag: linux.EPOLLHUP, Name: "EPULLHUP"},
|
||||
{Flag: linux.EPOLLRDNORM, Name: "EPOLLRDNORM"},
|
||||
{Flag: linux.EPOLLRDBAND, Name: "EPOLLRDBAND"},
|
||||
{Flag: linux.EPOLLWRNORM, Name: "EPOLLWRNORM"},
|
||||
{Flag: linux.EPOLLWRBAND, Name: "EPOLLWRBAND"},
|
||||
{Flag: linux.EPOLLMSG, Name: "EPOLLMSG"},
|
||||
{Flag: linux.EPOLLRDHUP, Name: "EPOLLRDHUP"},
|
||||
{Flag: linux.EPOLLEXCLUSIVE, Name: "EPOLLEXCLUSIVE"},
|
||||
{Flag: linux.EPOLLWAKEUP, Name: "EPOLLWAKEUP"},
|
||||
{Flag: linux.EPOLLONESHOT, Name: "EPOLLONESHOT"},
|
||||
{Flag: linux.EPOLLET, Name: "EPOLLET"},
|
||||
}
|
|
@ -256,8 +256,8 @@ var linuxAMD64 = SyscallMap{
|
|||
229: makeSyscallInfo("clock_getres", Hex, PostTimespec),
|
||||
230: makeSyscallInfo("clock_nanosleep", Hex, Hex, Timespec, PostTimespec),
|
||||
231: makeSyscallInfo("exit_group", Hex),
|
||||
232: makeSyscallInfo("epoll_wait", Hex, Hex, Hex, Hex),
|
||||
233: makeSyscallInfo("epoll_ctl", Hex, Hex, FD, Hex),
|
||||
232: makeSyscallInfo("epoll_wait", FD, EpollEvents, Hex, Hex),
|
||||
233: makeSyscallInfo("epoll_ctl", FD, EpollCtlOp, FD, EpollEvent),
|
||||
234: makeSyscallInfo("tgkill", Hex, Hex, Signal),
|
||||
235: makeSyscallInfo("utimes", Path, Timeval),
|
||||
// 236: vserver (not implemented in the Linux kernel)
|
||||
|
@ -305,7 +305,7 @@ var linuxAMD64 = SyscallMap{
|
|||
278: makeSyscallInfo("vmsplice", FD, Hex, Hex, Hex),
|
||||
279: makeSyscallInfo("move_pages", Hex, Hex, Hex, Hex, Hex, Hex),
|
||||
280: makeSyscallInfo("utimensat", FD, Path, UTimeTimespec, Hex),
|
||||
281: makeSyscallInfo("epoll_pwait", Hex, Hex, Hex, Hex, SigSet, Hex),
|
||||
281: makeSyscallInfo("epoll_pwait", FD, EpollEvents, Hex, Hex, SigSet, Hex),
|
||||
282: makeSyscallInfo("signalfd", Hex, Hex, Hex),
|
||||
283: makeSyscallInfo("timerfd_create", Hex, Hex),
|
||||
284: makeSyscallInfo("eventfd", Hex),
|
||||
|
|
|
@ -45,8 +45,8 @@ var linuxARM64 = SyscallMap{
|
|||
18: makeSyscallInfo("lookup_dcookie", Hex, Hex, Hex),
|
||||
19: makeSyscallInfo("eventfd2", Hex, Hex),
|
||||
20: makeSyscallInfo("epoll_create1", Hex),
|
||||
21: makeSyscallInfo("epoll_ctl", Hex, Hex, FD, Hex),
|
||||
22: makeSyscallInfo("epoll_pwait", Hex, Hex, Hex, Hex, SigSet, Hex),
|
||||
21: makeSyscallInfo("epoll_ctl", FD, EpollCtlOp, FD, EpollEvent),
|
||||
22: makeSyscallInfo("epoll_pwait", FD, EpollEvents, Hex, Hex, SigSet, Hex),
|
||||
23: makeSyscallInfo("dup", FD),
|
||||
24: makeSyscallInfo("dup3", FD, FD, Hex),
|
||||
25: makeSyscallInfo("fcntl", FD, Hex, Hex),
|
||||
|
|
|
@ -481,6 +481,12 @@ func (i *SyscallInfo) pre(t *kernel.Task, args arch.SyscallArguments, maximumBlo
|
|||
output = append(output, capData(t, args[arg-1].Pointer(), args[arg].Pointer()))
|
||||
case PollFDs:
|
||||
output = append(output, pollFDs(t, args[arg].Pointer(), uint(args[arg+1].Uint()), false))
|
||||
case EpollCtlOp:
|
||||
output = append(output, epollCtlOps.Parse(uint64(args[arg].Int())))
|
||||
case EpollEvent:
|
||||
output = append(output, epollEvent(t, args[arg].Pointer()))
|
||||
case EpollEvents:
|
||||
output = append(output, epollEvents(t, args[arg].Pointer(), 0 /* numEvents */, uint64(maximumBlobSize)))
|
||||
case SelectFDSet:
|
||||
output = append(output, fdSet(t, int(args[0].Int()), args[arg].Pointer()))
|
||||
case Oct:
|
||||
|
@ -549,6 +555,8 @@ func (i *SyscallInfo) post(t *kernel.Task, args arch.SyscallArguments, rval uint
|
|||
output[arg] = capData(t, args[arg-1].Pointer(), args[arg].Pointer())
|
||||
case PollFDs:
|
||||
output[arg] = pollFDs(t, args[arg].Pointer(), uint(args[arg+1].Uint()), true)
|
||||
case EpollEvents:
|
||||
output[arg] = epollEvents(t, args[arg].Pointer(), uint64(rval), uint64(maximumBlobSize))
|
||||
case GetSockOptVal:
|
||||
output[arg] = getSockOptVal(t, args[arg-2].Uint64() /* level */, args[arg-1].Uint64() /* optName */, args[arg].Pointer() /* optVal */, args[arg+1].Pointer() /* optLen */, maximumBlobSize, rval)
|
||||
case SetSockOptVal:
|
||||
|
|
|
@ -228,6 +228,16 @@ const (
|
|||
// SockOptLevel is the optname argument in getsockopt(2) and
|
||||
// setsockopt(2).
|
||||
SockOptName
|
||||
|
||||
// EpollCtlOp is the op argument to epoll_ctl(2).
|
||||
EpollCtlOp
|
||||
|
||||
// EpollEvent is the event argument in epoll_ctl(2).
|
||||
EpollEvent
|
||||
|
||||
// EpollEvents is an array of struct epoll_event. It is the events
|
||||
// argument in epoll_wait(2)/epoll_pwait(2).
|
||||
EpollEvents
|
||||
)
|
||||
|
||||
// defaultFormat is the syscall argument format to use if the actual format is
|
||||
|
|
Loading…
Reference in New Issue