Changeset 99236 in vbox
- Timestamp:
- Mar 30, 2023 3:30:26 PM (20 months ago)
- Location:
- trunk/src/VBox/Disassembler
- Files:
-
- 4 edited
- 1 copied
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Disassembler/Disasm.cpp
r99220 r99236 38 38 39 39 40 /********************************************************************************************************************************* 41 * Defined Constants And Macros * 42 *********************************************************************************************************************************/ 43 44 45 /********************************************************************************************************************************* 46 * Internal Functions * 47 *********************************************************************************************************************************/ 48 49 /** 50 * @interface_method_impl{FNDISREADBYTES, The default byte reader callber.} 51 */ 52 static DECLCALLBACK(int) disReadBytesDefault(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead) 53 { 54 #if 0 /*def IN_RING0 - why? */ 55 RT_NOREF_PV(cbMinRead); 56 AssertMsgFailed(("disReadWord with no read callback in ring 0!!\n")); 57 RT_BZERO(&pDis->u.abInstr[offInstr], cbMaxRead); 58 pDis->cbCachedInstr = offInstr + cbMaxRead; 59 return VERR_DIS_NO_READ_CALLBACK; 60 #else 61 uint8_t const *pbSrc = (uint8_t const *)(uintptr_t)pDis->uInstrAddr + offInstr; 62 size_t cbLeftOnPage = (uintptr_t)pbSrc & PAGE_OFFSET_MASK; 63 uint8_t cbToRead = cbLeftOnPage >= cbMaxRead 64 ? cbMaxRead 65 : cbLeftOnPage <= cbMinRead 66 ? cbMinRead 67 : (uint8_t)cbLeftOnPage; 68 memcpy(&pDis->u.abInstr[offInstr], pbSrc, cbToRead); 69 pDis->cbCachedInstr = offInstr + cbToRead; 70 return VINF_SUCCESS; 71 #endif 72 } 73 74 75 /** 76 * Read more bytes into the DISSTATE::u.abInstr buffer, advance 77 * DISSTATE::cbCachedInstr. 78 * 79 * Will set DISSTATE::rc on failure, but still advance cbCachedInstr. 80 * 81 * The caller shall fend off reads beyond the DISSTATE::u.abInstr buffer. 82 * 83 * @param pDis The disassembler state. 84 * @param offInstr The offset of the read request. 85 * @param cbMin The size of the read request that needs to be 86 * satisfied. 87 */ 88 DECLHIDDEN(void) disReadMore(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMin) 89 { 90 Assert(cbMin + offInstr <= sizeof(pDis->u.abInstr)); 91 92 /* 93 * Adjust the incoming request to not overlap with bytes that has already 94 * been read and to make sure we don't leave unread gaps. 95 */ 96 if (offInstr < pDis->cbCachedInstr) 97 { 98 Assert(offInstr + cbMin > pDis->cbCachedInstr); 99 cbMin -= pDis->cbCachedInstr - offInstr; 100 offInstr = pDis->cbCachedInstr; 101 } 102 else if (offInstr > pDis->cbCachedInstr) 103 { 104 cbMin += offInstr - pDis->cbCachedInstr; 105 offInstr = pDis->cbCachedInstr; 106 } 107 108 /* 109 * Do the read. 110 * (No need to zero anything on failure as u.abInstr is already zeroed by the 111 * DISInstrEx API.) 112 */ 113 int rc = pDis->pfnReadBytes(pDis, offInstr, cbMin, sizeof(pDis->u.abInstr) - offInstr); 114 if (RT_SUCCESS(rc)) 115 { 116 Assert(pDis->cbCachedInstr >= offInstr + cbMin); 117 Assert(pDis->cbCachedInstr <= sizeof(pDis->u.abInstr)); 118 } 119 else 120 { 121 Log(("disReadMore failed with rc=%Rrc!!\n", rc)); 122 pDis->rc = rc; 123 } 124 } 125 126 127 /** 128 * Function for handling a 8-bit cache miss. 129 * 130 * @returns The requested byte. 131 * @param pDis The disassembler state. 132 * @param offInstr The offset of the byte relative to the 133 * instruction. 134 */ 135 DECLHIDDEN(uint8_t) disReadByteSlow(PDISSTATE pDis, size_t offInstr) 136 { 137 if (RT_LIKELY(offInstr < DIS_MAX_INSTR_LENGTH)) 138 { 139 disReadMore(pDis, (uint8_t)offInstr, 1); 140 return pDis->u.abInstr[offInstr]; 141 } 142 143 Log(("disReadByte: too long instruction...\n")); 144 pDis->rc = VERR_DIS_TOO_LONG_INSTR; 145 ssize_t cbLeft = (ssize_t)(sizeof(pDis->u.abInstr) - offInstr); 146 if (cbLeft > 0) 147 return pDis->u.abInstr[offInstr]; 148 return 0; 149 } 150 151 152 /** 153 * Function for handling a 16-bit cache miss. 154 * 155 * @returns The requested word. 156 * @param pDis The disassembler state. 157 * @param offInstr The offset of the word relative to the 158 * instruction. 159 */ 160 DECLHIDDEN(uint16_t) disReadWordSlow(PDISSTATE pDis, size_t offInstr) 161 { 162 if (RT_LIKELY(offInstr + 2 <= DIS_MAX_INSTR_LENGTH)) 163 { 164 disReadMore(pDis, (uint8_t)offInstr, 2); 165 #ifdef DIS_HOST_UNALIGNED_ACCESS_OK 166 return *(uint16_t const *)&pDis->u.abInstr[offInstr]; 167 #else 168 return RT_MAKE_U16(pDis->u.abInstr[offInstr], pDis->u.abInstr[offInstr + 1]); 169 #endif 170 } 171 172 Log(("disReadWord: too long instruction...\n")); 173 pDis->rc = VERR_DIS_TOO_LONG_INSTR; 174 ssize_t cbLeft = (ssize_t)(sizeof(pDis->u.abInstr) - offInstr); 175 switch (cbLeft) 176 { 177 case 1: 178 return pDis->u.abInstr[offInstr]; 179 default: 180 if (cbLeft >= 2) 181 return RT_MAKE_U16(pDis->u.abInstr[offInstr], pDis->u.abInstr[offInstr + 1]); 182 return 0; 183 } 184 } 185 186 187 /** 188 * Function for handling a 32-bit cache miss. 189 * 190 * @returns The requested dword. 191 * @param pDis The disassembler state. 192 * @param offInstr The offset of the dword relative to the 193 * instruction. 194 */ 195 DECLHIDDEN(uint32_t) disReadDWordSlow(PDISSTATE pDis, size_t offInstr) 196 { 197 if (RT_LIKELY(offInstr + 4 <= DIS_MAX_INSTR_LENGTH)) 198 { 199 disReadMore(pDis, (uint8_t)offInstr, 4); 200 #ifdef DIS_HOST_UNALIGNED_ACCESS_OK 201 return *(uint32_t const *)&pDis->u.abInstr[offInstr]; 202 #else 203 return RT_MAKE_U32_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1], 204 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3]); 205 #endif 206 } 207 208 Log(("disReadDWord: too long instruction...\n")); 209 pDis->rc = VERR_DIS_TOO_LONG_INSTR; 210 ssize_t cbLeft = (ssize_t)(sizeof(pDis->u.abInstr) - offInstr); 211 switch (cbLeft) 212 { 213 case 1: 214 return RT_MAKE_U32_FROM_U8(pDis->u.abInstr[offInstr], 0, 0, 0); 215 case 2: 216 return RT_MAKE_U32_FROM_U8(pDis->u.abInstr[offInstr], pDis->u.abInstr[offInstr + 1], 0, 0); 217 case 3: 218 return RT_MAKE_U32_FROM_U8(pDis->u.abInstr[offInstr], pDis->u.abInstr[offInstr + 1], pDis->u.abInstr[offInstr + 2], 0); 219 default: 220 if (cbLeft >= 4) 221 return RT_MAKE_U32_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1], 222 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3]); 223 return 0; 224 } 225 } 226 227 228 /** 229 * Function for handling a 64-bit cache miss. 230 * 231 * @returns The requested qword. 232 * @param pDis The disassembler state. 233 * @param offInstr The offset of the qword relative to the 234 * instruction. 235 */ 236 DECLHIDDEN(uint64_t) disReadQWordSlow(PDISSTATE pDis, size_t offInstr) 237 { 238 if (RT_LIKELY(offInstr + 8 <= DIS_MAX_INSTR_LENGTH)) 239 { 240 disReadMore(pDis, (uint8_t)offInstr, 8); 241 #ifdef DIS_HOST_UNALIGNED_ACCESS_OK 242 return *(uint64_t const *)&pDis->u.abInstr[offInstr]; 243 #else 244 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1], 245 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3], 246 pDis->u.abInstr[offInstr + 4], pDis->u.abInstr[offInstr + 5], 247 pDis->u.abInstr[offInstr + 6], pDis->u.abInstr[offInstr + 7]); 248 #endif 249 } 250 251 Log(("disReadQWord: too long instruction...\n")); 252 pDis->rc = VERR_DIS_TOO_LONG_INSTR; 253 ssize_t cbLeft = (ssize_t)(sizeof(pDis->u.abInstr) - offInstr); 254 switch (cbLeft) 255 { 256 case 1: 257 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr], 0, 0, 0, 0, 0, 0, 0); 258 case 2: 259 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr], pDis->u.abInstr[offInstr + 1], 0, 0, 0, 0, 0, 0); 260 case 3: 261 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1], 262 pDis->u.abInstr[offInstr + 2], 0, 0, 0, 0, 0); 263 case 4: 264 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1], 265 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3], 266 0, 0, 0, 0); 267 case 5: 268 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1], 269 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3], 270 pDis->u.abInstr[offInstr + 4], 0, 0, 0); 271 case 6: 272 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1], 273 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3], 274 pDis->u.abInstr[offInstr + 4], pDis->u.abInstr[offInstr + 5], 275 0, 0); 276 case 7: 277 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1], 278 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3], 279 pDis->u.abInstr[offInstr + 4], pDis->u.abInstr[offInstr + 5], 280 pDis->u.abInstr[offInstr + 6], 0); 281 default: 282 if (cbLeft >= 8) 283 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1], 284 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3], 285 pDis->u.abInstr[offInstr + 4], pDis->u.abInstr[offInstr + 5], 286 pDis->u.abInstr[offInstr + 6], pDis->u.abInstr[offInstr + 7]); 287 return 0; 288 } 289 } 290 291 292 /** 293 * Inlined worker that initializes the disassembler state. 294 * 295 * @returns The primary opcode map to use. 296 * @param pDis The disassembler state. 297 * @param uInstrAddr The instruction address. 298 * @param enmCpuMode The CPU mode. 299 * @param fFilter The instruction filter settings. 300 * @param pfnReadBytes The byte reader, can be NULL. 301 * @param pvUser The user data for the reader. 302 */ 303 DECL_FORCE_INLINE(PCDISOPCODE) 304 disInitializeState(PDISSTATE pDis, RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter, 305 PFNDISREADBYTES pfnReadBytes, void *pvUser) 306 { 307 RT_ZERO(*pDis); 308 309 pDis->rc = VINF_SUCCESS; 310 pDis->uInstrAddr = uInstrAddr; 311 pDis->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault; 312 pDis->pvUser = pvUser; 313 pDis->uCpuMode = (uint8_t)enmCpuMode; 314 return disInitializeStateX86(pDis, enmCpuMode, fFilter); 315 } 316 317 318 /** 319 * Disassembles on instruction, details in @a pDis and length in @a pcbInstr. 320 * 321 * @returns VBox status code. 322 * @param uInstrAddr Address of the instruction to decode. What this means 323 * is left to the pfnReadBytes function. 324 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT. 325 * @param pfnReadBytes Callback for reading instruction bytes. 326 * @param fFilter Instruction type filter. 327 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.) 328 * @param pDis Pointer to disassembler state (output). 329 * @param pcbInstr Where to store the size of the instruction. (This 330 * is also stored in PDISSTATE::cbInstr.) Optional. 331 */ 332 DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter, 333 PFNDISREADBYTES pfnReadBytes, void *pvUser, 334 PDISSTATE pDis, uint32_t *pcbInstr) 335 { 336 337 PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser); 338 disPrefetchBytes(pDis); 339 return disInstrWorkerX86(pDis, paOneByteMap, pcbInstr); 340 } 341 342 343 /** 344 * Disassembles on instruction partially or fully from prefetched bytes, details 345 * in @a pDis and length in @a pcbInstr. 346 * 347 * @returns VBox status code. 348 * @param uInstrAddr Address of the instruction to decode. What this means 349 * is left to the pfnReadBytes function. 350 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT. 351 * @param pvPrefetched Pointer to the prefetched bytes. 352 * @param cbPrefetched The number of valid bytes pointed to by @a 353 * pbPrefetched. 354 * @param pfnReadBytes Callback for reading instruction bytes. 355 * @param fFilter Instruction type filter. 356 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.) 357 * @param pDis Pointer to disassembler state (output). 358 * @param pcbInstr Where to store the size of the instruction. (This 359 * is also stored in PDISSTATE::cbInstr.) Optional. 360 */ 361 DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter, 362 void const *pvPrefetched, size_t cbPretched, 363 PFNDISREADBYTES pfnReadBytes, void *pvUser, 364 PDISSTATE pDis, uint32_t *pcbInstr) 365 { 366 PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser); 367 368 if (!cbPretched) 369 disPrefetchBytes(pDis); 370 else 371 { 372 if (cbPretched >= sizeof(pDis->u.abInstr)) 373 { 374 memcpy(pDis->u.abInstr, pvPrefetched, sizeof(pDis->u.abInstr)); 375 pDis->cbCachedInstr = (uint8_t)sizeof(pDis->u.abInstr); 376 } 377 else 378 { 379 memcpy(pDis->u.abInstr, pvPrefetched, cbPretched); 380 pDis->cbCachedInstr = (uint8_t)cbPretched; 381 } 382 } 383 384 return disInstrWorkerX86(pDis, paOneByteMap, pcbInstr); 385 } 386 387 388 /** 389 * Parses one guest instruction. 390 * 391 * The result is found in pDis and pcbInstr. 392 * 393 * @returns VBox status code. 394 * @param uInstrAddr Address of the instruction to decode. What this means 395 * is left to the pfnReadBytes function. 396 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT. 397 * @param pfnReadBytes Callback for reading instruction bytes. 398 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.) 399 * @param pDis Pointer to disassembler state (output). 400 * @param pcbInstr Where to store the size of the instruction. 401 * NULL is allowed. This is also stored in 402 * PDISSTATE::cbInstr. 403 */ 404 DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser, 405 PDISSTATE pDis, uint32_t *pcbInstr) 406 { 407 return DISInstrEx(uInstrAddr, enmCpuMode, DISOPTYPE_ALL, pfnReadBytes, pvUser, pDis, pcbInstr); 408 } 409 410 411 /** 412 * Parses one guest instruction. 413 * 414 * The result is found in pDis and pcbInstr. 415 * 416 * @returns VBox status code. 417 * @param pvInstr Address of the instruction to decode. This is a 418 * real address in the current context that can be 419 * accessed without faulting. (Consider 420 * DISInstrWithReader if this isn't the case.) 421 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT. 422 * @param pfnReadBytes Callback for reading instruction bytes. 423 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.) 424 * @param pDis Pointer to disassembler state (output). 425 * @param pcbInstr Where to store the size of the instruction. 426 * NULL is allowed. This is also stored in 427 * PDISSTATE::cbInstr. 428 */ 429 DISDECL(int) DISInstr(const void *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr) 430 { 431 return DISInstrEx((uintptr_t)pvInstr, enmCpuMode, DISOPTYPE_ALL, NULL /*pfnReadBytes*/, NULL /*pvUser*/, pDis, pcbInstr); 432 } 433 434 435 #ifndef DIS_CORE_ONLY 40 436 /** 41 437 * Disassembles one instruction … … 58 454 pDis, pcbInstr, pszOutput, cbOutput); 59 455 } 456 60 457 61 458 /** … … 84 481 } 85 482 483 86 484 /** 87 485 * Disassembles one instruction; only fully disassembly an instruction if it matches the filter criteria … … 123 521 return rc; 124 522 } 125 523 #endif /* DIS_CORE_ONLY */ 524 -
trunk/src/VBox/Disassembler/DisasmCore-x86-amd64.cpp
r99235 r99236 39 39 #include <iprt/string.h> 40 40 #include <iprt/stdarg.h> 41 #include "DisasmInternal .h"41 #include "DisasmInternal-x86-amd64.h" 42 42 43 43 … … 45 45 * Defined Constants And Macros * 46 46 *********************************************************************************************************************************/ 47 /** This must be less or equal to DISSTATE::u.abInstr.48 * See Vol3A/Table 6-2 and Vol3B/Section22.25 for instance. */49 #define DIS_MAX_INSTR_LENGTH 1550 51 /** Whether we can do unaligned access. */52 #if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)53 # define DIS_HOST_UNALIGNED_ACCESS_OK54 #endif55 47 56 48 … … 232 224 233 225 234 235 236 237 /********************************************************************************************************************************238 *239 *240 * Read functions for getting the opcode bytes241 *242 *243 ********************************************************************************************************************************/244 245 /**246 * @interface_method_impl{FNDISREADBYTES, The default byte reader callber.}247 */248 static DECLCALLBACK(int) disReadBytesDefault(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)249 {250 #if 0 /*def IN_RING0 - why? */251 RT_NOREF_PV(cbMinRead);252 AssertMsgFailed(("disReadWord with no read callback in ring 0!!\n"));253 RT_BZERO(&pDis->u.abInstr[offInstr], cbMaxRead);254 pDis->cbCachedInstr = offInstr + cbMaxRead;255 return VERR_DIS_NO_READ_CALLBACK;256 #else257 uint8_t const *pbSrc = (uint8_t const *)(uintptr_t)pDis->uInstrAddr + offInstr;258 size_t cbLeftOnPage = (uintptr_t)pbSrc & PAGE_OFFSET_MASK;259 uint8_t cbToRead = cbLeftOnPage >= cbMaxRead260 ? cbMaxRead261 : cbLeftOnPage <= cbMinRead262 ? cbMinRead263 : (uint8_t)cbLeftOnPage;264 memcpy(&pDis->u.abInstr[offInstr], pbSrc, cbToRead);265 pDis->cbCachedInstr = offInstr + cbToRead;266 return VINF_SUCCESS;267 #endif268 }269 270 271 /**272 * Read more bytes into the DISSTATE::u.abInstr buffer, advance273 * DISSTATE::cbCachedInstr.274 *275 * Will set DISSTATE::rc on failure, but still advance cbCachedInstr.276 *277 * The caller shall fend off reads beyond the DISSTATE::u.abInstr buffer.278 *279 * @param pDis The disassembler state.280 * @param offInstr The offset of the read request.281 * @param cbMin The size of the read request that needs to be282 * satisfied.283 */284 DECL_NO_INLINE(static, void) disReadMore(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMin)285 {286 Assert(cbMin + offInstr <= sizeof(pDis->u.abInstr));287 288 /*289 * Adjust the incoming request to not overlap with bytes that has already290 * been read and to make sure we don't leave unread gaps.291 */292 if (offInstr < pDis->cbCachedInstr)293 {294 Assert(offInstr + cbMin > pDis->cbCachedInstr);295 cbMin -= pDis->cbCachedInstr - offInstr;296 offInstr = pDis->cbCachedInstr;297 }298 else if (offInstr > pDis->cbCachedInstr)299 {300 cbMin += offInstr - pDis->cbCachedInstr;301 offInstr = pDis->cbCachedInstr;302 }303 304 /*305 * Do the read.306 * (No need to zero anything on failure as u.abInstr is already zeroed by the307 * DISInstrEx API.)308 */309 int rc = pDis->pfnReadBytes(pDis, offInstr, cbMin, sizeof(pDis->u.abInstr) - offInstr);310 if (RT_SUCCESS(rc))311 {312 Assert(pDis->cbCachedInstr >= offInstr + cbMin);313 Assert(pDis->cbCachedInstr <= sizeof(pDis->u.abInstr));314 }315 else316 {317 Log(("disReadMore failed with rc=%Rrc!!\n", rc));318 pDis->rc = rc;319 }320 }321 322 323 /**324 * Function for handling a 8-bit cache miss.325 *326 * @returns The requested byte.327 * @param pDis The disassembler state.328 * @param offInstr The offset of the byte relative to the329 * instruction.330 */331 DECL_NO_INLINE(static, uint8_t) disReadByteSlow(PDISSTATE pDis, size_t offInstr)332 {333 if (RT_LIKELY(offInstr < DIS_MAX_INSTR_LENGTH))334 {335 disReadMore(pDis, (uint8_t)offInstr, 1);336 return pDis->u.abInstr[offInstr];337 }338 339 Log(("disReadByte: too long instruction...\n"));340 pDis->rc = VERR_DIS_TOO_LONG_INSTR;341 ssize_t cbLeft = (ssize_t)(sizeof(pDis->u.abInstr) - offInstr);342 if (cbLeft > 0)343 return pDis->u.abInstr[offInstr];344 return 0;345 }346 347 348 /**349 * Read a byte (8-bit) instruction.350 *351 * @returns The requested byte.352 * @param pDis The disassembler state.353 * @param uAddress The address.354 */355 DECLINLINE(uint8_t) disReadByte(PDISSTATE pDis, size_t offInstr)356 {357 if (offInstr >= pDis->cbCachedInstr)358 return disReadByteSlow(pDis, offInstr);359 return pDis->u.abInstr[offInstr];360 }361 362 363 /**364 * Function for handling a 16-bit cache miss.365 *366 * @returns The requested word.367 * @param pDis The disassembler state.368 * @param offInstr The offset of the word relative to the369 * instruction.370 */371 DECL_NO_INLINE(static, uint16_t) disReadWordSlow(PDISSTATE pDis, size_t offInstr)372 {373 if (RT_LIKELY(offInstr + 2 <= DIS_MAX_INSTR_LENGTH))374 {375 disReadMore(pDis, (uint8_t)offInstr, 2);376 #ifdef DIS_HOST_UNALIGNED_ACCESS_OK377 return *(uint16_t const *)&pDis->u.abInstr[offInstr];378 #else379 return RT_MAKE_U16(pDis->u.abInstr[offInstr], pDis->u.abInstr[offInstr + 1]);380 #endif381 }382 383 Log(("disReadWord: too long instruction...\n"));384 pDis->rc = VERR_DIS_TOO_LONG_INSTR;385 ssize_t cbLeft = (ssize_t)(sizeof(pDis->u.abInstr) - offInstr);386 switch (cbLeft)387 {388 case 1:389 return pDis->u.abInstr[offInstr];390 default:391 if (cbLeft >= 2)392 return RT_MAKE_U16(pDis->u.abInstr[offInstr], pDis->u.abInstr[offInstr + 1]);393 return 0;394 }395 }396 397 398 /**399 * Read a word (16-bit) instruction.400 *401 * @returns The requested word.402 * @param pDis The disassembler state.403 * @param offInstr The offset of the qword relative to the404 * instruction.405 */406 DECLINLINE(uint16_t) disReadWord(PDISSTATE pDis, size_t offInstr)407 {408 if (offInstr + 2 > pDis->cbCachedInstr)409 return disReadWordSlow(pDis, offInstr);410 411 #ifdef DIS_HOST_UNALIGNED_ACCESS_OK412 return *(uint16_t const *)&pDis->u.abInstr[offInstr];413 #else414 return RT_MAKE_U16(pDis->u.abInstr[offInstr], pDis->u.abInstr[offInstr + 1]);415 #endif416 }417 418 419 /**420 * Function for handling a 32-bit cache miss.421 *422 * @returns The requested dword.423 * @param pDis The disassembler state.424 * @param offInstr The offset of the dword relative to the425 * instruction.426 */427 DECL_NO_INLINE(static, uint32_t) disReadDWordSlow(PDISSTATE pDis, size_t offInstr)428 {429 if (RT_LIKELY(offInstr + 4 <= DIS_MAX_INSTR_LENGTH))430 {431 disReadMore(pDis, (uint8_t)offInstr, 4);432 #ifdef DIS_HOST_UNALIGNED_ACCESS_OK433 return *(uint32_t const *)&pDis->u.abInstr[offInstr];434 #else435 return RT_MAKE_U32_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1],436 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3]);437 #endif438 }439 440 Log(("disReadDWord: too long instruction...\n"));441 pDis->rc = VERR_DIS_TOO_LONG_INSTR;442 ssize_t cbLeft = (ssize_t)(sizeof(pDis->u.abInstr) - offInstr);443 switch (cbLeft)444 {445 case 1:446 return RT_MAKE_U32_FROM_U8(pDis->u.abInstr[offInstr], 0, 0, 0);447 case 2:448 return RT_MAKE_U32_FROM_U8(pDis->u.abInstr[offInstr], pDis->u.abInstr[offInstr + 1], 0, 0);449 case 3:450 return RT_MAKE_U32_FROM_U8(pDis->u.abInstr[offInstr], pDis->u.abInstr[offInstr + 1], pDis->u.abInstr[offInstr + 2], 0);451 default:452 if (cbLeft >= 4)453 return RT_MAKE_U32_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1],454 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3]);455 return 0;456 }457 }458 459 460 /**461 * Read a dword (32-bit) instruction.462 *463 * @returns The requested dword.464 * @param pDis The disassembler state.465 * @param offInstr The offset of the qword relative to the466 * instruction.467 */468 DECLINLINE(uint32_t) disReadDWord(PDISSTATE pDis, size_t offInstr)469 {470 if (offInstr + 4 > pDis->cbCachedInstr)471 return disReadDWordSlow(pDis, offInstr);472 473 #ifdef DIS_HOST_UNALIGNED_ACCESS_OK474 return *(uint32_t const *)&pDis->u.abInstr[offInstr];475 #else476 return RT_MAKE_U32_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1],477 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3]);478 #endif479 }480 481 482 /**483 * Function for handling a 64-bit cache miss.484 *485 * @returns The requested qword.486 * @param pDis The disassembler state.487 * @param offInstr The offset of the qword relative to the488 * instruction.489 */490 DECL_NO_INLINE(static, uint64_t) disReadQWordSlow(PDISSTATE pDis, size_t offInstr)491 {492 if (RT_LIKELY(offInstr + 8 <= DIS_MAX_INSTR_LENGTH))493 {494 disReadMore(pDis, (uint8_t)offInstr, 8);495 #ifdef DIS_HOST_UNALIGNED_ACCESS_OK496 return *(uint64_t const *)&pDis->u.abInstr[offInstr];497 #else498 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1],499 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3],500 pDis->u.abInstr[offInstr + 4], pDis->u.abInstr[offInstr + 5],501 pDis->u.abInstr[offInstr + 6], pDis->u.abInstr[offInstr + 7]);502 #endif503 }504 505 Log(("disReadQWord: too long instruction...\n"));506 pDis->rc = VERR_DIS_TOO_LONG_INSTR;507 ssize_t cbLeft = (ssize_t)(sizeof(pDis->u.abInstr) - offInstr);508 switch (cbLeft)509 {510 case 1:511 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr], 0, 0, 0, 0, 0, 0, 0);512 case 2:513 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr], pDis->u.abInstr[offInstr + 1], 0, 0, 0, 0, 0, 0);514 case 3:515 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1],516 pDis->u.abInstr[offInstr + 2], 0, 0, 0, 0, 0);517 case 4:518 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1],519 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3],520 0, 0, 0, 0);521 case 5:522 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1],523 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3],524 pDis->u.abInstr[offInstr + 4], 0, 0, 0);525 case 6:526 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1],527 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3],528 pDis->u.abInstr[offInstr + 4], pDis->u.abInstr[offInstr + 5],529 0, 0);530 case 7:531 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1],532 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3],533 pDis->u.abInstr[offInstr + 4], pDis->u.abInstr[offInstr + 5],534 pDis->u.abInstr[offInstr + 6], 0);535 default:536 if (cbLeft >= 8)537 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1],538 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3],539 pDis->u.abInstr[offInstr + 4], pDis->u.abInstr[offInstr + 5],540 pDis->u.abInstr[offInstr + 6], pDis->u.abInstr[offInstr + 7]);541 return 0;542 }543 }544 545 546 /**547 * Read a qword (64-bit) instruction.548 *549 * @returns The requested qword.550 * @param pDis The disassembler state.551 * @param uAddress The address.552 */553 DECLINLINE(uint64_t) disReadQWord(PDISSTATE pDis, size_t offInstr)554 {555 if (offInstr + 8 > pDis->cbCachedInstr)556 return disReadQWordSlow(pDis, offInstr);557 558 #ifdef DIS_HOST_UNALIGNED_ACCESS_OK559 return *(uint64_t const *)&pDis->u.abInstr[offInstr];560 #else561 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1],562 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3],563 pDis->u.abInstr[offInstr + 4], pDis->u.abInstr[offInstr + 5],564 pDis->u.abInstr[offInstr + 6], pDis->u.abInstr[offInstr + 7]);565 #endif566 }567 568 569 570 226 //***************************************************************************** 571 227 //***************************************************************************** … … 2672 2328 * @param pcbInstr Where to store the instruction size. Can be NULL. 2673 2329 */ 2674 static int disInstrWorker(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr)2330 DECLHIDDEN(int) disInstrWorkerX86(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr) 2675 2331 { 2676 2332 /* … … 2801 2457 * @param pvUser The user data for the reader. 2802 2458 */ 2803 DECL_FORCE_INLINE(PCDISOPCODE) 2804 disInitializeState(PDISSTATE pDis, RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter, 2805 PFNDISREADBYTES pfnReadBytes, void *pvUser) 2459 DECLHIDDEN(PCDISOPCODE) disInitializeStateX86(PDISSTATE pDis, DISCPUMODE enmCpuMode, uint32_t fFilter) 2806 2460 { 2807 2461 RT_ZERO(*pDis); … … 2830 2484 pDis->arch.x86.fFilter = fFilter; 2831 2485 2832 pDis->rc = VINF_SUCCESS;2833 pDis->uInstrAddr = uInstrAddr;2834 pDis->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;2835 pDis->pvUser = pvUser;2836 pDis->uCpuMode = (uint8_t)enmCpuMode;2837 2486 PCDISOPCODE paOneByteMap; 2838 2487 if (enmCpuMode == DISCPUMODE_64BIT) … … 2850 2499 return paOneByteMap; 2851 2500 } 2852 2853 2854 /**2855 * Reads some bytes into the cache.2856 *2857 * While this will set DISSTATE::rc on failure, the caller should disregard2858 * this since that is what would happen if we didn't prefetch bytes prior to the2859 * instruction parsing.2860 *2861 * @param pDis The disassembler state.2862 */2863 DECL_FORCE_INLINE(void) disPrefetchBytes(PDISSTATE pDis)2864 {2865 /*2866 * Read some bytes into the cache. (If this fail we continue as nothing2867 * has gone wrong since this is what would happen if we didn't precharge2868 * the cache here.)2869 */2870 int rc = pDis->pfnReadBytes(pDis, 0, 1, sizeof(pDis->u.abInstr));2871 if (RT_SUCCESS(rc))2872 {2873 Assert(pDis->cbCachedInstr >= 1);2874 Assert(pDis->cbCachedInstr <= sizeof(pDis->u.abInstr));2875 }2876 else2877 {2878 Log(("Initial read failed with rc=%Rrc!!\n", rc));2879 pDis->rc = rc;2880 }2881 }2882 2883 2884 /**2885 * Disassembles on instruction, details in @a pDis and length in @a pcbInstr.2886 *2887 * @returns VBox status code.2888 * @param uInstrAddr Address of the instruction to decode. What this means2889 * is left to the pfnReadBytes function.2890 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.2891 * @param pfnReadBytes Callback for reading instruction bytes.2892 * @param fFilter Instruction type filter.2893 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)2894 * @param pDis Pointer to disassembler state (output).2895 * @param pcbInstr Where to store the size of the instruction. (This2896 * is also stored in PDISSTATE::cbInstr.) Optional.2897 */2898 DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,2899 PFNDISREADBYTES pfnReadBytes, void *pvUser,2900 PDISSTATE pDis, uint32_t *pcbInstr)2901 {2902 2903 PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);2904 disPrefetchBytes(pDis);2905 return disInstrWorker(pDis, paOneByteMap, pcbInstr);2906 }2907 2908 2909 /**2910 * Disassembles on instruction partially or fully from prefetched bytes, details2911 * in @a pDis and length in @a pcbInstr.2912 *2913 * @returns VBox status code.2914 * @param uInstrAddr Address of the instruction to decode. What this means2915 * is left to the pfnReadBytes function.2916 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.2917 * @param pvPrefetched Pointer to the prefetched bytes.2918 * @param cbPrefetched The number of valid bytes pointed to by @a2919 * pbPrefetched.2920 * @param pfnReadBytes Callback for reading instruction bytes.2921 * @param fFilter Instruction type filter.2922 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)2923 * @param pDis Pointer to disassembler state (output).2924 * @param pcbInstr Where to store the size of the instruction. (This2925 * is also stored in PDISSTATE::cbInstr.) Optional.2926 */2927 DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,2928 void const *pvPrefetched, size_t cbPretched,2929 PFNDISREADBYTES pfnReadBytes, void *pvUser,2930 PDISSTATE pDis, uint32_t *pcbInstr)2931 {2932 PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);2933 2934 if (!cbPretched)2935 disPrefetchBytes(pDis);2936 else2937 {2938 if (cbPretched >= sizeof(pDis->u.abInstr))2939 {2940 memcpy(pDis->u.abInstr, pvPrefetched, sizeof(pDis->u.abInstr));2941 pDis->cbCachedInstr = (uint8_t)sizeof(pDis->u.abInstr);2942 }2943 else2944 {2945 memcpy(pDis->u.abInstr, pvPrefetched, cbPretched);2946 pDis->cbCachedInstr = (uint8_t)cbPretched;2947 }2948 }2949 2950 return disInstrWorker(pDis, paOneByteMap, pcbInstr);2951 }2952 2953 2954 2955 /**2956 * Parses one guest instruction.2957 *2958 * The result is found in pDis and pcbInstr.2959 *2960 * @returns VBox status code.2961 * @param uInstrAddr Address of the instruction to decode. What this means2962 * is left to the pfnReadBytes function.2963 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.2964 * @param pfnReadBytes Callback for reading instruction bytes.2965 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)2966 * @param pDis Pointer to disassembler state (output).2967 * @param pcbInstr Where to store the size of the instruction.2968 * NULL is allowed. This is also stored in2969 * PDISSTATE::cbInstr.2970 */2971 DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,2972 PDISSTATE pDis, uint32_t *pcbInstr)2973 {2974 return DISInstrEx(uInstrAddr, enmCpuMode, DISOPTYPE_ALL, pfnReadBytes, pvUser, pDis, pcbInstr);2975 }2976 2977 2978 /**2979 * Parses one guest instruction.2980 *2981 * The result is found in pDis and pcbInstr.2982 *2983 * @returns VBox status code.2984 * @param pvInstr Address of the instruction to decode. This is a2985 * real address in the current context that can be2986 * accessed without faulting. (Consider2987 * DISInstrWithReader if this isn't the case.)2988 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.2989 * @param pfnReadBytes Callback for reading instruction bytes.2990 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)2991 * @param pDis Pointer to disassembler state (output).2992 * @param pcbInstr Where to store the size of the instruction.2993 * NULL is allowed. This is also stored in2994 * PDISSTATE::cbInstr.2995 */2996 DISDECL(int) DISInstr(const void *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr)2997 {2998 return DISInstrEx((uintptr_t)pvInstr, enmCpuMode, DISOPTYPE_ALL, NULL /*pfnReadBytes*/, NULL /*pvUser*/, pDis, pcbInstr);2999 }3000 -
trunk/src/VBox/Disassembler/DisasmInternal-x86-amd64.h
r99231 r99236 26 26 */ 27 27 28 #ifndef VBOX_INCLUDED_SRC_DisasmInternal_ h29 #define VBOX_INCLUDED_SRC_DisasmInternal_ h28 #ifndef VBOX_INCLUDED_SRC_DisasmInternal_x86_amd64_h 29 #define VBOX_INCLUDED_SRC_DisasmInternal_x86_amd64_h 30 30 #ifndef RT_WITHOUT_PRAGMA_ONCE 31 31 # pragma once … … 33 33 34 34 #include <VBox/types.h> 35 #include <VBox/err.h> 35 36 #include <VBox/dis.h> 36 37 38 /** @defgroup grp_dis_int Internals. 37 #include <VBox/log.h> 38 39 #include <iprt/param.h> 40 #include "DisasmInternal.h" 41 42 43 /** @addtogroup grp_dis_int Internals. 39 44 * @ingroup grp_dis 40 45 * @{ … … 227 232 /** @} */ 228 233 229 /** @def OP 230 * Wrapper which initializes an DISOPCODE. 231 * We must use this so that we can exclude unused fields in order 232 * to save precious bytes in the GC version. 233 * 234 * @internal 235 */ 236 #if DISOPCODE_FORMAT == 0 237 # define OP(pszOpcode, idxParse1, idxParse2, idxParse3, opcode, param1, param2, param3, optype) \ 238 { pszOpcode, idxParse1, idxParse2, idxParse3, 0, opcode, param1, param2, param3, 0, 0, optype } 239 # define OPVEX(pszOpcode, idxParse1, idxParse2, idxParse3, idxParse4, opcode, param1, param2, param3, param4, optype) \ 240 { pszOpcode, idxParse1, idxParse2, idxParse3, idxParse4, opcode, param1, param2, param3, param4, 0, optype | DISOPTYPE_X86_SSE } 241 242 #elif DISOPCODE_FORMAT == 16 243 # define OP(pszOpcode, idxParse1, idxParse2, idxParse3, opcode, param1, param2, param3, optype) \ 244 { optype, opcode, idxParse1, idxParse2, param1, param2, idxParse3, param3, 0, 0 } 245 # define OPVEX(pszOpcode, idxParse1, idxParse2, idxParse3, idxParse4, opcode, param1, param2, param3, param4, optype) \ 246 { optype | DISOPTYPE_X86_SSE, opcode, idxParse1, idxParse2, param1, param2, idxParse3, param3, param4, idxParse4 } 247 248 #elif DISOPCODE_FORMAT == 15 249 # define OP(pszOpcode, idxParse1, idxParse2, idxParse3, opcode, param1, param2, param3, optype) \ 250 { opcode, idxParse1, idxParse2, idxParse3, param1, param2, param3, optype, 0, 0 } 251 # define OPVEX(pszOpcode, idxParse1, idxParse2, idxParse3, idxParse4, opcode, param1, param2, param3, param4, optype) \ 252 { opcode, idxParse1, idxParse2, idxParse3, param1, param2, param3, optype | DISOPTYPE_X86_SSE, param4, idxParse4 } 253 #else 254 # error Unsupported DISOPCODE_FORMAT value 255 #endif 256 257 258 size_t disFormatBytes(PCDISSTATE pDis, char *pszDst, size_t cchDst, uint32_t fFlags); 259 260 /** @} */ 261 #endif /* !VBOX_INCLUDED_SRC_DisasmInternal_h */ 262 234 235 /** @} */ 236 #endif /* !VBOX_INCLUDED_SRC_DisasmInternal_x86_amd64_h */ 237 -
trunk/src/VBox/Disassembler/DisasmInternal.h
r99220 r99236 33 33 34 34 #include <VBox/types.h> 35 #include <VBox/err.h> 35 36 #include <VBox/dis.h> 37 #include <VBox/log.h> 38 39 #include <iprt/param.h> 36 40 37 41 … … 41 45 */ 42 46 43 /** @name Index into g_apfnCalcSize and g_apfnFullDisasm. 44 * @{ */ 45 enum IDX_Parse 46 { 47 IDX_ParseNop = 0, 48 IDX_ParseModRM, 49 IDX_UseModRM, 50 IDX_ParseImmByte, 51 IDX_ParseImmBRel, 52 IDX_ParseImmUshort, 53 IDX_ParseImmV, 54 IDX_ParseImmVRel, 55 IDX_ParseImmAddr, 56 IDX_ParseFixedReg, 57 IDX_ParseImmUlong, 58 IDX_ParseImmQword, 59 IDX_ParseTwoByteEsc, 60 IDX_ParseGrp1, 61 IDX_ParseShiftGrp2, 62 IDX_ParseGrp3, 63 IDX_ParseGrp4, 64 IDX_ParseGrp5, 65 IDX_Parse3DNow, 66 IDX_ParseGrp6, 67 IDX_ParseGrp7, 68 IDX_ParseGrp8, 69 IDX_ParseGrp9, 70 IDX_ParseGrp10, 71 IDX_ParseGrp12, 72 IDX_ParseGrp13, 73 IDX_ParseGrp14, 74 IDX_ParseGrp15, 75 IDX_ParseGrp16, 76 IDX_ParseGrp17, 77 IDX_ParseModFence, 78 IDX_ParseYv, 79 IDX_ParseYb, 80 IDX_ParseXv, 81 IDX_ParseXb, 82 IDX_ParseEscFP, 83 IDX_ParseNopPause, 84 IDX_ParseImmByteSX, 85 IDX_ParseImmZ, 86 IDX_ParseThreeByteEsc4, 87 IDX_ParseThreeByteEsc5, 88 IDX_ParseImmAddrF, 89 IDX_ParseInvOpModRM, 90 IDX_ParseVex2b, 91 IDX_ParseVex3b, 92 IDX_ParseVexDest, 93 IDX_ParseMax 94 }; 95 AssertCompile(IDX_ParseMax < 64 /* Packed DISOPCODE assumption. */); 96 /** @} */ 97 98 /** 99 * Opcode map descriptor. 100 * 101 * This is used a number of places to save storage space where there are lots of 102 * invalid instructions and the beginning or end of the map. 103 */ 104 typedef struct DISOPMAPDESC 105 { 106 /** Pointer to the opcodes described by this structure. */ 107 PCDISOPCODE papOpcodes; 108 #if ARCH_BITS <= 32 109 uint16_t 110 #else 111 uint32_t 112 #endif 113 /** The map index corresponding to the first papOpcodes entry. */ 114 idxFirst, 115 /** Number of opcodes in the map. */ 116 cOpcodes; 117 } DISOPMAPDESC; 118 /** Pointer to a const opcode map descriptor. */ 119 typedef DISOPMAPDESC const *PCDISOPMAPDESC; 120 121 /** @name Opcode maps. 122 * @{ */ 123 extern const DISOPCODE g_InvalidOpcode[1]; 124 125 extern const DISOPCODE g_aOneByteMapX86[256]; 126 extern const DISOPCODE g_aOneByteMapX64[256]; 127 extern const DISOPCODE g_aTwoByteMapX86[256]; 128 129 /** Two byte opcode map with prefix 0x66 */ 130 extern const DISOPCODE g_aTwoByteMapX86_PF66[256]; 131 132 /** Two byte opcode map with prefix 0xF2 */ 133 extern const DISOPCODE g_aTwoByteMapX86_PFF2[256]; 134 135 /** Two byte opcode map with prefix 0xF3 */ 136 extern const DISOPCODE g_aTwoByteMapX86_PFF3[256]; 137 138 /** Three byte opcode map (0xF 0x38) */ 139 extern PCDISOPCODE const g_apThreeByteMapX86_0F38[16]; 140 141 /** Three byte opcode map with prefix 0x66 (0xF 0x38) */ 142 extern PCDISOPCODE const g_apThreeByteMapX86_660F38[16]; 143 144 /** Three byte opcode map with prefix 0xF2 (0xF 0x38) */ 145 extern PCDISOPCODE const g_apThreeByteMapX86_F20F38[16]; 146 147 /** Three byte opcode map with prefix 0xF3 (0xF 0x38) */ 148 extern PCDISOPCODE const g_apThreeByteMapX86_F30F38[16]; 149 150 extern PCDISOPCODE const g_apThreeByteMapX86_0F3A[16]; 151 152 /** Three byte opcode map with prefix 0x66 (0xF 0x3A) */ 153 extern PCDISOPCODE const g_apThreeByteMapX86_660F3A[16]; 154 155 /** Three byte opcode map with prefixes 0x66 0xF2 (0xF 0x38) */ 156 extern PCDISOPCODE const g_apThreeByteMapX86_66F20F38[16]; 157 158 /** VEX opcodes table defined by [VEX.m-mmmm - 1]. 159 * 0Fh, 0F38h, 0F3Ah correspondingly, VEX.pp = 00b */ 160 extern PCDISOPMAPDESC const g_apVexOpcodesMapRanges_None[3]; 161 162 /** VEX opcodes table defined by [VEX.m-mmmm - 1]. 163 * 0Fh, 0F38h, 0F3Ah correspondingly, VEX.pp = 01b (66h) */ 164 extern PCDISOPMAPDESC const g_apVexOpcodesMapRanges_66H[3]; 165 166 /** 0Fh, 0F38h, 0F3Ah correspondingly, VEX.pp = 10b (F3h) */ 167 extern PCDISOPMAPDESC const g_apVexOpcodesMapRanges_F3H[3]; 168 169 /** 0Fh, 0F38h, 0F3Ah correspondingly, VEX.pp = 11b (F2h) */ 170 extern PCDISOPMAPDESC const g_apVexOpcodesMapRanges_F2H[3]; 171 172 /** Two dimmentional map descriptor array: first index is by VEX.pp (prefix), 173 * second by the VEX.mmmm (map). 174 * The latter has to be bounced checked as we only have the first 4 maps. */ 175 extern PCDISOPMAPDESC const g_aapVexOpcodesMapRanges[4][4]; 176 /** @} */ 177 178 /** @name Opcode extensions (Group tables) 179 * @{ */ 180 extern const DISOPCODE g_aMapX86_Group1[8*4]; 181 extern const DISOPCODE g_aMapX86_Group2[8*6]; 182 extern const DISOPCODE g_aMapX86_Group3[8*2]; 183 extern const DISOPCODE g_aMapX86_Group4[8]; 184 extern const DISOPCODE g_aMapX86_Group5[8]; 185 extern const DISOPCODE g_aMapX86_Group6[8]; 186 extern const DISOPCODE g_aMapX86_Group7_mem[8]; 187 extern const DISOPCODE g_aMapX86_Group7_mod11_rm000[8]; 188 extern const DISOPCODE g_aMapX86_Group7_mod11_rm001[8]; 189 extern const DISOPCODE g_aMapX86_Group8[8]; 190 extern const DISOPCODE g_aMapX86_Group9[8]; 191 extern const DISOPCODE g_aMapX86_Group10[8]; 192 extern const DISOPCODE g_aMapX86_Group11[8*2]; 193 extern const DISOPCODE g_aMapX86_Group12[8*2]; 194 extern const DISOPCODE g_aMapX86_Group13[8*2]; 195 extern const DISOPCODE g_aMapX86_Group14[8*2]; 196 extern const DISOPCODE g_aMapX86_Group15_mem[8]; 197 extern const DISOPCODE g_aMapX86_Group15_mod11_rm000[8]; 198 extern const DISOPCODE g_aMapX86_Group16[8]; 199 extern const DISOPCODE g_aMapX86_Group17[8*2]; 200 extern const DISOPCODE g_aMapX86_NopPause[2]; 201 /** @} */ 202 203 /** 3DNow! map (0x0F 0x0F prefix) */ 204 extern const DISOPCODE g_aTwoByteMapX86_3DNow[256]; 205 206 /** Floating point opcodes starting with escape byte 0xDF 207 * @{ */ 208 extern const DISOPCODE g_aMapX86_EscF0_Low[8]; 209 extern const DISOPCODE g_aMapX86_EscF0_High[16*4]; 210 extern const DISOPCODE g_aMapX86_EscF1_Low[8]; 211 extern const DISOPCODE g_aMapX86_EscF1_High[16*4]; 212 extern const DISOPCODE g_aMapX86_EscF2_Low[8]; 213 extern const DISOPCODE g_aMapX86_EscF2_High[16*4]; 214 extern const DISOPCODE g_aMapX86_EscF3_Low[8]; 215 extern const DISOPCODE g_aMapX86_EscF3_High[16*4]; 216 extern const DISOPCODE g_aMapX86_EscF4_Low[8]; 217 extern const DISOPCODE g_aMapX86_EscF4_High[16*4]; 218 extern const DISOPCODE g_aMapX86_EscF5_Low[8]; 219 extern const DISOPCODE g_aMapX86_EscF5_High[16*4]; 220 extern const DISOPCODE g_aMapX86_EscF6_Low[8]; 221 extern const DISOPCODE g_aMapX86_EscF6_High[16*4]; 222 extern const DISOPCODE g_aMapX86_EscF7_Low[8]; 223 extern const DISOPCODE g_aMapX86_EscF7_High[16*4]; 224 225 extern const PCDISOPCODE g_apMapX86_FP_Low[8]; 226 extern const PCDISOPCODE g_apMapX86_FP_High[8]; 227 /** @} */ 47 /** This must be less or equal to DISSTATE::u.abInstr. 48 * See Vol3A/Table 6-2 and Vol3B/Section22.25 for instance. */ 49 #define DIS_MAX_INSTR_LENGTH 15 50 51 /** Whether we can do unaligned access. */ 52 #if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64) 53 # define DIS_HOST_UNALIGNED_ACCESS_OK 54 #endif 55 228 56 229 57 /** @def OP … … 256 84 257 85 86 /* Common */ 87 DECLHIDDEN(void) disReadMore(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMin); 88 DECLHIDDEN(uint8_t) disReadByteSlow(PDISSTATE pDis, size_t offInstr); 89 DECLHIDDEN(uint16_t) disReadWordSlow(PDISSTATE pDis, size_t offInstr); 90 DECLHIDDEN(uint32_t) disReadDWordSlow(PDISSTATE pDis, size_t offInstr); 91 DECLHIDDEN(uint64_t) disReadQWordSlow(PDISSTATE pDis, size_t offInstr); 92 93 94 /** 95 * Read a byte (8-bit) instruction. 96 * 97 * @returns The requested byte. 98 * @param pDis The disassembler state. 99 * @param uAddress The address. 100 */ 101 DECL_FORCE_INLINE(uint8_t) disReadByte(PDISSTATE pDis, size_t offInstr) 102 { 103 if (offInstr >= pDis->cbCachedInstr) 104 return disReadByteSlow(pDis, offInstr); 105 return pDis->u.abInstr[offInstr]; 106 } 107 108 109 /** 110 * Read a word (16-bit) instruction. 111 * 112 * @returns The requested word. 113 * @param pDis The disassembler state. 114 * @param offInstr The offset of the qword relative to the 115 * instruction. 116 */ 117 DECL_FORCE_INLINE(uint16_t) disReadWord(PDISSTATE pDis, size_t offInstr) 118 { 119 if (offInstr + 2 > pDis->cbCachedInstr) 120 return disReadWordSlow(pDis, offInstr); 121 122 #ifdef DIS_HOST_UNALIGNED_ACCESS_OK 123 return *(uint16_t const *)&pDis->u.abInstr[offInstr]; 124 #else 125 return RT_MAKE_U16(pDis->u.abInstr[offInstr], pDis->u.abInstr[offInstr + 1]); 126 #endif 127 } 128 129 130 /** 131 * Read a dword (32-bit) instruction. 132 * 133 * @returns The requested dword. 134 * @param pDis The disassembler state. 135 * @param offInstr The offset of the qword relative to the 136 * instruction. 137 */ 138 DECL_FORCE_INLINE(uint32_t) disReadDWord(PDISSTATE pDis, size_t offInstr) 139 { 140 if (offInstr + 4 > pDis->cbCachedInstr) 141 return disReadDWordSlow(pDis, offInstr); 142 143 #ifdef DIS_HOST_UNALIGNED_ACCESS_OK 144 return *(uint32_t const *)&pDis->u.abInstr[offInstr]; 145 #else 146 return RT_MAKE_U32_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1], 147 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3]); 148 #endif 149 } 150 151 152 /** 153 * Read a qword (64-bit) instruction. 154 * 155 * @returns The requested qword. 156 * @param pDis The disassembler state. 157 * @param uAddress The address. 158 */ 159 DECL_FORCE_INLINE(uint64_t) disReadQWord(PDISSTATE pDis, size_t offInstr) 160 { 161 if (offInstr + 8 > pDis->cbCachedInstr) 162 return disReadQWordSlow(pDis, offInstr); 163 164 #ifdef DIS_HOST_UNALIGNED_ACCESS_OK 165 return *(uint64_t const *)&pDis->u.abInstr[offInstr]; 166 #else 167 return RT_MAKE_U64_FROM_U8(pDis->u.abInstr[offInstr ], pDis->u.abInstr[offInstr + 1], 168 pDis->u.abInstr[offInstr + 2], pDis->u.abInstr[offInstr + 3], 169 pDis->u.abInstr[offInstr + 4], pDis->u.abInstr[offInstr + 5], 170 pDis->u.abInstr[offInstr + 6], pDis->u.abInstr[offInstr + 7]); 171 #endif 172 } 173 174 175 /** 176 * Reads some bytes into the cache. 177 * 178 * While this will set DISSTATE::rc on failure, the caller should disregard 179 * this since that is what would happen if we didn't prefetch bytes prior to the 180 * instruction parsing. 181 * 182 * @param pDis The disassembler state. 183 */ 184 DECL_FORCE_INLINE(void) disPrefetchBytes(PDISSTATE pDis) 185 { 186 /* 187 * Read some bytes into the cache. (If this fail we continue as nothing 188 * has gone wrong since this is what would happen if we didn't precharge 189 * the cache here.) 190 */ 191 int rc = pDis->pfnReadBytes(pDis, 0, 1, sizeof(pDis->u.abInstr)); 192 if (RT_SUCCESS(rc)) 193 { 194 Assert(pDis->cbCachedInstr >= 1); 195 Assert(pDis->cbCachedInstr <= sizeof(pDis->u.abInstr)); 196 } 197 else 198 { 199 Log(("Initial read failed with rc=%Rrc!!\n", rc)); 200 pDis->rc = rc; 201 } 202 } 203 204 205 /* x86/amd64 */ 206 DECLHIDDEN(PCDISOPCODE) disInitializeStateX86(PDISSTATE pDis, DISCPUMODE enmCpuMode, uint32_t fFilter); 207 DECLHIDDEN(int) disInstrWorkerX86(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr); 208 258 209 size_t disFormatBytes(PCDISSTATE pDis, char *pszDst, size_t cchDst, uint32_t fFlags); 259 210 -
trunk/src/VBox/Disassembler/DisasmTables-x86-amd64.cpp
r99235 r99236 32 32 #include <VBox/dis.h> 33 33 #include <VBox/disopcode-x86-amd64.h> 34 #include "DisasmInternal .h"34 #include "DisasmInternal-x86-amd64.h" 35 35 36 36 -
trunk/src/VBox/Disassembler/DisasmTablesX64.cpp
r99220 r99236 32 32 #include <VBox/dis.h> 33 33 #include <VBox/disopcode-x86-amd64.h> 34 #include "DisasmInternal .h"34 #include "DisasmInternal-x86-amd64.h" 35 35 36 36 -
trunk/src/VBox/Disassembler/Makefile.kmk
r98439 r99236 40 40 DisasmR3_SOURCES = \ 41 41 Disasm.cpp \ 42 DisasmCore .cpp \43 DisasmTables .cpp \42 DisasmCore-x86-amd64.cpp \ 43 DisasmTables-x86-amd64.cpp \ 44 44 DisasmTablesX64.cpp \ 45 45 DisasmMisc.cpp \ … … 61 61 DisasmCoreR3_DEFS = IN_DIS DIS_CORE_ONLY 62 62 DisasmCoreR3_SOURCES = \ 63 DisasmCore.cpp \ 64 DisasmTables.cpp \ 63 Disasm.cpp \ 64 DisasmCore-x86-amd64.cpp \ 65 DisasmTables-x86-amd64.cpp \ 65 66 DisasmTablesX64.cpp \ 66 67 DisasmMisc.cpp … … 71 72 DisasmRC_DEFS = IN_DIS IN_RT_RC DIS_CORE_ONLY 72 73 DisasmRC_SOURCES = \ 73 DisasmCore.cpp \ 74 DisasmTables.cpp \ 74 Disasm.cpp \ 75 DisasmCore-x86-amd64.cpp \ 76 DisasmTables-x86-amd64.cpp \ 75 77 DisasmTablesX64.cpp \ 76 78 DisasmMisc.cpp … … 81 83 DisasmR0_DEFS = IN_DIS IN_RT_R0 DIS_CORE_ONLY 82 84 DisasmR0_SOURCES = \ 83 DisasmCore.cpp \ 84 DisasmTables.cpp \ 85 Disasm.cpp \ 86 DisasmCore-x86-amd64.cpp \ 87 DisasmTables-x86-amd64.cpp \ 85 88 DisasmTablesX64.cpp \ 86 89 DisasmMisc.cpp
Note:
See TracChangeset
for help on using the changeset viewer.