golang.org/x/arch@v0.17.0/x86/xeddata/object.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package xeddata 6 7 import ( 8 "encoding/json" 9 "strings" 10 ) 11 12 // An Object is a single "dec/enc-instruction" XED object from datafiles. 13 // 14 // Field names and their comments are borrowed from Intel XED 15 // engineering notes (see "$XED/misc/engineering-notes.txt"). 16 // 17 // Field values are always trimmed (i.e. no leading/trailing whitespace). 18 // 19 // Missing optional members are expressed with an empty string. 20 // 21 // Object contains multiple Inst elements that represent concrete 22 // instruction with encoding pattern and operands description. 23 type Object struct { 24 // Pos is the file position of the start of this object. 25 Pos Pos 26 27 // Iclass is instruction class name (opcode). 28 // Iclass alone is not enough to uniquely identify machine instructions. 29 // Example: "PSRLW". 30 Iclass string 31 32 // Disasm is substituted name when a simple conversion 33 // from iclass is inappropriate. 34 // Never combined with DisasmIntel or DisasmATTSV. 35 // Example: "syscall". 36 // 37 // Optional. 38 Disasm string 39 40 // DisasmIntel is like Disasm, but with Intel syntax. 41 // If present, usually comes with DisasmATTSV. 42 // Example: "jmp far". 43 // 44 // Optional. 45 DisasmIntel string 46 47 // DisasmATTSV is like Disasm, but with AT&T/SysV syntax. 48 // If present, usually comes with DisasmIntel. 49 // Example: "ljmp". 50 // 51 // Optional. 52 DisasmATTSV string 53 54 // Attributes describes name set for bits in the binary attributes field. 55 // Example: "NOP X87_CONTROL NOTSX". 56 // 57 // Optional. If not present, zero attribute set is implied. 58 Attributes string 59 60 // Uname is unique name used for deleting / replacing instructions. 61 // 62 // Optional. Provided for completeness, mostly useful for XED internal usage. 63 Uname string 64 65 // CPL is instruction current privilege level restriction. 66 // Can have value of "0" or "3". 67 CPL string 68 69 // Category is an ad-hoc categorization of instructions. 70 // Example: "SEMAPHORE". 71 Category string 72 73 // Extension is an ad-hoc grouping of instructions. 74 // If no ISASet is specified, this is used instead. 75 // Example: "3DNOW" 76 Extension string 77 78 // Exceptions is an exception set name. 79 // Example: "SSE_TYPE_7". 80 // 81 // Optional. Empty exception category generally means that 82 // instruction generates no exceptions. 83 Exceptions string 84 85 // ISASet is a name for the group of instructions that 86 // introduced this feature. 87 // Example: "I286PROTECTED". 88 // 89 // Older objects only defined Extension field. 90 // Newer objects may contain both Extension and ISASet fields. 91 // For some objects Extension==ISASet. 92 // Both fields are required to do precise CPUID-like decisions. 93 // 94 // Optional. 95 ISASet string 96 97 // Flags describes read/written flag bit values. 98 // Example: "MUST [ of-u sf-u af-u pf-u cf-mod ]". 99 // 100 // Optional. If not present, no flags are neither read nor written. 101 Flags string 102 103 // A hopefully useful comment. 104 // 105 // Optional. 106 Comment string 107 108 // The object revision. 109 // 110 // Optional. 111 Version string 112 113 // RealOpcode marks unstable (not in SDM yet) instructions with "N". 114 // Normally, always "Y" or not present at all. 115 // 116 // Optional. 117 RealOpcode string 118 119 // Insts are concrete instruction templates that are derived from containing Object. 120 // Inst contains fields PATTERN, OPERANDS, IFORM in enc/dec instruction. 121 Insts []*Inst 122 } 123 124 // Inst represents a single instruction template. 125 // 126 // Some templates contain expandable (macro) pattern and operands 127 // which tells that there are more than one real instructions 128 // that are expressed by the template. 129 type Inst struct { 130 // Object that contains properties that are shared with multiple 131 // Inst objects. 132 *Object 133 134 // Pos is the file position of this Inst's PATTERN. 135 Pos Pos 136 137 // Index is the position inside XED object. 138 // Object.Insts[Index] returns this inst. 139 Index int 140 141 // Pattern is the sequence of bits and nonterminals used to 142 // decode/encode an instruction. 143 // Example: "0x0F 0x28 no_refining_prefix MOD[0b11] MOD=3 REG[rrr] RM[nnn]". 144 Pattern string 145 146 // Operands are instruction arguments, typicall registers, 147 // memory operands and pseudo-resources. Separated by space. 148 // Example: "MEM0:rcw:b REG0=GPR8_R():r REG1=XED_REG_AL:rcw:SUPP". 149 Operands string 150 151 // Iform is a name for the pattern that starts with the 152 // iclass and bakes in the operands. If omitted, XED 153 // tries to generate one. We often add custom suffixes 154 // to these to disambiguate certain combinations. 155 // Example: "MOVAPS_XMMps_XMMps_0F28". 156 // 157 // Optional. 158 Iform string 159 } 160 161 // Opcode returns instruction name or empty string, 162 // if appropriate Object fields are not initialized. 163 func (o *Object) Opcode() string { 164 switch { 165 case o.Iclass != "": 166 return o.Iclass 167 case o.Disasm != "": 168 return o.Disasm 169 case o.DisasmIntel != "": 170 return o.DisasmIntel 171 case o.DisasmATTSV != "": 172 return o.DisasmATTSV 173 case o.Uname != "": 174 return o.Uname 175 } 176 return "" 177 } 178 179 // HasAttribute checks that o has attribute with specified name. 180 // Note that check is done at "word" level, substring names will not match. 181 func (o *Object) HasAttribute(name string) bool { 182 return containsWord(o.Attributes, name) 183 } 184 185 // String returns pretty-printed inst representation. 186 // 187 // Outputs valid JSON string. This property is 188 // not guaranteed to be preserved. 189 func (inst *Inst) String() string { 190 // Do not use direct inst marshalling to achieve 191 // flat object printed representation. 192 // Map is avoided to ensure consistent props order. 193 type flatObject struct { 194 Iclass string 195 Disasm string `json:",omitempty"` 196 DisasmIntel string `json:",omitempty"` 197 DisasmATTSV string `json:",omitempty"` 198 Attributes string `json:",omitempty"` 199 Uname string `json:",omitempty"` 200 CPL string 201 Category string 202 Extension string 203 Exceptions string `json:",omitempty"` 204 ISASet string `json:",omitempty"` 205 Flags string `json:",omitempty"` 206 Comment string `json:",omitempty"` 207 Version string `json:",omitempty"` 208 RealOpcode string `json:",omitempty"` 209 Pattern string 210 Operands string 211 Iform string `json:",omitempty"` 212 } 213 214 flat := flatObject{ 215 Iclass: inst.Iclass, 216 Disasm: inst.Disasm, 217 DisasmIntel: inst.DisasmIntel, 218 DisasmATTSV: inst.DisasmATTSV, 219 Attributes: inst.Attributes, 220 Uname: inst.Uname, 221 CPL: inst.CPL, 222 Category: inst.Category, 223 Extension: inst.Extension, 224 Exceptions: inst.Exceptions, 225 ISASet: inst.ISASet, 226 Flags: inst.Flags, 227 Comment: inst.Comment, 228 Version: inst.Version, 229 RealOpcode: inst.RealOpcode, 230 Pattern: inst.Pattern, 231 Operands: inst.Operands, 232 Iform: inst.Iform, 233 } 234 235 b, err := json.MarshalIndent(flat, "", " ") 236 if err != nil { 237 panic(err) 238 } 239 return string(b) 240 } 241 242 // ExpandStates returns a copy of s where all state macros 243 // are expanded. 244 // This requires db "states" to be loaded. 245 func ExpandStates(db *Database, s string) string { 246 substs := db.states 247 parts := strings.Fields(s) 248 for i := range parts { 249 if repl := substs[parts[i]]; repl != "" { 250 parts[i] = repl 251 } 252 } 253 return strings.Join(parts, " ") 254 } 255 256 // containsWord searches for whole word match in s. 257 func containsWord(s, word string) bool { 258 i := strings.Index(s, word) 259 if i == -1 { 260 return false 261 } 262 leftOK := i == 0 || 263 (s[i-1] == ' ') 264 rigthOK := i+len(word) == len(s) || 265 (s[i+len(word)] == ' ') 266 return leftOK && rigthOK 267 }