diff options
Diffstat (limited to 'js/src/zydis/ZydisAPI.cpp')
-rw-r--r-- | js/src/zydis/ZydisAPI.cpp | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/js/src/zydis/ZydisAPI.cpp b/js/src/zydis/ZydisAPI.cpp new file mode 100644 index 0000000000..de8e8229fb --- /dev/null +++ b/js/src/zydis/ZydisAPI.cpp @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * + * Zyan Disassembler Library (Zydis) + * + * Original Author : Code taken from examples on zydis github README.md. + * + * Modified by Mozilla. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <inttypes.h> +#include <stdio.h> +#include <string.h> + +#include "zydis/ZydisAPI.h" + +void zydisDisassemble(const uint8_t* code, size_t codeLen, + void(*println)(const char*)) { + ZydisDecoder decoder; + ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64); + + ZydisFormatter formatter; + ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_ATT); + ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE); + + ZyanU64 runtime_address = 0; + ZyanUSize offset = 0; + const ZyanUSize length = (ZyanUSize)codeLen; + ZydisDecodedInstruction instruction; + char buffer[1024]; + while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, code + offset, length - offset, + &instruction))) + { +# define LIMIT 36 +# define LIMSTR "36" + + // We format the tag and the address and the bytes in a field of LIMIT + // characters and start the menmonic at position LIMIT. If the + // tag+address+bytes would be too long we put the mnemonic + operands on the + // next line. + + // Emit address + sprintf(buffer, "%08" PRIX64 " ", runtime_address); + + // Emit bytes + for (size_t i = 0; i < instruction.length; i++) { + sprintf(buffer+strlen(buffer), "%s%02x", i == 0 ? "" : " ", *(code + offset + i)); + } + + // Pad with at least one space + sprintf(buffer+strlen(buffer), " "); + + // Pad out to the limit if necessary + if (strlen(buffer) < LIMIT) { + char* cur_end = buffer + strlen(buffer); + size_t spaces = LIMIT - strlen(buffer); + memset(cur_end, ' ', spaces); + cur_end[spaces] = '\0'; + } + + // If too long then flush and provide an appropriate indent + if (strlen(buffer) > LIMIT) { + println(buffer); + sprintf(buffer, "%-" LIMSTR "s", ""); + } + + // Emit instruction mnemonic + operands + size_t used = strlen(buffer); + ZydisFormatterFormatInstruction(&formatter, &instruction, buffer + used, + sizeof(buffer) - used, runtime_address); + println(buffer); + + offset += instruction.length; + runtime_address += instruction.length; + +# undef LIMIT +# undef LIMSTR + } +} |