brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.0 KiB · 6d44151 Raw
153 lines · cpp
1//===- X86MCDisassemblerTest.cpp - Tests for X86 MCDisassembler -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/MC/MCAsmInfo.h"10#include "llvm/MC/MCContext.h"11#include "llvm/MC/MCDisassembler/MCDisassembler.h"12#include "llvm/MC/MCDisassembler/MCSymbolizer.h"13#include "llvm/MC/MCInst.h"14#include "llvm/MC/MCRegisterInfo.h"15#include "llvm/MC/MCSubtargetInfo.h"16#include "llvm/MC/MCTargetOptions.h"17#include "llvm/MC/TargetRegistry.h"18#include "llvm/Support/TargetSelect.h"19#include "gtest/gtest.h"20 21using namespace llvm;22 23namespace {24 25struct Context {26  static constexpr char TripleName[] = "x86_64-unknown-elf";27  const Triple TheTriple;28  std::unique_ptr<MCRegisterInfo> MRI;29  std::unique_ptr<MCAsmInfo> MAI;30  std::unique_ptr<MCContext> Ctx;31  std::unique_ptr<MCSubtargetInfo> STI;32  std::unique_ptr<MCDisassembler> DisAsm;33 34  Context() : TheTriple(TripleName) {35    LLVMInitializeX86TargetInfo();36    LLVMInitializeX86TargetMC();37    LLVMInitializeX86Disassembler();38 39    // If we didn't build x86, do not run the test.40    std::string Error;41    const Target *TheTarget = TargetRegistry::lookupTarget(TheTriple, Error);42    if (!TheTarget)43      return;44 45    MRI.reset(TheTarget->createMCRegInfo(TheTriple));46    MAI.reset(TheTarget->createMCAsmInfo(*MRI, TheTriple, MCTargetOptions()));47    STI.reset(TheTarget->createMCSubtargetInfo(TheTriple, "", ""));48    Ctx =49        std::make_unique<MCContext>(TheTriple, MAI.get(), MRI.get(), STI.get());50 51    DisAsm.reset(TheTarget->createMCDisassembler(*STI, *Ctx));52  }53 54  operator MCContext &() { return *Ctx; };55};56 57Context &getContext() {58  static Context Ctxt;59  return Ctxt;60}61 62class X86MCSymbolizerTest : public MCSymbolizer {63public:64  X86MCSymbolizerTest(MCContext &MC) : MCSymbolizer(MC, nullptr) {}65  ~X86MCSymbolizerTest() override = default;66 67  struct OpInfo {68    int64_t Value = 0;69    uint64_t Offset = 0;70    uint64_t Size;71  };72  std::vector<OpInfo> Operands;73  uint64_t InstructionSize = 0;74 75  void reset() {76    Operands.clear();77    InstructionSize = 0;78  }79 80  bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &CStream,81                                int64_t Value, uint64_t Address, bool IsBranch,82                                uint64_t Offset, uint64_t OpSize,83                                uint64_t InstSize) override {84    Operands.push_back({Value, Offset, OpSize});85    InstructionSize = InstSize;86    return false;87  }88 89  void tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value,90                                       uint64_t Address) override {}91};92 93} // namespace94 95TEST(X86Disassembler, X86MCSymbolizerTest) {96  X86MCSymbolizerTest *TestSymbolizer = new X86MCSymbolizerTest(getContext());97  getContext().DisAsm->setSymbolizer(98      std::unique_ptr<MCSymbolizer>(TestSymbolizer));99 100  MCDisassembler::DecodeStatus Status;101  MCInst Inst;102  uint64_t InstSize;103 104  auto checkBytes = [&](ArrayRef<uint8_t> Bytes) {105    TestSymbolizer->reset();106    Status =107        getContext().DisAsm->getInstruction(Inst, InstSize, Bytes, 0, nulls());108    ASSERT_TRUE(Status == MCDisassembler::Success);109    EXPECT_EQ(TestSymbolizer->InstructionSize, InstSize);110  };111 112  auto checkOperand = [&](size_t OpNo, int64_t Value, uint64_t Offset,113                          uint64_t Size) {114    ASSERT_TRUE(TestSymbolizer->Operands.size() > OpNo);115    EXPECT_EQ(TestSymbolizer->Operands[OpNo].Value, Value);116    EXPECT_EQ(TestSymbolizer->Operands[OpNo].Offset, Offset);117    EXPECT_EQ(TestSymbolizer->Operands[OpNo].Size, Size);118  };119 120  // movq    $0x80000, 0x80000121  checkBytes(122      {0x48, 0xc7, 0x04, 0x25, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00});123  checkOperand(0, 0x80000, 4, 4);124  checkOperand(1, 0x80000, 8, 4);125 126  // movq   $0x2a, 0x123(%rax,%r14,8)127  checkBytes(128      {0x4a, 0xc7, 0x84, 0xf0, 0x23, 0x01, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00});129  checkOperand(0, 291, 4, 4);130  checkOperand(1, 42, 8, 4);131 132  // movq   $0xffffffffffffefe8, -0x1(%rip)133  // Test that the value of the rip-relative operand is set correctly.134  // The instruction address is 0 and the size is 12 bytes.135  checkBytes(136      {0x48, 0xc7, 0x05, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xef, 0xff, 0xff});137  checkOperand(0, /*next instr address*/ 11 - /*disp*/ 1, 3, 4);138  checkOperand(1, 0xffffffffffffefe8, 7, 4);139 140  // movq   $0xfffffffffffffef5, (%r12)141  // Test that the displacement operand has a size of 0, since it is not142  // explicitly specified in the instruction.143  checkBytes({0x49, 0xc7, 0x04, 0x24, 0xf5, 0xfe, 0xff, 0xff});144  checkOperand(0, 0, 4, 0);145  checkOperand(1, 0xfffffffffffffef5, 4, 4);146 147  // mov    %ax, 0x1568179(%rbx)148  // Test that the displacement operand size is not affected by the operand149  // size override prefix.150  checkBytes({0x66, 0x89, 0x83, 0x79, 0x81, 0x56, 0x01});151  checkOperand(0, 0x1568179, 3, 4);152}153