forked from u-root/u-root
/
print.go
134 lines (112 loc) · 3.54 KB
/
print.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2018 Google LLC.
//
// 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.
//
// Changes are Copyright 2018 the u-root Authors.
package strace
import (
"fmt"
"strings"
"golang.org/x/sys/unix"
)
// DefaultLogMaximumSize is the default LogMaximumSize.
const DefaultLogMaximumSize = 1024
// LogMaximumSize determines the maximum display size for data blobs (read,
// write, etc.).
var LogMaximumSize uint = DefaultLogMaximumSize
// 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.
var EventMaximumSize uint
func dump(t *Tracer, addr Addr, size uint, maximumBlobSize uint) string {
origSize := size
if size > maximumBlobSize {
size = maximumBlobSize
}
if size == 0 {
return ""
}
b := make([]byte, size)
amt, err := t.Read(addr, b)
if err != nil {
return fmt.Sprintf("%#x (error decoding string: %s)", addr, err)
}
dot := ""
if uint(amt) < origSize {
// ... if we truncated the dump.
dot = "..."
}
return fmt.Sprintf("%#x %q%s", addr, b[:amt], dot)
}
func iovecs(t *Tracer, addr Addr, iovcnt int, printContent bool, maxBytes uint64) string {
if iovcnt < 0 || iovcnt > 0x10 /*unix.MSG_MAXIOVLEN*/ {
return fmt.Sprintf("%#x (error decoding iovecs: invalid iovcnt)", addr)
}
v := make([]iovec, iovcnt)
_, err := t.Read(addr, v)
if err != nil {
return fmt.Sprintf("%#x (error decoding iovecs: %v)", addr, err)
}
var totalBytes uint64
var truncated bool
iovs := make([]string, iovcnt)
for i, vv := range v {
if vv.S == 0 || !printContent {
iovs[i] = fmt.Sprintf("{base=%#x, len=%d}", vv.P, vv.S)
continue
}
size := uint64(vv.S)
if truncated || totalBytes+size > maxBytes {
truncated = true
size = maxBytes - totalBytes
} else {
totalBytes += uint64(vv.S)
}
b := make([]byte, size)
amt, err := t.Read(vv.P, b)
if err != nil {
iovs[i] = fmt.Sprintf("{base=%#x, len=%d, %q..., error decoding string: %v}", vv.P, vv.S, b[:amt], err)
continue
}
dot := ""
if truncated {
// Indicate truncation.
dot = "..."
}
iovs[i] = fmt.Sprintf("{base=%#x, len=%d, %q%s}", vv.P, vv.S, b[:amt], dot)
}
return fmt.Sprintf("%#x %s", addr, strings.Join(iovs, ", "))
}
func fdpair(t *Tracer, addr Addr) string {
var fds [2]int32
_, err := t.Read(addr, &fds)
if err != nil {
return fmt.Sprintf("%#x (error decoding fds: %s)", addr, err)
}
return fmt.Sprintf("%#x [%d %d]", addr, fds[0], fds[1])
}
func uname(t *Tracer, addr Addr) string {
var u unix.Utsname
if _, err := t.Read(addr, &u); err != nil {
return fmt.Sprintf("%#x (error decoding utsname: %s)", addr, err)
}
return fmt.Sprintf("%#x %s", addr, u)
}
// AlignUp rounds a length up to an alignment. align must be a power of 2.
func AlignUp(length int, align uint) int {
return (length + int(align) - 1) & ^(int(align) - 1)
}
// AlignDown rounds a down to an alignment. align must be a power of 2.
func AlignDown(length int, align uint) int {
return length & ^(int(align) - 1)
}