v0.3.0 Latest Latest

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

Go to latest
Published: Nov 21, 2018 License: BSD-3-Clause Imports: 14 Imported by: 30



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.



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


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.).


func AlignDown added in v0.3.0

func AlignDown(length int, align uint) int

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

func AlignUp added in v0.3.0

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 added in v0.3.0

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

NewProcReader returns an io.Reader for a ProcIO.

func NewProcWriter added in v0.3.0

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

NewProcWriter returns an io.Writer for a ProcIO.

func ReadMessageHeader64 added in v0.3.0

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

ReadMessageHeader64 reads a MessageHeader64

func Run added in v0.3.0

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 successully, 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 added in v0.3.0

func SysCall(t *Tracer, r *TraceRecord)

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

func Wait added in v0.3.0

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.


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 added in v0.3.0

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.

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

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

	// 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.

	// 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.

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

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

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

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

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

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

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

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

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

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

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

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

	// SockFamily is a socket protocol family value.

	// SockType is a socket type and flags value.

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

	// SockFlags are socket flags.

	// Timespec is a pointer to a struct timespec.

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

	// UTimeTimespec is a pointer to a struct timespec. Formatting includes

	// ItimerVal is a pointer to a struct itimerval.

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

	// ItimerSpec is a pointer to a struct itimerspec.

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

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

	// Utimbuf is a pointer to a struct utimbuf.

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

	// CloneFlags are clone(2) flags.

	// OpenFlags are open(2) flags.

	// Mode is a mode_t.

	// FutexOp is the futex(2) operation.

	// PtraceRequest is the ptrace(2) request.

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

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, sfamily int, 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 added in v0.3.0

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 added in v0.3.0

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

Read implements io.Read for a ProcIO.

func (*ProcIO) Write added in v0.3.0

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 added in v0.3.0

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 arguements 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 added in v0.3.0

func (rec *TraceRecord) FillRet()

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

func (*TraceRecord) String added in v0.3.0

func (t *TraceRecord) String() string

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

type Tracer added in v0.3.0

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 added in v0.3.0

func New() (*Tracer, error)

New returns a new Tracer.

func NewTracerChild added in v0.3.0

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

NewTracerChild creates a tracer from a tracer.

func (*Tracer) Read added in v0.3.0

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 added in v0.3.0

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 added in v0.3.0

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 added in v0.3.0

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 added in v0.3.0

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 added in v0.3.0

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

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

Jump to

Keyboard shortcuts

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