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