Index: trunk/src/VBox/VMM/Makefile.kmk
===================================================================
--- trunk/src/VBox/VMM/Makefile.kmk	(revision 89694)
+++ trunk/src/VBox/VMM/Makefile.kmk	(revision 89695)
@@ -119,5 +119,5 @@
 	VMMR3/DBGFR3Trace.cpp \
 	$(if-expr defined(VBOX_WITH_DBGF_TRACING), VMMR3/DBGFR3Tracer.cpp,) \
-	$(if-expr defined(VBOX_WITH_DBGF_SAMPLE_REPORT), VMMR3/DBGFR3SampleReport.cpp,) \
+	VMMR3/DBGFR3SampleReport.cpp \
 	VMMR3/DBGFR3Type.cpp \
 	VMMR3/EM.cpp \
Index: trunk/src/VBox/VMM/VMMR3/DBGFR3SampleReport.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/DBGFR3SampleReport.cpp	(revision 89694)
+++ trunk/src/VBox/VMM/VMMR3/DBGFR3SampleReport.cpp	(revision 89695)
@@ -42,4 +42,5 @@
 #include <iprt/timer.h>
 #include <iprt/string.h>
+#include <iprt/stream.h>
 
 
@@ -132,4 +133,6 @@
     /** Number of microseconds left for sampling. */
     uint64_t                         cSampleUsLeft;
+    /** The report created after sampling was stopped. */
+    char                             *pszReport;
     /** Array of per VCPU samples collected. */
     DBGFSAMPLEREPORTVCPU             aCpus[1];
@@ -331,9 +334,10 @@
  *
  * @returns nothing.
+ * @param   pHlp                    The debug info helper used for printing.
  * @param   pUVM                    The usermode VM handle.
  * @param   pFrame                  The frame to dump.
  * @param   idxFrame                The frame number.
  */
-static void dbgfR3SampleReportDumpFrame(PUVM pUVM, PCDBGFSAMPLEFRAME pFrame, uint32_t idxFrame)
+static void dbgfR3SampleReportDumpFrame(PCDBGFINFOHLP pHlp, PUVM pUVM, PCDBGFSAMPLEFRAME pFrame, uint32_t idxFrame)
 {
     RTGCINTPTR offDisp;
@@ -350,19 +354,20 @@
             const char *pszModName = hMod != NIL_RTDBGMOD ? RTDbgModName(hMod) : NULL;
 
-            LogRel(("%*s%RU64 %s+%llx (%s) [%RGv]\n", idxFrame * 4, " ",
-                                                      pFrame->cSamples,
-                                                      SymPC.szName, offDisp,
-                                                      hMod ? pszModName : "",
-                                                      pFrame->AddrFrame.FlatPtr));
+            pHlp->pfnPrintf(pHlp,
+                            "%*s%RU64 %s+%llx (%s) [%RGv]\n", idxFrame * 4, " ",
+                                                              pFrame->cSamples,
+                                                              SymPC.szName, offDisp,
+                                                              hMod ? pszModName : "",
+                                                              pFrame->AddrFrame.FlatPtr);
             RTDbgModRelease(hMod);
         }
         else
-            LogRel(("%*s%RU64 %RGv\n", idxFrame * 4, " ", pFrame->cSamples, pFrame->AddrFrame.FlatPtr));
+            pHlp->pfnPrintf(pHlp, "%*s%RU64 %RGv\n", idxFrame * 4, " ", pFrame->cSamples, pFrame->AddrFrame.FlatPtr);
     }
     else
-        LogRel(("%*s%RU64 %RGv\n", idxFrame * 4, " ", pFrame->cSamples, pFrame->AddrFrame.FlatPtr));
+        pHlp->pfnPrintf(pHlp, "%*s%RU64 %RGv\n", idxFrame * 4, " ", pFrame->cSamples, pFrame->AddrFrame.FlatPtr);
 
     for (uint32_t i = 0; i < pFrame->cFramesValid; i++)
-        dbgfR3SampleReportDumpFrame(pUVM, &pFrame->paFrames[i], idxFrame + 1);
+        dbgfR3SampleReportDumpFrame(pHlp, pUVM, &pFrame->paFrames[i], idxFrame + 1);
 }
 
@@ -441,5 +446,9 @@
             pThis->hTimer = NULL;
 
-#if 1
+            DBGFSAMPLEREPORTINFOHLP Hlp;
+            PCDBGFINFOHLP           pHlp = &Hlp.Core;
+
+            dbgfR3SampleReportInfoHlpInit(&Hlp);
+
             /* Some early dump code. */
             for (uint32_t i = 0; i < pThis->pUVM->cCpus; i++)
@@ -447,12 +456,7 @@
                 PCDBGFSAMPLEREPORTVCPU pSampleVCpu = &pThis->aCpus[i];
 
-                LogRel(("Sample report for vCPU %u:\n", i));
-                dbgfR3SampleReportDumpFrame(pThis->pUVM, &pSampleVCpu->FrameRoot, 0);
+                pHlp->pfnPrintf(pHlp, "Sample report for vCPU %u:\n", i);
+                dbgfR3SampleReportDumpFrame(pHlp, pThis->pUVM, &pSampleVCpu->FrameRoot, 0);
             }
-
-            DBGFSAMPLEREPORTINFOHLP Hlp;
-            PCDBGFINFOHLP           pHlp = &Hlp.Core;
-
-            dbgfR3SampleReportInfoHlpInit(&Hlp);
 
             /* Shameless copy from VMMGuruMeditation.cpp */
@@ -494,7 +498,10 @@
                             "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
 
-            LogRel(("%s", Hlp.pachBuf));
+            if (pThis->pszReport)
+                RTMemFree(pThis->pszReport);
+            pThis->pszReport = Hlp.pachBuf;
             dbgfR3SampleReportInfoHlpDelete(&Hlp);
-#endif
+
+            ASMAtomicXchgU32((volatile uint32_t *)&pThis->enmState, DBGFSAMPLEREPORTSTATE_READY);
 
             if (pThis->pfnProgress)
@@ -505,5 +512,4 @@
             }
 
-            ASMAtomicXchgU32((volatile uint32_t *)&pThis->enmState, DBGFSAMPLEREPORTSTATE_READY);
             DBGFR3SampleReportRelease(pThis);
         }
@@ -617,6 +623,4 @@
  * @returns New reference count, on 0 the sample report instance is destroyed.
  * @param   hSample                 Sample report handle.
- *
- * @note Can't be called from the progress callback passed during creation.
  */
 VMMR3DECL(uint32_t) DBGFR3SampleReportRelease(DBGFSAMPLEREPORT hSample)
@@ -718,4 +722,5 @@
  *
  * @returns VBox status code.
+ * @retval  VERR_INVALID_STATE if nothing was sampled so far for reporting.
  * @param   hSample                 Sample report handle.
  * @param   pszFilename             The filename to dump the report to.
@@ -723,6 +728,17 @@
 VMMR3DECL(int) DBGFR3SampleReportDumpToFile(DBGFSAMPLEREPORT hSample, const char *pszFilename)
 {
-    RT_NOREF(hSample, pszFilename);
-    return VINF_SUCCESS;
-}
-
+    PDBGFSAMPLEREPORTINT pThis = hSample;
+
+    AssertReturn(pThis->pszReport, VERR_INVALID_STATE);
+
+    PRTSTREAM hStream;
+    int rc = RTStrmOpen(pszFilename, "w", &hStream);
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTStrmPutStr(hStream, pThis->pszReport);
+        RTStrmClose(hStream);
+    }
+
+    return rc;
+}
+
