cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

arm-a64.cc (2823B)


      1/*
      2 * ARM A64 disassembly output wrapper to libvixl
      3 * Copyright (c) 2013 Linaro Limited
      4 * Written by Claudio Fontana
      5 *
      6 * This program is free software: you can redistribute it and/or modify
      7 * it under the terms of the GNU General Public License as published by
      8 * the Free Software Foundation, either version 2 of the License, or
      9 * (at your option) any later version.
     10 *
     11 * This program is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 * GNU General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU General Public License
     17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     18 */
     19
     20#include "qemu/osdep.h"
     21#include "disas/dis-asm.h"
     22
     23#include "vixl/a64/disasm-a64.h"
     24
     25using namespace vixl;
     26
     27static Decoder *vixl_decoder = NULL;
     28static Disassembler *vixl_disasm = NULL;
     29
     30/* We don't use libvixl's PrintDisassembler because its output
     31 * is a little unhelpful (trailing newlines, for example).
     32 * Instead we use our own very similar variant so we have
     33 * control over the format.
     34 */
     35class QEMUDisassembler : public Disassembler {
     36public:
     37    QEMUDisassembler() : printf_(NULL), stream_(NULL) { }
     38    ~QEMUDisassembler() { }
     39
     40    void SetStream(FILE *stream) {
     41        stream_ = stream;
     42    }
     43
     44    void SetPrintf(fprintf_function printf_fn) {
     45        printf_ = printf_fn;
     46    }
     47
     48protected:
     49    virtual void ProcessOutput(const Instruction *instr) {
     50        printf_(stream_, "%08" PRIx32 "      %s",
     51                instr->InstructionBits(), GetOutput());
     52    }
     53
     54private:
     55    fprintf_function printf_;
     56    FILE *stream_;
     57};
     58
     59static int vixl_is_initialized(void)
     60{
     61    return vixl_decoder != NULL;
     62}
     63
     64static void vixl_init() {
     65    vixl_decoder = new Decoder();
     66    vixl_disasm = new QEMUDisassembler();
     67    vixl_decoder->AppendVisitor(vixl_disasm);
     68}
     69
     70#define INSN_SIZE 4
     71
     72/* Disassemble ARM A64 instruction. This is our only entry
     73 * point from QEMU's C code.
     74 */
     75int print_insn_arm_a64(uint64_t addr, disassemble_info *info)
     76{
     77    uint8_t bytes[INSN_SIZE];
     78    uint32_t instrval;
     79    const Instruction *instr;
     80    int status;
     81
     82    status = info->read_memory_func(addr, bytes, INSN_SIZE, info);
     83    if (status != 0) {
     84        info->memory_error_func(status, addr, info);
     85        return -1;
     86    }
     87
     88    if (!vixl_is_initialized()) {
     89        vixl_init();
     90    }
     91
     92    ((QEMUDisassembler *)vixl_disasm)->SetPrintf(info->fprintf_func);
     93    ((QEMUDisassembler *)vixl_disasm)->SetStream(info->stream);
     94
     95    instrval = bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24;
     96    instr = reinterpret_cast<const Instruction *>(&instrval);
     97    vixl_disasm->MapCodeAddress(addr, instr);
     98    vixl_decoder->Decode(instr);
     99
    100    return INSN_SIZE;
    101}