void TranslatorX64::fCallArrayHelper(const Offset pcOff, const Offset pcNext) { DECLARE_FRAME_POINTER(framePtr); ActRec* fp = (ActRec*)framePtr->m_savedRbp; VMExecutionContext *ec = g_vmContext; ec->m_fp = fp; ec->m_stack.top() = sp; ec->m_pc = fp->unit()->at(pcOff); PC pc = fp->unit()->at(pcNext); tl_regState = VMRegState::CLEAN; bool runFunc = ec->doFCallArray(pc); sp = ec->m_stack.top(); tl_regState = VMRegState::DIRTY; if (!runFunc) return; ec->m_fp->m_savedRip = framePtr->m_savedRip; // smash our return and frame pointer chain framePtr->m_savedRip = (uint64_t)ec->m_fp->m_func->getFuncBody(); framePtr->m_savedRbp = (uint64_t)ec->m_fp; }
void XDebugProfiler::enableTracing(const String& filename, int64_t opts) { assert(!m_tracingEnabled); // Attempt to open the passed filename. php5 xdebug doesn't enable tracing // if we cannot open the file, so we need to open it now as opposed to when we // actually do the writing in order to ensure we handle this case. We keep the // file handle open in order to ensure we can still write on tracing stop FILE* file; if (opts & k_XDEBUG_TRACE_APPEND) { file = fopen(filename.data(), "a"); } else { file = fopen(filename.data(), "w"); } // If file is null, opening the passed filename failed. php5 xdebug doesn't // do anything in this case, but we should probably notify the user if (file == nullptr) { raise_warning("xdebug profiler failed to open tracing file %s for writing.", filename.data()); return; } m_tracingEnabled = true; m_tracingStartIdx = m_nextFrameIdx; m_tracingFilename = filename; m_tracingFile = file; m_tracingOpts = opts; // If we're not at the top level, need to grab the call sites for each frame // on the stack. VMRegAnchor _; Offset offset; ActRec* fp = vmfp(); while ((fp = g_context->getPrevVMState(fp, &offset)) != nullptr) { FrameData frame; frame.func = fp->func(); frame.line = fp->unit()->getLineNumber(offset); m_tracingStartFrameData.push_back(frame); } }