strace

package
v6.0.0+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 14, 2019 License: BSD-3-Clause Imports: 14 Imported by: 0

Documentation

Overview

Package strace implements the logic to print out the input and the return value of each traced syscall.

Package strace supports tracing programs. The basic control of tracing is via a Tracer, which returns raw TraceRecords via a chan. The easiest way to create a Tracer is via RunTracerFromCommand, which uses a filled out exec.Cmd to start a process and produce trace records. Forking is not yet supported.

Index

Constants

View Source
const (
	// ExecMaxTotalSize is the maximum length of all argv and envv entries.
	//
	// N.B. The behavior here is different than Linux. Linux provides a limit on
	// individual arguments of 32 pages, and an aggregate limit of at least 32 pages
	// but otherwise bounded by min(stack size / 4, 8 MB * 3 / 4). We don't implement
	// any behavior based on the stack size, and instead provide a fixed hard-limit of
	// 2 MB (which should work well given that 8 MB stack limits are common).
	ExecMaxTotalSize = 2 * 1024 * 1024

	// ExecMaxElemSize is the maximum length of a single argv or envv entry.
	ExecMaxElemSize = 32 * 4096
)

From gvisor:

View Source
const DefaultLogMaximumSize = 1024

DefaultLogMaximumSize is the default LogMaximumSize.

View Source
const Width = 64

Variables

View Source
var ByteOrder = binary.LittleEndian
View Source
var Debug = func(string, ...interface{}) {}

Debug is a do-nothing function which can be replaced by, e.g., log.Printf

View Source
var EventMaximumSize uint

EventMaximumSize determines the maximum size for data blobs (read, write, etc.) sent over the event channel. Default is 0 because most clients cannot do anything useful with binary text dump of byte array arguments.

View Source
var LogMaximumSize uint = DefaultLogMaximumSize

LogMaximumSize determines the maximum display size for data blobs (read, write, etc.).

Functions

func AlignDown

func AlignDown(length int, align uint) int

AlignDown rounds a down to an alignment. align must be a power of 2.

func AlignUp

func AlignUp(length int, align uint) int

AlignUp rounds a length up to an alignment. align must be a power of 2.

func CaptureAddress

func CaptureAddress(t *Tracer, addr Addr, addrlen uint32) ([]byte, error)

CaptureAddress pulls a socket address from the process as a byte slice. It returns any errors.

func NewProcReader

func NewProcReader(pid int, addr uintptr) io.Reader

NewProcReader returns an io.Reader for a ProcIO.

func NewProcWriter

func NewProcWriter(pid int, addr uintptr) io.Writer

NewProcWriter returns an io.Writer for a ProcIO.

func ReadMessageHeader64

func ReadMessageHeader64(t *Tracer, addr Addr, msg *abi.MessageHeader64) error

ReadMessageHeader64 reads a MessageHeader64

func Run

func Run(root *Tracer) error

Run runs a set of processes as defined by a Tracer. Because of Unix restrictions around which processes which can trace other processes, Run gets a tad involved. It is implemented as a simple loop, driving events via ptrace commands to processes; and responding to events returned by a Wait. It has to handle a few events specially: o if a wait fails, the process has exited, and must no longer be commanded

this is indicated by a wait followed by an error on PtraceGetRegs

o if a process forks successfully, we must add it to our set of traced processes.

We attach that process, wait for it, then issue a ptrace system call command
to it. We don't use the Linux SEIZE command as we can do this in a more generic
Unix way.

We create a map of our traced processes and run until it is empty. The initial value of the map is just the one process we start with.

func SysCall

func SysCall(t *Tracer, r *TraceRecord)

SysCall takes a Tracer and a TraceRecord and adds prettyprint to the TraceRecord.

func Wait

func Wait(wpid int) (int, unix.WaitStatus, error)

Wait will wait for the specified pid using Wait4. Callers may specify the full range of values as specified in the waipid man page, though we typically use only -1 or a valid pid.

Types

type Addr

type Addr uintptr

Addr is an address for use in strace I/O

type Address

type Address string

Address is a byte slice cast as a string that represents the address of a network node. Or, in the case of unix endpoints, it may represent a path.

type Arg

type Arg uintptr

Arg is the argument type for system calls

type EventType

type EventType string

EventType describes whether a record is system call Entry or Exit

const (
	Enter EventType = "E"
	Exit            = "X"
)

type FormatSpecifier

type FormatSpecifier int

FormatSpecifier values describe how an individual syscall argument should be formatted.

const (
	// Hex is just a hexadecimal number.
	Hex FormatSpecifier = iota

	// Oct is just an octal number.
	Oct

	// ReadBuffer is a buffer for a read-style call. The syscall return
	// value is used for the length.
	//
	// Formatted after syscall execution.
	ReadBuffer

	// WriteBuffer is a buffer for a write-style call. The following arg is
	// used for the length.
	//
	// Contents omitted after syscall execution.
	WriteBuffer

	// ReadIOVec is a pointer to a struct iovec for a writev-style call.
	// The following arg is used for the length. The return value is used
	// for the total length.
	//
	// Complete contents only formatted after syscall execution.
	ReadIOVec

	// WriteIOVec is a pointer to a struct iovec for a writev-style call.
	// The following arg is used for the length.
	//
	// Complete contents only formatted before syscall execution, omitted
	// after.
	WriteIOVec

	// IOVec is a generic pointer to a struct iovec. Contents are not dumped.
	IOVec

	// SendMsgHdr is a pointer to a struct msghdr for a sendmsg-style call.
	// Contents formatted only before syscall execution, omitted after.
	SendMsgHdr

	// RecvMsgHdr is a pointer to a struct msghdr for a recvmsg-style call.
	// Contents formatted only after syscall execution.
	RecvMsgHdr

	// Path is a pointer to a char* path.
	Path

	// PostPath is a pointer to a char* path, formatted after syscall
	// execution.
	PostPath

	// ExecveStringVector is a NULL-terminated array of strings. Enforces
	// the maximum execve array length.
	ExecveStringVector

	// PipeFDs is an array of two FDs, formatted after syscall execution.
	PipeFDs

	// Uname is a pointer to a struct uname, formatted after syscall execution.
	Uname

	// Stat is a pointer to a struct stat, formatted after syscall execution.
	Stat

	// SockAddr is a pointer to a struct sockaddr. The following arg is
	// used for length.
	SockAddr

	// PostSockAddr is a pointer to a struct sockaddr, formatted after
	// syscall execution. The following arg is a pointer to the socklen_t
	// length.
	PostSockAddr

	// SockLen is a pointer to a socklen_t, formatted before and after
	// syscall execution.
	SockLen

	// SockFamily is a socket protocol family value.
	SockFamily

	// SockType is a socket type and flags value.
	SockType

	// SockProtocol is a socket protocol value. Argument n-2 is the socket
	// protocol family.
	SockProtocol

	// SockFlags are socket flags.
	SockFlags

	// Timespec is a pointer to a struct timespec.
	Timespec

	// PostTimespec is a pointer to a struct timespec, formatted after
	// syscall execution.
	PostTimespec

	// UTimeTimespec is a pointer to a struct timespec. Formatting includes
	// UTIME_NOW and UTIME_OMIT.
	UTimeTimespec

	// ItimerVal is a pointer to a struct itimerval.
	ItimerVal

	// PostItimerVal is a pointer to a struct itimerval, formatted after
	// syscall execution.
	PostItimerVal

	// ItimerSpec is a pointer to a struct itimerspec.
	ItimerSpec

	// PostItimerSpec is a pointer to a struct itimerspec, formatted after
	// syscall execution.
	PostItimerSpec

	// Timeval is a pointer to a struct timeval, formatted before and after
	// syscall execution.
	Timeval

	// Utimbuf is a pointer to a struct utimbuf.
	Utimbuf

	// Rusage is a struct rusage, formatted after syscall execution.
	Rusage

	// CloneFlags are clone(2) flags.
	CloneFlags

	// OpenFlags are open(2) flags.
	OpenFlags

	// Mode is a mode_t.
	Mode

	// FutexOp is the futex(2) operation.
	FutexOp

	// PtraceRequest is the ptrace(2) request.
	PtraceRequest

	// ItimerType is an itimer type (ITIMER_REAL, etc).
	ItimerType
)

Valid FormatSpecifiers.

Unless otherwise specified, values are formatted before syscall execution and not updated after syscall execution (the same value is output).

type FullAddress

type FullAddress struct {
	// Addr is the network address.
	Addr Address

	// Port is the transport port.
	//
	// This may not be used by all endpoint types.
	Port uint16
}

func GetAddress

func GetAddress(t *Tracer, addr []byte) (FullAddress, error)

GetAddress reads an sockaddr struct from the given address and converts it to the FullAddress format. It supports AF_UNIX, AF_INET and AF_INET6 addresses.

type ProcIO

type ProcIO struct {
	// contains filtered or unexported fields
}

A ProcIO is used to implement io.Reader and io.Writer. it contains a pid, which is unchanging; and an addr and byte count which change as IO proceeds.

func (*ProcIO) Read

func (p *ProcIO) Read(b []byte) (int, error)

Read implements io.Read for a ProcIO.

func (*ProcIO) Write

func (p *ProcIO) Write(b []byte) (int, error)

Write implements io.Write for a ProcIO.

type SyscallArgument

type SyscallArgument struct {
	// Prefer to use accessor methods instead of 'Value' directly.
	Value uintptr
}

SyscallArgument is an argument supplied to a syscall implementation. The methods used to access the arguments are named after the ***C type name*** and they convert to the closest Go type available. For example, Int() refers to a 32-bit signed integer argument represented in Go as an int32.

Using the accessor methods guarantees that the conversion between types is correct, taking into account size and signedness (i.e., zero-extension vs signed-extension).

func (SyscallArgument) Int

func (a SyscallArgument) Int() int32

Int returns the int32 representation of a 32-bit signed integer argument.

func (SyscallArgument) Int64

func (a SyscallArgument) Int64() int64

Int64 returns the int64 representation of a 64-bit signed integer argument.

func (SyscallArgument) ModeT

func (a SyscallArgument) ModeT() uint

ModeT returns the int representation of a mode_t argument.

func (SyscallArgument) Pointer

func (a SyscallArgument) Pointer() Addr

Pointer returns the usermem.Addr representation of a pointer argument.

func (SyscallArgument) SizeT

func (a SyscallArgument) SizeT() uint

SizeT returns the uint representation of a size_t argument.

func (SyscallArgument) Uint

func (a SyscallArgument) Uint() uint32

Uint returns the uint32 representation of a 32-bit unsigned integer argument.

func (SyscallArgument) Uint64

func (a SyscallArgument) Uint64() uint64

Uint64 returns the uint64 representation of a 64-bit unsigned integer argument.

type SyscallArguments

type SyscallArguments [6]SyscallArgument

SyscallArguments represents the set of arguments passed to a syscall.

type SyscallInfo

type SyscallInfo struct {
	// contains filtered or unexported fields
}

SyscallInfo captures the name and printing format of a syscall.

type SyscallMap

type SyscallMap map[uintptr]SyscallInfo

SyscallMap maps syscalls into names and printing formats.

type TraceRecord

type TraceRecord struct {
	EX     EventType
	Regs   unix.PtraceRegs
	Serial int
	Pid    int
	Err    error
	Errno  int
	Args   SyscallArguments
	Ret    [2]SyscallArgument
	Sysno  int
	Time   time.Duration
	Out    string
}

TraceRecord has information about a ptrace event.

func (*TraceRecord) FillArgs

func (rec *TraceRecord) FillArgs()

FillArgs pulls the correct registers to populate system call arguments and the system call number into a TraceRecord. Note that the system call number is not technically an argument. This is good, in a sense, since it makes the function arguments end up in "the right place" from the point of view of the caller. The performance improvement is negligible, as you can see by a look at the GNU runtime.

func (*TraceRecord) FillRet

func (rec *TraceRecord) FillRet()

FillRet fills the TraceRecord with the result values from the registers.

func (*TraceRecord) String

func (t *TraceRecord) String() string

String is a stringer for TraceRecords TODO: stringer for Regs.

type Tracer

type Tracer struct {
	Pid     int
	EX      EventType
	Records chan *TraceRecord
	Count   int
	Raw     bool // Set by the user, it disables pretty printing
	Name    string
	Printer func(t *Tracer, r *TraceRecord)
	Last    *TraceRecord
	// contains filtered or unexported fields
}

Tracer has information to trace one process. It can be created by starting a command, or attaching. Attaching is not supported yet.

func New

func New() (*Tracer, error)

New returns a new Tracer.

func NewTracerChild

func NewTracerChild(pid int) (*Tracer, error)

NewTracerChild creates a tracer from a tracer.

func (*Tracer) Read

func (t *Tracer) Read(addr Addr, v interface{}) (int, error)

Read reads from the process at Addr to the interface{} and returns a byte count and error.

func (*Tracer) ReadString

func (t *Tracer) ReadString(addr Addr, max int) (string, error)

ReadString reads a null-terminated string from the process at Addr and any errors.

func (*Tracer) ReadStringVector

func (t *Tracer) ReadStringVector(addr Addr, maxsize, maxno int) ([]string, error)

ReadStringVector takes an address, max string size, and max number of string to read, and returns a string slice or error.

func (*Tracer) RunTracerFromCmd

func (t *Tracer) RunTracerFromCmd(c *exec.Cmd)

RunTracerFromCommand runs a Tracer given an exec.Cmd. It locks itself down with LockOSThread and will unlock itself when it returns, after the command and all its children exit.

func (*Tracer) Step

func (t *Tracer) Step(e EventType) (int, error)

Step steps a Tracer by issuing a PtraceSyscall to it and then doing a Wait. Note that Step waits for any child to return, not just the one we are stepping.

func (*Tracer) Write

func (t *Tracer) Write(addr Addr, v interface{}) (int, error)

Write writes to the process address sapce and returns a count and error.

Directories

Path Synopsis
internal
abi
Package abi describes the interface between a kernel and userspace.
Package abi describes the interface between a kernel and userspace.
binary
Package binary translates between select fixed-sized types and a binary representation.
Package binary translates between select fixed-sized types and a binary representation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL