ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SgAsmBlock.C
Go to the documentation of this file.
1 /* SgAsmBlock member definitions. Do not move them to src/ROSETTA/Grammar/BinaryInstruction.code (or any *.code file) because
2  * then they won't get indexed/formatted/etc. by C-aware tools. */
3 
4 #include "sage3basic.h"
5 #include "stringify.h"
6 
7 using namespace rose;
8 
13 {
14  ROSE_ASSERT(!get_statementList().empty());
15  SgAsmInstruction *last = isSgAsmInstruction(get_statementList().back());
16  ROSE_ASSERT(last!=NULL);
17  return last->get_address() + last->get_size();
18 }
19 
23 bool
25 {
26  const SgAsmStatementPtrList &stmts = get_statementList();
27  for (SgAsmStatementPtrList::const_iterator si=stmts.begin(); si!=stmts.end(); ++si) {
28  if (isSgAsmInstruction(*si))
29  return true;
30  }
31  return false;
32 }
33 
36 std::string
37 SgAsmBlock::reason_key(const std::string &prefix)
38 {
39  return (prefix + "L = left over blocks N = NOP/zero padding F = fragment\n" +
40  prefix + "J = jump table E = Function entry\n" +
41  prefix + "H = CFG head U = user-def reason M = miscellaneous\n" +
42  prefix + "1 = first CFG traversal 2 = second CFG traversal 3 = third CFG traversal\n");
43 }
44 
46 std::string
47 SgAsmBlock::reason_str(bool do_pad) const
48 {
49  return reason_str(do_pad, get_reason());
50 }
51 
55 std::string
56 SgAsmBlock::reason_str(bool do_pad, unsigned r)
57 {
58  using namespace StringUtility; // for add_to_reason_string()
59  std::string result;
60 
61  if (r & BLK_LEFTOVERS) {
62  add_to_reason_string(result, true, do_pad, "L", "leftovers");
63  } else if (r & BLK_PADDING) {
64  add_to_reason_string(result, true, do_pad, "N", "padding");
65  } else if (r & BLK_FRAGMENT) {
66  add_to_reason_string(result, true, do_pad, "F", "fragment");
67  } else if (r & BLK_JUMPTABLE) {
68  add_to_reason_string(result, true, do_pad, "J", "jumptable");
69  } else {
70  add_to_reason_string(result, (r & BLK_ENTRY_POINT), do_pad, "E", "entry point");
71  }
72 
73  if (r & BLK_CFGHEAD) {
74  add_to_reason_string(result, true, do_pad, "H", "CFG head");
75  } else if (r & BLK_GRAPH1) {
76  add_to_reason_string(result, true, do_pad, "1", "graph-1");
77  } else if (r & BLK_GRAPH2) {
78  add_to_reason_string(result, true, do_pad, "2", "graph-2");
79  } else {
80  add_to_reason_string(result, (r & BLK_GRAPH3), do_pad, "3", "graph-3");
81  }
82 
83  if (r & BLK_USERDEF) {
84  add_to_reason_string(result, true, do_pad, "U", "user defined");
85  } else {
86  char abbr[32], full[64];
87  int width = snprintf(abbr, sizeof abbr, "%u", BLK_MISCMASK);
88  snprintf(abbr, sizeof abbr, "M%0*u", width, (r & BLK_MISCMASK));
89  abbr[sizeof(abbr)-1] = '\0';
90  if (!do_pad) {
91  std::string miscname = stringifySgAsmBlockReason((r & BLK_MISCMASK), "BLK_");
92  if (miscname.empty() || miscname[0]=='(') {
93  snprintf(full, sizeof full, "misc-%u", (r & BLK_MISCMASK));
94  } else {
95  for (size_t i=0; i<miscname.size(); ++i)
96  miscname[i] = tolower(miscname[i]);
97  strncpy(full, miscname.c_str(), sizeof full);
98  }
99  full[sizeof(full)-1] = '\0';
100  } else {
101  full[0] = '\0';
102  }
103  add_to_reason_string(result, (r & BLK_MISCMASK), do_pad, abbr, full);
104  }
105  return result;
106 }
107 
115 bool
117 {
118  static const rose_addr_t INVALID_ADDR = (rose_addr_t)(-1);
119  target_va = return_va = INVALID_ADDR;;
120  if (!is_basic_block())
121  return false;
122  std::vector<SgAsmInstruction*> insns = SageInterface::querySubTree<SgAsmInstruction>(this);
123  assert(!insns.empty()); // basic blocks must have instructions
124 
125  // Check that all the successors point to functions entry addresses (other functions or this block's function). There
126  // might be one edge that points to the fall-through address of this block, and that's ok.
127  SgAsmFunction *func = SageInterface::getEnclosingNode<SgAsmFunction>(this);
128  SgAsmInterpretation *interp = SageInterface::getEnclosingNode<SgAsmInterpretation>(func);
129  std::set<rose_addr_t> callee_vas;
130  if (interp) {
131  const InstructionMap &imap = interp->get_instruction_map();
132  const SgAsmIntegerValuePtrList &successors = get_successors();
133  for (SgAsmIntegerValuePtrList::const_iterator si=successors.begin(); si!=successors.end(); ++si) {
134  rose_addr_t successor_va = (*si)->get_absolute_value();
135  if (SgAsmInstruction *target_insn = imap.get_value_or(successor_va, NULL)) {
136  SgAsmFunction *target_func = SageInterface::getEnclosingNode<SgAsmFunction>(target_insn);
137  if (successor_va==target_func->get_entry_va()) {
138  callee_vas.insert(successor_va); // branches to a function entry point
139  } else if (return_va!=INVALID_ADDR) {
140  target_va = return_va = INVALID_ADDR;
141  return false; // multiple function-local CFG edges that are not this function's entry point
142  } else {
143  return_va = successor_va; // possible return address
144  }
145  }
146  }
147  }
148 
149  // Now for the architecture-dependent determination. This will not update target_va or return_va if they cannot be
150  // determined or are ambiguous; so we must reset them to INVALID_ADDR if we're about to return false.
151  bool retval = insns.front()->is_function_call(insns, &target_va, &return_va);
152  if (!retval) {
153  target_va = return_va = INVALID_ADDR;
154  } else if (INVALID_ADDR==target_va && 1==callee_vas.size()) {
155  target_va = *callee_vas.begin();
156  }
157  return retval;
158 }