github.com/cloudwego/iasm@v0.2.0/repl/display.go (about) 1 // 2 // Copyright 2024 CloudWeGo Authors 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 package repl 18 19 import ( 20 `fmt` 21 `strings` 22 `unicode` 23 ) 24 25 func vector(v []byte, indent int) string { 26 n := len(v) 27 m := make([]string, 0, len(v)) 28 29 /* convert each element */ 30 for i := 0; i < n; i++ { 31 if i == 0 || (i & 15) != 0 { 32 m = append(m, fmt.Sprintf("0x%02x", v[n - i - 1])) 33 } else { 34 m = append(m, fmt.Sprintf("\n%s0x%02x", strings.Repeat(" ", indent + 1), v[n - i - 1])) 35 } 36 } 37 38 /* join them together */ 39 return fmt.Sprintf( 40 "{%s}", 41 strings.Join(m, ", "), 42 ) 43 } 44 45 func display(v byte) string { 46 if !unicode.IsPrint(rune(v)) { 47 return "." 48 } else { 49 return string(v) 50 } 51 } 52 53 func vecdiff(v0 []byte, v1 []byte, indent int) string { 54 return vector(v0, indent) + strings.Repeat(" ", indent - 2) + "->" + vector(v1, indent) 55 } 56 57 func asmdump(m []byte, pos uintptr, src string) string { 58 row := -1 59 ret := []string(nil) 60 61 /* must have at least 1 byte */ 62 if len(m) == 0 { 63 panic("empty instruction bytes") 64 } 65 66 /* convert all the bytes */ 67 for i, v := range m { 68 if i % 7 != 0 { 69 ret[row] = ret[row] + fmt.Sprintf(" %02x", v) 70 } else { 71 ret, row = append(ret, fmt.Sprintf("(%#06x) %02x", pos + uintptr(i), v)), row + 1 72 } 73 } 74 75 /* pad the first line if needed */ 76 if n := len(m); n < 7 { 77 ret[0] += strings.Repeat(" ", (7 - n) * 3) 78 } 79 80 /* add the source */ 81 ret[0] += " " + src 82 return strings.Join(ret, "\n") 83 } 84 85 func hexdump(buf []byte, start uintptr) string { 86 off := 0 87 nbs := len(buf) 88 ret := []string(nil) 89 90 /* dump the data, 16-byte loop */ 91 for nbs >= 16 { 92 _ = buf[off + 15] 93 ret = append(ret, fmt.Sprintf("%x:", start + uintptr(off))) 94 ret = append(ret, fmt.Sprintf(" %02x %02x %02x %02x", buf[off + 0], buf[off + 1], buf[off + 2], buf[off + 3])) 95 ret = append(ret, fmt.Sprintf(" %02x %02x %02x %02x", buf[off + 4], buf[off + 5], buf[off + 6], buf[off + 7]), " ") 96 ret = append(ret, fmt.Sprintf(" %02x %02x %02x %02x", buf[off + 8], buf[off + 9], buf[off + 10], buf[off + 11])) 97 ret = append(ret, fmt.Sprintf(" %02x %02x %02x %02x", buf[off + 12], buf[off + 13], buf[off + 14], buf[off + 15]), " ") 98 99 /* print the 16 characters */ 100 for i := 0; i < 16; i++ { 101 ret = append(ret, display(buf[off + i])) 102 } 103 104 /* move to the next line */ 105 off = off + 16 106 nbs = nbs - 16 107 ret = append(ret, "\n") 108 } 109 110 /* still have more bytes */ 111 if nbs > 0 { 112 ret = append(ret, fmt.Sprintf("%x:", start + uintptr(off))) 113 } 114 115 /* print the remaining bytes */ 116 for i := 0; i < nbs; i++ { 117 if i != 7 { 118 ret = append(ret, fmt.Sprintf(" %02x", buf[off + i])) 119 } else { 120 ret = append(ret, fmt.Sprintf(" %02x ", buf[off + i])) 121 } 122 } 123 124 /* pad the last line */ 125 if nbs > 0 { 126 if nbs < 8 { 127 ret = append(ret, strings.Repeat(" ", (17 - int(nbs)) * 3)) 128 } else { 129 ret = append(ret, strings.Repeat(" ", (17 - int(nbs)) * 3 - 1)) 130 } 131 } 132 133 /* print the last characters */ 134 for i := 0; i < nbs; i++ { 135 ret = append(ret, display(buf[off + i])) 136 } 137 138 /* check the final terminator */ 139 if nbs <= 0 { 140 return strings.Join(ret, "") 141 } else { 142 return strings.Join(append(ret, "\n"), "") 143 } 144 }