Пример #1
0
void
FixupMap::fixupWorkSimulated(ExecutionContext* ec) const {
  TRACE(1, "fixup(begin):\n");

  auto isVMFrame = [] (ActRec* ar, const vixl::Simulator* sim) {
    // If this assert is failing, you may have forgotten a sync point somewhere
    assert(ar);
    bool ret =
      uintptr_t(ar) - s_stackLimit >= s_stackSize &&
      !sim->is_on_stack(ar);
    assert(!ret ||
           (ar >= vmStack().getStackLowAddress() &&
            ar < vmStack().getStackHighAddress()) ||
           ar->resumed());
    return ret;
  };

  // For each nested simulator (corresponding to nested VM invocations), look at
  // its PC to find a potential fixup key.
  //
  // Callstack walking is necessary, because we may get called from a
  // uniqueStub.
  for (int i = ec->m_activeSims.size() - 1; i >= 0; --i) {
    auto const* sim = ec->m_activeSims[i];
    auto* rbp = reinterpret_cast<ActRec*>(sim->xreg(JIT::ARM::rVmFp.code()));
    auto tca = reinterpret_cast<TCA>(sim->pc());
    TRACE(2, "considering frame %p, %p\n", rbp, tca);

    while (rbp && !isVMFrame(rbp, sim)) {
      tca = reinterpret_cast<TCA>(rbp->m_savedRip);
      rbp = rbp->m_sfp;
    }

    if (!rbp) continue;

    auto* ent = m_fixups.find(tca);
    if (!ent) {
      continue;
    }

    if (ent->isIndirect()) {
      not_implemented();
    }

    VMRegs regs;
    regsFromActRec(tca, rbp, ent->fixup, &regs);
    TRACE(2, "fixup(end): func %s fp %p sp %p pc %p\b",
          regs.m_fp->m_func->name()->data(),
          regs.m_fp, regs.m_sp, regs.m_pc);
    vmfp() = const_cast<ActRec*>(regs.m_fp);
    vmpc() = reinterpret_cast<PC>(regs.m_pc);
    vmsp() = regs.m_sp;
    return;
  }

  // This shouldn't be reached.
  always_assert(false);
}
Пример #2
0
bool FixupMap::getFrameRegs(const ActRec* ar,
                            const ActRec* prevAr,
                            VMRegs* outVMRegs) const {
  CTCA tca = (CTCA)ar->m_savedRip;
  // Non-obvious off-by-one fun: if the *return address* points into the TC,
  // then the frame we were running on in the TC is actually the previous
  // frame.
  ar = ar->m_sfp;
  auto* ent = m_fixups.find(tca);
  if (!ent) return false;
  if (ent->isIndirect()) {
    // Note: if indirect fixups happen frequently enough, we could
    // just compare savedRip to be less than some threshold where
    // stubs in a.code stop.
    assertx(prevAr);
    auto pRealRip = ent->indirect.returnIpDisp +
      uintptr_t(prevAr->m_sfp);
    ent = m_fixups.find(*reinterpret_cast<CTCA*>(pRealRip));
    assertx(ent && !ent->isIndirect());
  }
  regsFromActRec(tca, ar, ent->fixup, outVMRegs);
  return true;
}