github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/strace/print.go (about) 1 // Copyright 2018 Google LLC. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // Changes are Copyright 2018 the u-root Authors. 16 17 package strace 18 19 import ( 20 "bytes" 21 "fmt" 22 "strings" 23 24 "golang.org/x/sys/unix" 25 ) 26 27 // DefaultLogMaximumSize is the default LogMaximumSize. 28 const DefaultLogMaximumSize = 1024 29 30 // LogMaximumSize determines the maximum display size for data blobs (read, 31 // write, etc.). 32 var LogMaximumSize uint = DefaultLogMaximumSize 33 34 // EventMaximumSize determines the maximum size for data blobs (read, write, 35 // etc.) sent over the event channel. Default is 0 because most clients cannot 36 // do anything useful with binary text dump of byte array arguments. 37 var EventMaximumSize uint 38 39 func dump(t Task, addr Addr, size uint, maximumBlobSize uint) string { 40 origSize := size 41 if size > maximumBlobSize { 42 size = maximumBlobSize 43 } 44 if size == 0 { 45 return "" 46 } 47 48 b := make([]byte, size) 49 amt, err := t.Read(addr, b) 50 if err != nil { 51 return fmt.Sprintf("%#x (error decoding string: %s)", addr, err) 52 } 53 54 dot := "" 55 if uint(amt) < origSize { 56 // ... if we truncated the dump. 57 dot = "..." 58 } 59 60 return fmt.Sprintf("%#x %q%s", addr, b[:amt], dot) 61 } 62 63 func iovecs(t Task, addr Addr, iovcnt int, printContent bool, maxBytes uint64) string { 64 if iovcnt < 0 || iovcnt > 0x10 /*unix.MSG_MAXIOVLEN*/ { 65 return fmt.Sprintf("%#x (error decoding iovecs: invalid iovcnt)", addr) 66 } 67 v := make([]iovec, iovcnt) 68 _, err := t.Read(addr, v) 69 if err != nil { 70 return fmt.Sprintf("%#x (error decoding iovecs: %v)", addr, err) 71 } 72 73 var totalBytes uint64 74 var truncated bool 75 iovs := make([]string, iovcnt) 76 for i, vv := range v { 77 if vv.S == 0 || !printContent { 78 iovs[i] = fmt.Sprintf("{base=%#x, len=%d}", vv.P, vv.S) 79 continue 80 } 81 82 size := uint64(vv.S) 83 if truncated || totalBytes+size > maxBytes { 84 truncated = true 85 size = maxBytes - totalBytes 86 } else { 87 totalBytes += uint64(vv.S) 88 } 89 90 b := make([]byte, size) 91 amt, err := t.Read(vv.P, b) 92 if err != nil { 93 iovs[i] = fmt.Sprintf("{base=%#x, len=%d, %q..., error decoding string: %v}", vv.P, vv.S, b[:amt], err) 94 continue 95 } 96 97 dot := "" 98 if truncated { 99 // Indicate truncation. 100 dot = "..." 101 } 102 iovs[i] = fmt.Sprintf("{base=%#x, len=%d, %q%s}", vv.P, vv.S, b[:amt], dot) 103 } 104 105 return fmt.Sprintf("%#x %s", addr, strings.Join(iovs, ", ")) 106 } 107 108 func fdpair(t Task, addr Addr) string { 109 var fds [2]int32 110 _, err := t.Read(addr, &fds) 111 if err != nil { 112 return fmt.Sprintf("%#x (error decoding fds: %s)", addr, err) 113 } 114 115 return fmt.Sprintf("%#x [%d %d]", addr, fds[0], fds[1]) 116 } 117 118 type SaneUtsname struct { 119 Sysname string 120 Nodename string 121 Release string 122 Version string 123 Machine string 124 Domainname string 125 } 126 127 func SaneUname(u unix.Utsname) SaneUtsname { 128 return SaneUtsname{ 129 Sysname: convertUname(u.Sysname), 130 Nodename: convertUname(u.Nodename), 131 Release: convertUname(u.Release), 132 Version: convertUname(u.Version), 133 Machine: convertUname(u.Machine), 134 Domainname: convertUname(u.Domainname), 135 } 136 } 137 138 func convertUname(s [65]uint8) string { 139 return string(bytes.TrimRight(s[:], "\x00")) 140 } 141 142 func uname(t Task, addr Addr) string { 143 var u unix.Utsname 144 if _, err := t.Read(addr, &u); err != nil { 145 return fmt.Sprintf("%#x (error decoding utsname: %s)", addr, err) 146 } 147 148 return fmt.Sprintf("%#x %#v", addr, SaneUname(u)) 149 } 150 151 // alignUp rounds a length up to an alignment. align must be a power of 2. 152 func alignUp(length int, align uint) int { 153 return (length + int(align) - 1) & ^(int(align) - 1) 154 } 155 156 // alignDown rounds a down to an alignment. align must be a power of 2. 157 func alignDown(length int, align uint) int { 158 return length & ^(int(align) - 1) 159 }