ROSE  0.9.9.109
unparseX86Asm.C
1 #include "sage3basic.h"
2 #include "Registers.h"
3 #include "AsmUnparser.h"
4 #include "Diagnostics.h"
5 #include "stringify.h"
6 
7 #include <iomanip>
8 
9 using namespace Rose;
10 using namespace Diagnostics;
11 using namespace BinaryAnalysis;
12 
14 std::string unparseX86Mnemonic(SgAsmX86Instruction *insn) {
15  ASSERT_not_null(insn);
16  std::string result;
17  if (insn->get_lockPrefix())
18  result += "lock ";
19  result += insn->get_mnemonic();
20  switch (insn->get_branchPrediction()) {
21  case x86_branch_prediction_none: break;
22  case x86_branch_prediction_taken: result += ",pt"; break;
23  case x86_branch_prediction_not_taken: result += ",pn"; break;
24  default:
25  ASSERT_not_reachable("bad x86 branch prediction: " + stringifyX86BranchPrediction(insn->get_branchPrediction()));
26  }
27  return result;
28 }
29 
34 std::string unparseX86Register(SgAsmInstruction *insn, RegisterDescriptor reg, const RegisterDictionary *registers) {
35  if (!registers)
37  std::string name = registers->lookup(reg);
38  if (name.empty())
39  name = AsmUnparser::invalid_register(insn, reg, registers);
40  return name;
41 }
42 
43 std::string unparseX86Register(RegisterDescriptor reg, const RegisterDictionary *registers) {
44  return unparseX86Register(NULL, reg, registers);
45 }
46 
47 static std::string x86ValToLabel(uint64_t val, const AsmUnparser::LabelMap *labels)
48 {
49  if (!val || !labels)
50  return "";
51 
52  AsmUnparser::LabelMap::const_iterator li = labels->find(val);
53  if (li==labels->end())
54  return "";
55 
56  return li->second;
57 }
58 
59 static std::string x86TypeToPtrName(SgAsmType* ty) {
60  if (NULL==ty) {
61  mlog[ERROR] <<"x86TypeToPtrName: null type\n";
62  return "BAD_TYPE";
63  }
64 
65  if (SgAsmIntegerType *it = isSgAsmIntegerType(ty)) {
66  switch (it->get_nBits()) {
67  case 8: return "byte";
68  case 16: return "word";
69  case 32: return "dword";
70  case 64: return "qword";
71  }
72  } else if (SgAsmFloatType *ft = isSgAsmFloatType(ty)) {
73  switch (ft->get_nBits()) {
74  case 32: return "float";
75  case 64: return "double";
76  case 80: return "ldouble";
77  }
79  return "dqword";
80  } else if (SgAsmVectorType *vt = isSgAsmVectorType(ty)) {
81  return "v" + StringUtility::numberToString(vt->get_nElmts()) + x86TypeToPtrName(vt->get_elmtType());
82  }
83  ASSERT_not_reachable("unhandled type: " + ty->toString());
84 }
85 
86 std::string unparseX86Expression(SgAsmExpression *expr, const AsmUnparser::LabelMap *labels,
87  const RegisterDictionary *registers, bool leaMode) {
88  std::string result = "";
89  if (expr == NULL) return "BOGUS:NULL";
90 
91  switch (expr->variantT()) {
92  case V_SgAsmBinaryAdd:
93  result = unparseX86Expression(isSgAsmBinaryExpression(expr)->get_lhs(), labels, registers, false) + " + " +
94  unparseX86Expression(isSgAsmBinaryExpression(expr)->get_rhs(), labels, registers, false);
95  break;
96 
97  case V_SgAsmBinarySubtract:
98  result = unparseX86Expression(isSgAsmBinaryExpression(expr)->get_lhs(), labels, registers, false) + " - " +
99  unparseX86Expression(isSgAsmBinaryExpression(expr)->get_rhs(), labels, registers, false);
100  break;
101 
102  case V_SgAsmBinaryMultiply:
103  result = unparseX86Expression(isSgAsmBinaryExpression(expr)->get_lhs(), labels, registers, false) + "*" +
104  unparseX86Expression(isSgAsmBinaryExpression(expr)->get_rhs(), labels, registers, false);
105  break;
106 
107  case V_SgAsmMemoryReferenceExpression: {
108  SgAsmMemoryReferenceExpression* mr = isSgAsmMemoryReferenceExpression(expr);
109  if (!leaMode) {
110  result += x86TypeToPtrName(mr->get_type()) + " " +
111  (mr->get_segment() ? unparseX86Expression(mr->get_segment(), labels, registers, false) + ":" : "");
112  }
113  result += "[" + unparseX86Expression(mr->get_address(), labels, registers, false) + "]";
114  break;
115  }
116 
117  case V_SgAsmDirectRegisterExpression: {
118  SgAsmInstruction *insn = SageInterface::getEnclosingNode<SgAsmInstruction>(expr);
119  SgAsmDirectRegisterExpression* rr = isSgAsmDirectRegisterExpression(expr);
120  result = unparseX86Register(insn, rr->get_descriptor(), registers);
121  break;
122  }
123 
124  case V_SgAsmIndirectRegisterExpression: {
125  SgAsmInstruction *insn = SageInterface::getEnclosingNode<SgAsmInstruction>(expr);
126  SgAsmIndirectRegisterExpression* rr = isSgAsmIndirectRegisterExpression(expr);
127  result = unparseX86Register(insn, rr->get_descriptor(), registers);
128  if (!result.empty() && '0'==result[result.size()-1])
129  result = result.substr(0, result.size()-1);
130  result += "(" + StringUtility::numberToString(rr->get_index()) + ")";
131  break;
132  }
133 
134  case V_SgAsmIntegerValueExpression: {
135  SgAsmIntegerValueExpression *ival = isSgAsmIntegerValueExpression(expr);
136  ASSERT_not_null(ival);
137  uint64_t value = ival->get_absoluteValue(); // not sign extended
138 
139  // If the value looks like it might be an address, then don't bother showing the decimal form.
140  if ((32==ival->get_significantBits() || 64==ival->get_significantBits()) &&
141  value > 0x0000ffff && value < 0xffff0000) {
142  result = StringUtility::addrToString(value, ival->get_significantBits());
143  } else {
144  result = StringUtility::signedToHex2(value, ival->get_significantBits());
145  }
146 
147  // Optional label. Prefer a label supplied by the caller's LabelMap, but not for single-byte constants. If
148  // there's no caller-supplied label, then consider whether the value expression is relative to some other IR node.
149  if (expr->get_comment().empty()) {
150  std::string label;
151  if (label.empty() && ival->get_significantBits()>8)
152  label =x86ValToLabel(value, labels);
153  if (label.empty())
154  label = ival->get_label();
155  result = StringUtility::appendAsmComment(result, label);
156  }
157  break;
158  }
159 
160  default: {
161  ASSERT_not_reachable("invalid x86 expression: " + expr->class_name());
162  }
163  }
164 
165  result = StringUtility::appendAsmComment(result, expr->get_comment());
166  return result;
167 }
168 
170 std::string unparseX86Expression(SgAsmExpression *expr, const AsmUnparser::LabelMap *labels,
171  const RegisterDictionary *registers) {
172  /* Find the instruction with which this expression is associated. */
173  SgAsmX86Instruction *insn = NULL;
174  for (SgNode *node=expr; !insn && node; node=node->get_parent()) {
175  insn = isSgAsmX86Instruction(node);
176  }
177  ASSERT_not_null(insn);
178  return unparseX86Expression(expr, labels, registers, insn->get_kind()==x86_lea);
179 }
SgAsmType * get_type() const
Property: Type of expression.
ROSE_UTIL_API std::string signedToHex2(uint64_t value, size_t nbits)
Convert a number to a hexadecimal and decimal string.
ROSE_UTIL_API std::string numberToString(long long)
Convert an integer to a string.
SgAsmExpression * get_segment() const
Property: Optional memory segment register.
Base class for machine instructions.
X86InstructionKind get_kind() const
Property: Instruction kind.
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
const std::string & get_comment() const
Property: Comment.
static const RegisterDictionary * dictionary_amd64()
Amd64 registers.
SgAsmIntegerType * buildTypeU64()
64-bit unsigned
Error messages that indicate an abnormal situation from which the program was able to at least partia...
Definition: Message.h:327
SgAsmExpression * get_address() const
Property: Memory address expression.
Main namespace for the ROSE library.
std::string stringifyX86BranchPrediction(long int n, const char *strip=NULL, bool canonic=false)
Converts an enum of type X86BranchPrediction to a string.
Definition: stringify.C:29845
Describes (part of) a physical CPU register.
virtual VariantT variantT() const
returns new style SageIII enum values
const std::string & get_mnemonic() const
Property: Instruction mnemonic string.
Reference to memory locations.
virtual std::string toString() const
Convert a type to a string.
ROSE_UTIL_API std::string appendAsmComment(const std::string &s, const std::string &comment)
Append an assembly comment to a string.
std::string get_label(bool quiet=false) const
Returns a label for the value.
Expression representing a machine register.
Base class for integer values.
bool get_lockPrefix() const
Property: Whether the x86 lock prefix was present.
This class represents the base class for all IR nodes within Sage III.
Definition: Cxx_Grammar.h:8322
ROSE_UTIL_API std::string addrToString(uint64_t value, size_t nbits=0)
Convert a virtual address to a string.
size_t get_significantBits() const
Return the number of significant bits in the value.
Represents one Intel x86 machine instruction.
Defines registers available for a particular architecture.
Definition: Registers.h:32
Base class for expressions.
virtual std::string class_name() const
returns a string representing the class name
Base class for binary types.
Registers accessed indirectly.
SgNode * get_parent() const
Access function for parent node.
Integer types.
uint64_t get_absoluteValue(size_t nbits=0) const
Returns the current absolute value zero filled to 64 bits.
Floating point types.
X86BranchPrediction get_branchPrediction() const
Property: An enum constant describing branch prediction.
const RegisterDescriptor * lookup(const std::string &name) const
Returns a descriptor for a given register name.
SgAsmVectorType * buildTypeVector(size_t, SgAsmType *)
Fixed-size, packed array.
Base class for vector types.