1226890Sdim//===- lib/Support/Disassembler.cpp -----------------------------*- C++ -*-===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10218885Sdim// This file implements the necessary glue to call external disassembler
11218885Sdim// libraries.
12218885Sdim//
13218885Sdim//===----------------------------------------------------------------------===//
14218885Sdim
15252723Sdim#include "llvm/Support/Disassembler.h"
16218885Sdim#include "llvm/Config/config.h"
17218885Sdim#include <cassert>
18218885Sdim#include <iomanip>
19252723Sdim#include <sstream>
20218885Sdim#include <string>
21218885Sdim
22218885Sdim#if USE_UDIS86
23218885Sdim#include <udis86.h>
24218885Sdim#endif
25218885Sdim
26218885Sdimusing namespace llvm;
27218885Sdim
28218885Sdimbool llvm::sys::hasDisassembler()
29218885Sdim{
30218885Sdim#if defined (__i386__) || defined (__amd64__) || defined (__x86_64__)
31218885Sdim  // We have option to enable udis86 library.
32218885Sdim# if USE_UDIS86
33218885Sdim  return true;
34218885Sdim#else
35218885Sdim  return false;
36218885Sdim#endif
37218885Sdim#else
38218885Sdim  return false;
39218885Sdim#endif
40218885Sdim}
41218885Sdim
42218885Sdimstd::string llvm::sys::disassembleBuffer(uint8_t* start, size_t length,
43218885Sdim                                         uint64_t pc) {
44263509Sdim#if (defined (__i386__) || defined (__amd64__) || defined (__x86_64__)) \
45263509Sdim  && USE_UDIS86
46218885Sdim  std::stringstream res;
47218885Sdim
48218885Sdim  unsigned bits;
49218885Sdim# if defined(__i386__)
50218885Sdim  bits = 32;
51218885Sdim# else
52218885Sdim  bits = 64;
53218885Sdim# endif
54218885Sdim
55218885Sdim  ud_t ud_obj;
56218885Sdim
57218885Sdim  ud_init(&ud_obj);
58218885Sdim  ud_set_input_buffer(&ud_obj, start, length);
59218885Sdim  ud_set_mode(&ud_obj, bits);
60218885Sdim  ud_set_pc(&ud_obj, pc);
61218885Sdim  ud_set_syntax(&ud_obj, UD_SYN_ATT);
62218885Sdim
63218885Sdim  res << std::setbase(16)
64218885Sdim      << std::setw(bits/4);
65218885Sdim
66218885Sdim  while (ud_disassemble(&ud_obj)) {
67218885Sdim    res << ud_insn_off(&ud_obj) << ":\t" << ud_insn_asm(&ud_obj) << "\n";
68218885Sdim  }
69263509Sdim
70263509Sdim  return res.str();
71218885Sdim#else
72263509Sdim  return "No disassembler available. See configure help for options.\n";
73218885Sdim#endif
74218885Sdim}
75