Beispiel #1
0
Offset instrJumpTarget(PC instrs, Offset pos) {
  Offset* offset = instrJumpOffset(instrs + pos);

  if (!offset) {
    return InvalidAbsoluteOffset;
  } else {
    return *offset + pos;
  }
}
Beispiel #2
0
Offset instrJumpTarget(const Opcode* instrs, Offset pos) {
  Offset* offset = instrJumpOffset(const_cast<Opcode*>(instrs + pos));

  if (!offset) {
    return InvalidAbsoluteOffset;
  } else {
    return *offset + pos;
  }
}
Beispiel #3
0
/**
 * Return the number of successor-edges including fall-through paths but not
 * implicit exception paths.
 */
int numSuccs(const Opcode* instr) {
  if (!instrIsControlFlow(*instr)) return 1;
  if ((instrFlags(*instr) & TF) != 0) {
    if (Op(*instr) == OpSwitch) return *(int*)(instr + 1);
    if (Op(*instr) == OpJmp) return 1;
    return 0;
  }
  if (instrJumpOffset(const_cast<Opcode*>(instr))) return 2;
  return 1;
}
Beispiel #4
0
/**
 * Return the number of successor-edges including fall-through paths but not
 * implicit exception paths.
 */
int numSuccs(const Op* instr) {
  if ((instrFlags(*instr) & TF) != 0) {
    if (isSwitch(*instr)) {
      return *(int*)(instr + 1);
    }
    if (isUnconditionalJmp(*instr) || *instr == OpIterBreak) return 1;
    return 0;
  }
  if (!instrIsControlFlow(*instr)) return 1;
  if (instrJumpOffset(const_cast<Op*>(instr))) return 2;
  return 1;
}
Beispiel #5
0
/**
 * Return the number of successor-edges including fall-through paths but not
 * implicit exception paths.
 */
int numSuccs(PC const origPC) {
  auto pc = origPC;
  auto const op = decode_op(pc);
  if ((instrFlags(op) & TF) != 0) {
    if (isSwitch(op)) {
      return decode_raw<int32_t>(pc);
    }
    if (isUnconditionalJmp(op) || op == OpIterBreak) return 1;
    return 0;
  }
  if (!instrIsControlFlow(op)) return 1;
  if (instrJumpOffset(origPC)) return 2;
  return 1;
}
Beispiel #6
0
/*
 * This function returns the offset of instruction i's branch target.
 * This is normally the offset corresponding to the branch being
 * taken.  However, if i does not break a trace and it's followed in
 * the trace by the instruction in the taken branch, then this
 * function returns the offset of the i's fall-through instruction.
 * In that case, the invertCond output argument is set to true;
 * otherwise it's set to false.
 */
static Offset getBranchTarget(const NormalizedInstruction& i,
                              bool& invertCond) {
  assert(instrJumpOffset((Op*)(i.pc())) != nullptr);
  Offset targetOffset = i.offset() + i.imm[1].u_BA;
  invertCond = false;

  if (!i.endsRegion && i.nextOffset == targetOffset) {
    invertCond = true;
    Offset fallthruOffset = i.offset() + instrLen((Op*)i.pc());
    targetOffset = fallthruOffset;
  }

  return targetOffset;
}
Beispiel #7
0
/**
 * Return the number of successor-edges including fall-through paths but not
 * implicit exception paths.
 */
int numSuccs(PC const origPC) {
  auto pc = origPC;
  auto const op = decode_op(pc);
  if ((instrFlags(op) & TF) != 0) {
    if (isSwitch(op)) {
      if (op == Op::Switch) {
        decode_raw<SwitchKind>(pc); // skip bounded flag
        decode_raw<int64_t>(pc); // skip base
      }
      return decode_raw<int32_t>(pc); // vector length
    }
    if (isUnconditionalJmp(op) || op == OpIterBreak) return 1;
    return 0;
  }
  if (!instrIsControlFlow(op)) return 1;
  if (instrJumpOffset(origPC)) return 2;
  return 1;
}
Beispiel #8
0
void BCPattern::matchAnchored(const Expr& pattern,
                              PC start, PC end, Result& result) {
  auto pos = pattern.begin();

  for (auto inst = start; inst != end; ) {
    // Detect a match.
    if (pos == pattern.end()) {
      result.m_start = start;
      result.m_end = inst;
      return;
    }

    auto const op = peek_op(inst);

    // Skip pattern-globally ignored opcodes.
    if (m_ignores.count(op)) {
      inst = next(inst);
      continue;
    }

    // Check for alternations whenever we fail to match.
    auto nomatch = [&] {
      if (!pos->hasAlt()) return result.erase();

      // Pop the capture if we made one.
      if (pos->shouldCapture()) {
        result.m_captures.pop_back();
      }

      for (auto const& atom : pos->getAlt()) {
        // Construct the full alternate pattern.
        auto alt = Expr { atom };
        alt.insert(alt.end(), std::next(pos), pattern.end());
        auto res = result;

        // Match on the alternate.
        matchAnchored(alt, inst, end, res);

        if (res.found()) {
          result = res;
          result.m_start = start;
          return;
        }
      }
      return result.erase();
    };

    // Capture the atom if desired.
    if (pos->shouldCapture()) {
      result.m_captures.push_back(inst);
    }

    // Check for shallow match.
    if (pos->op() != op) {
      return nomatch();
    }

    auto filter = pos->getFilter();

    // Check for deep match if desired.
    if (filter && !filter(inst, result.m_captures)) {
      return nomatch();
    }

    if ((pos->op() == Op::JmpZ || pos->op() == Op::JmpNZ)) {
      // Match the taken block, if there is one.
      auto off = instrJumpOffset(inst);
      assert(off);

      auto res = result;
      matchAnchored(pos->getTaken(), inst + *off, end, res);

      if (!res.found()) {
        return nomatch();
      }

      // Grab the captures.
      result.m_captures = res.m_captures;
    }

    if (pos->hasSeq()) {
      // Match the subsequence if we have one.
      auto res = result;
      matchAnchored(pos->getSeq(), next(inst), end, res);

      if (!res.found()) {
        return nomatch();
      }

      // Set the PC.
      result.m_captures = res.m_captures;
      inst = res.m_end;
    } else {
      // Step the PC.
      inst = next(inst);
    }

    // Step the pattern.
    ++pos;
  }

  // Detect a terminal match.
  if (pos == pattern.end()) {
    result.m_start = start;
    result.m_end = end;
  }
}
Beispiel #9
0
Offset instrJumpTarget(PC instrs, Offset pos) {
  auto offset = instrJumpOffset(instrs + pos);
  return offset ? *offset + pos : InvalidAbsoluteOffset;
}