ZydisAPI.cpp (3684B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * 4 * Zyan Disassembler Library (Zydis) 5 * 6 * Original Author : Code taken from examples on zydis github README.md. 7 * 8 * Modified by Mozilla. 9 * 10 * Permission is hereby granted, free of charge, to any person obtaining a copy 11 * of this software and associated documentation files (the "Software"), to deal 12 * in the Software without restriction, including without limitation the rights 13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 * copies of the Software, and to permit persons to whom the Software is 15 * furnished to do so, subject to the following conditions: 16 * 17 * The above copyright notice and this permission notice shall be included in all 18 * copies or substantial portions of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 * SOFTWARE. 27 */ 28 29 #include <inttypes.h> 30 #include <stdio.h> 31 #include <string.h> 32 33 #include "zydis/ZydisAPI.h" 34 35 void zydisDisassemble(const uint8_t* code, size_t codeLen, 36 void(*println)(const char*)) { 37 ZydisDecoder decoder; 38 ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64); 39 40 ZydisFormatter formatter; 41 ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_ATT); 42 ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE); 43 44 ZyanU64 runtime_address = 0; 45 ZyanUSize offset = 0; 46 const ZyanUSize length = (ZyanUSize)codeLen; 47 ZydisDecodedInstruction instruction; 48 ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; 49 char buffer[1024]; 50 while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(&decoder, code + offset, length - offset, 51 &instruction, operands))) 52 { 53 # define LIMIT 48 54 # define LIMSTR "48" 55 56 // We format the tag and the address and the bytes in a field of LIMIT 57 // characters and start the menmonic at position LIMIT. If the 58 // tag+address+bytes would be too long we put the mnemonic + operands on the 59 // next line. 60 61 // Emit address 62 sprintf(buffer, "%08" PRIX64 " ", runtime_address); 63 64 // Emit bytes 65 for (size_t i = 0; i < instruction.length; i++) { 66 sprintf(buffer+strlen(buffer), "%s%02x", i == 0 ? "" : " ", *(code + offset + i)); 67 } 68 69 // Pad with at least one space 70 sprintf(buffer+strlen(buffer), " "); 71 72 // Pad out to the limit if necessary 73 if (strlen(buffer) < LIMIT) { 74 char* cur_end = buffer + strlen(buffer); 75 size_t spaces = LIMIT - strlen(buffer); 76 memset(cur_end, ' ', spaces); 77 cur_end[spaces] = '\0'; 78 } 79 80 // If too long then flush and provide an appropriate indent 81 if (strlen(buffer) > LIMIT) { 82 println(buffer); 83 sprintf(buffer, "%-" LIMSTR "s", ""); 84 } 85 86 // Emit instruction mnemonic + operands 87 size_t used = strlen(buffer); 88 ZydisFormatterFormatInstruction(&formatter, &instruction, operands, 89 instruction.operand_count_visible, buffer + used, 90 sizeof(buffer) - used, runtime_address, ZYAN_NULL); 91 println(buffer); 92 93 offset += instruction.length; 94 runtime_address += instruction.length; 95 96 # undef LIMIT 97 # undef LIMSTR 98 } 99 }