tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }