mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-06 15:29:31 +03:00
Fix Warnings
This commit is contained in:
parent
13b27252c1
commit
c2caa84f24
13 changed files with 90 additions and 69 deletions
|
@ -481,6 +481,7 @@
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_help.cpp" />
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_help.cpp" />
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_options.cpp" />
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_options.cpp" />
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_settings.cpp" />
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_settings.cpp" />
|
||||||
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_process_info.cpp" />
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_stats.cpp" />
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_stats.cpp" />
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_utils.cpp" />
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_utils.cpp" />
|
||||||
<ClCompile Include="..\..\src\random.c" />
|
<ClCompile Include="..\..\src\random.c" />
|
||||||
|
|
|
@ -76,6 +76,9 @@
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_settings.cpp">
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_settings.cpp">
|
||||||
<Filter>Sources\Windbg</Filter>
|
<Filter>Sources\Windbg</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_process_info.cpp">
|
||||||
|
<Filter>Sources\Windbg</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_stats.cpp">
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_stats.cpp">
|
||||||
<Filter>Sources\Windbg</Filter>
|
<Filter>Sources\Windbg</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -513,6 +513,7 @@
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_help.cpp" />
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_help.cpp" />
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_options.cpp" />
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_options.cpp" />
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_settings.cpp" />
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_settings.cpp" />
|
||||||
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_process_info.cpp" />
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_stats.cpp" />
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_stats.cpp" />
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_utils.cpp" />
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_utils.cpp" />
|
||||||
<ClCompile Include="..\..\src\random.c" />
|
<ClCompile Include="..\..\src\random.c" />
|
||||||
|
|
|
@ -79,6 +79,9 @@
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_settings.cpp">
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_settings.cpp">
|
||||||
<Filter>Sources\Windbg</Filter>
|
<Filter>Sources\Windbg</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_process_info.cpp">
|
||||||
|
<Filter>Sources\Windbg</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_stats.cpp">
|
<ClCompile Include="..\..\src\prim\windows\windbg\mimalloc_windbg_stats.cpp">
|
||||||
<Filter>Sources\Windbg</Filter>
|
<Filter>Sources\Windbg</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -71,7 +71,7 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK DebugExtensionInitialize(PULON
|
||||||
|
|
||||||
// Register output callbacks
|
// Register output callbacks
|
||||||
mi_register_output(
|
mi_register_output(
|
||||||
[](const char* msg, void* arg) {
|
[]([[maybe_unused]] const char* msg, [[maybe_unused]] void* arg) {
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, msg);
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, msg);
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "\n");
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "\n");
|
||||||
},
|
},
|
||||||
|
|
|
@ -38,6 +38,7 @@ Command: !mi_dump_arenas
|
||||||
including fragmentation and leaks.
|
including fragmentation and leaks.
|
||||||
*/
|
*/
|
||||||
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arenas(PDEBUG_CLIENT client, PCSTR args) {
|
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arenas(PDEBUG_CLIENT client, PCSTR args) {
|
||||||
|
UNREFERENCED_PARAMETER(client);
|
||||||
UNREFERENCED_PARAMETER(args);
|
UNREFERENCED_PARAMETER(args);
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
@ -52,66 +53,66 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arenas(PDEBUG_CLIENT c
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
||||||
PrintLink(subprocMainAddr, std::format("dx -r1 (*((mimalloc!mi_subproc_s *)0x{:016X}))", subprocMainAddr), "subproc_main");
|
PrintLink(subprocMainAddr, std::format("dx -r1 (*((mimalloc!mi_subproc_s *)0x{:016X}))", subprocMainAddr), "subproc_main");
|
||||||
|
|
||||||
mi_subproc_t subprocMain {};
|
auto subprocMain = std::make_unique<mi_subproc_t>();
|
||||||
hr = ReadMemory(subprocMainAddr, &subprocMain, sizeof(mi_subproc_t));
|
hr = ReadMemory(subprocMainAddr, subprocMain.get(), sizeof(mi_subproc_t));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read subproc_main at 0x%llx.\n", subprocMainAddr);
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read subproc_main at 0x%llx.\n", subprocMainAddr);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print results
|
// Print results
|
||||||
size_t arenaCount = subprocMain.arena_count.load();
|
size_t arenaCount = subprocMain->arena_count.load();
|
||||||
|
|
||||||
size_t totalSlices = 0;
|
double totalSlices = 0.0;
|
||||||
size_t totalCommittedSlices = 0;
|
double totalCommittedSlices = 0.0;
|
||||||
size_t totalCommittedPages = 0;
|
double totalCommittedPages = 0.0;
|
||||||
size_t totalAbandonedPages = 0;
|
double totalAbandonedPages = 0.0;
|
||||||
|
|
||||||
std::vector<float> potentialFragmentation;
|
std::vector<double> potentialFragmentation;
|
||||||
std::vector<float> highAbandonedPagesRatio;
|
std::vector<double> highAbandonedPagesRatio;
|
||||||
for (size_t i = 0; i < arenaCount; ++i) {
|
for (size_t i = 0; i < arenaCount; ++i) {
|
||||||
ULONG64 arenaAddr = subprocMainAddr + offsetof(mi_subproc_t, arenas) + (i * sizeof(std::atomic<mi_arena_t*>));
|
ULONG64 arenaAddr = subprocMainAddr + offsetof(mi_subproc_t, arenas) + (i * sizeof(std::atomic<mi_arena_t*>));
|
||||||
ULONG64 arenaValueAddr = 0;
|
ULONG64 arenaValueAddr = 0;
|
||||||
HRESULT hr = ReadMemory(arenaAddr, &arenaValueAddr, sizeof(ULONG64));
|
hr = ReadMemory(arenaAddr, &arenaValueAddr, sizeof(ULONG64));
|
||||||
if (FAILED(hr) || arenaValueAddr == 0) {
|
if (FAILED(hr) || arenaValueAddr == 0) {
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read mi_arena_t pointer at 0x%016llx.\n", arenaAddr);
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read mi_arena_t pointer at 0x%016llx.\n", arenaAddr);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
mi_arena_t arena {};
|
auto arena = std::make_unique<mi_arena_t>();
|
||||||
hr = ReadMemory(arenaValueAddr, &arena, sizeof(mi_arena_t));
|
hr = ReadMemory(arenaValueAddr, arena.get(), sizeof(mi_arena_t));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read mi_arena_t at 0x%016llx.\n", arenaAddr);
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read mi_arena_t at 0x%016llx.\n", arenaAddr);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
totalSlices += arena.slice_count;
|
totalSlices += arena->slice_count;
|
||||||
|
|
||||||
// Count committed slices using the bitmap in arena->slices_committed.
|
// Count committed slices using the bitmap in arena->slices_committed.
|
||||||
mi_bitmap_t slicesCommitted {};
|
auto slicesCommitted = std::make_unique<mi_bitmap_t>();
|
||||||
hr = ReadMemory(reinterpret_cast<ULONG64>(arena.slices_committed), &slicesCommitted, sizeof(mi_bitmap_t));
|
hr = ReadMemory(reinterpret_cast<ULONG64>(arena->slices_committed), slicesCommitted.get(), sizeof(mi_bitmap_t));
|
||||||
if (FAILED(hr) || arenaValueAddr == 0) {
|
if (FAILED(hr) || arenaValueAddr == 0) {
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read arena.slices_committed pointer at 0x%016llx.\n", reinterpret_cast<ULONG64>(arena.slices_committed));
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read arena.slices_committed pointer at 0x%016llx.\n", reinterpret_cast<ULONG64>(arena->slices_committed));
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t committed = mi_bitmap_count(&slicesCommitted);
|
size_t committed = mi_bitmap_count(slicesCommitted.get());
|
||||||
totalCommittedSlices += committed;
|
totalCommittedSlices += committed;
|
||||||
|
|
||||||
// Count committed pages using the bitmap in arena->pages.
|
// Count committed pages using the bitmap in arena->pages.
|
||||||
mi_bitmap_t pages {};
|
auto pages = std::make_unique<mi_bitmap_t>();
|
||||||
hr = ReadMemory(reinterpret_cast<ULONG64>(arena.pages), &pages, sizeof(mi_bitmap_t));
|
hr = ReadMemory(reinterpret_cast<ULONG64>(arena->pages), pages.get(), sizeof(mi_bitmap_t));
|
||||||
if (FAILED(hr) || arenaValueAddr == 0) {
|
if (FAILED(hr) || arenaValueAddr == 0) {
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read pages pointer at 0x%016llx.\n", reinterpret_cast<ULONG64>(arena.pages));
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read pages pointer at 0x%016llx.\n", reinterpret_cast<ULONG64>(arena->pages));
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
size_t committedPages = mi_bitmap_count(&pages);
|
size_t committedPages = mi_bitmap_count(pages.get());
|
||||||
totalCommittedPages += committedPages;
|
totalCommittedPages += committedPages;
|
||||||
|
|
||||||
// For abandoned pages, iterate over each bin (0 to MI_BIN_COUNT - 1).
|
// For abandoned pages, iterate over each bin (0 to MI_BIN_COUNT - 1).
|
||||||
size_t abandonedPages = 0;
|
size_t abandonedPages = 0;
|
||||||
for (int bin = 0; bin < MI_BIN_COUNT; bin++) {
|
for (int bin = 0; bin < MI_BIN_COUNT; bin++) {
|
||||||
ULONG64 itemAdr = reinterpret_cast<ULONG64>(arena.pages_abandoned[bin]);
|
ULONG64 itemAdr = reinterpret_cast<ULONG64>(arena->pages_abandoned[bin]);
|
||||||
mi_bitmap_t abandonedBmp {};
|
mi_bitmap_t abandonedBmp {};
|
||||||
hr = ReadMemory(itemAdr, &abandonedBmp, sizeof(mi_bitmap_t));
|
hr = ReadMemory(itemAdr, &abandonedBmp, sizeof(mi_bitmap_t));
|
||||||
if (FAILED(hr) || arenaValueAddr == 0) {
|
if (FAILED(hr) || arenaValueAddr == 0) {
|
||||||
|
@ -125,10 +126,10 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arenas(PDEBUG_CLIENT c
|
||||||
totalAbandonedPages += abandonedPages;
|
totalAbandonedPages += abandonedPages;
|
||||||
|
|
||||||
// --- Anomaly Detection ---
|
// --- Anomaly Detection ---
|
||||||
float pctCommittedSlices = (arena.slice_count > 0) ? (committed * 100.0 / arena.slice_count) : 0.0;
|
auto pctCommittedSlices = (arena->slice_count > 0) ? (committed * 100.0 / arena->slice_count) : 0.0;
|
||||||
potentialFragmentation.push_back(pctCommittedSlices);
|
potentialFragmentation.push_back(pctCommittedSlices);
|
||||||
|
|
||||||
float abandonedPagesRatio = 0.0;
|
auto abandonedPagesRatio = 0.0;
|
||||||
if (committedPages > 0 && abandonedPages > 0) {
|
if (committedPages > 0 && abandonedPages > 0) {
|
||||||
abandonedPagesRatio = (abandonedPages * 100.0) / committedPages;
|
abandonedPagesRatio = (abandonedPages * 100.0) / committedPages;
|
||||||
}
|
}
|
||||||
|
@ -163,6 +164,8 @@ Command: !mi_dump_arena <arena_address>
|
||||||
critical components of the arena.
|
critical components of the arena.
|
||||||
*/
|
*/
|
||||||
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arena(PDEBUG_CLIENT client, PCSTR args) {
|
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arena(PDEBUG_CLIENT client, PCSTR args) {
|
||||||
|
UNREFERENCED_PARAMETER(client);
|
||||||
|
|
||||||
if (!args || !*args) {
|
if (!args || !*args) {
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "Usage: !mi_dump_arena <arena_address>\n");
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "Usage: !mi_dump_arena <arena_address>\n");
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
@ -184,51 +187,51 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arena(PDEBUG_CLIENT cl
|
||||||
PrintLink(arenaAddr, std::format("dx -r1 ((mimalloc!mi_arena_s *)0x{:016X})", arenaValueAddr), std::format("Dumping Arena at Address: 0x{:016X}\n", arenaAddr));
|
PrintLink(arenaAddr, std::format("dx -r1 ((mimalloc!mi_arena_s *)0x{:016X})", arenaValueAddr), std::format("Dumping Arena at Address: 0x{:016X}\n", arenaAddr));
|
||||||
|
|
||||||
// Read the `mi_arena_t` structure from the memory
|
// Read the `mi_arena_t` structure from the memory
|
||||||
mi_arena_t arena {};
|
auto arena = std::make_unique<mi_arena_t>();
|
||||||
hr = ReadMemory(arenaValueAddr, &arena, sizeof(mi_arena_t));
|
hr = ReadMemory(arenaValueAddr, arena.get(), sizeof(mi_arena_t));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read mi_arena_t at 0x%016llx.\n", arenaAddr);
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read mi_arena_t at 0x%016llx.\n", arenaAddr);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "[0x%p] - Slice Count: %llu\n", arenaAddr + offsetof(mi_arena_t, slice_count), arena.slice_count);
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "[0x%p] - Slice Count: %llu\n", arenaAddr + offsetof(mi_arena_t, slice_count), arena->slice_count);
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "[0x%p] - Info Slices: %llu\n", arenaAddr + offsetof(mi_arena_t, info_slices), arena.info_slices);
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "[0x%p] - Info Slices: %llu\n", arenaAddr + offsetof(mi_arena_t, info_slices), arena->info_slices);
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "[0x%p] - NUMA Node: %d\n", arenaAddr + offsetof(mi_arena_t, numa_node), arena.numa_node);
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "[0x%p] - NUMA Node: %d\n", arenaAddr + offsetof(mi_arena_t, numa_node), arena->numa_node);
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "[0x%p] - Exclusive: %s\n", arenaAddr + offsetof(mi_arena_t, is_exclusive), arena.is_exclusive ? "Yes" : "No");
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "[0x%p] - Exclusive: %s\n", arenaAddr + offsetof(mi_arena_t, is_exclusive), arena->is_exclusive ? "Yes" : "No");
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "[0x%p] - Purge Expire: %d\n", arenaAddr + offsetof(mi_arena_t, purge_expire), arena.purge_expire.load());
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "[0x%p] - Purge Expire: %d\n", arenaAddr + offsetof(mi_arena_t, purge_expire), arena->purge_expire.load());
|
||||||
|
|
||||||
size_t totalSlices = 0;
|
double totalSlices = 0.0;
|
||||||
size_t totalCommittedSlices = 0;
|
double totalCommittedSlices = 0.0;
|
||||||
size_t totalCommittedPages = 0;
|
double totalCommittedPages = 0.0;
|
||||||
size_t totalAbandonedPages = 0;
|
double totalAbandonedPages = 0.0;
|
||||||
|
|
||||||
totalSlices += arena.slice_count;
|
totalSlices += arena->slice_count;
|
||||||
|
|
||||||
// Count committed slices using the bitmap in arena->slices_committed.
|
// Count committed slices using the bitmap in arena->slices_committed.
|
||||||
mi_bitmap_t slicesCommitted {};
|
auto slicesCommitted = std::make_unique<mi_bitmap_t>();
|
||||||
hr = ReadMemory(reinterpret_cast<ULONG64>(arena.slices_committed), &slicesCommitted, sizeof(mi_bitmap_t));
|
hr = ReadMemory(reinterpret_cast<ULONG64>(arena->slices_committed), slicesCommitted.get(), sizeof(mi_bitmap_t));
|
||||||
if (FAILED(hr) || arenaValueAddr == 0) {
|
if (FAILED(hr) || arenaValueAddr == 0) {
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read arena.slices_committed pointer at 0x%016llx.\n", reinterpret_cast<ULONG64>(arena.slices_committed));
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read arena.slices_committed pointer at 0x%016llx.\n", reinterpret_cast<ULONG64>(arena->slices_committed));
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t committed = mi_bitmap_count(&slicesCommitted);
|
size_t committed = mi_bitmap_count(slicesCommitted.get());
|
||||||
totalCommittedSlices += committed;
|
totalCommittedSlices += committed;
|
||||||
|
|
||||||
// Count committed pages using the bitmap in arena->pages.
|
// Count committed pages using the bitmap in arena->pages.
|
||||||
mi_bitmap_t pages {};
|
auto pages = std::make_unique<mi_bitmap_t>();
|
||||||
hr = ReadMemory(reinterpret_cast<ULONG64>(arena.pages), &pages, sizeof(mi_bitmap_t));
|
hr = ReadMemory(reinterpret_cast<ULONG64>(arena->pages), pages.get(), sizeof(mi_bitmap_t));
|
||||||
if (FAILED(hr) || arenaValueAddr == 0) {
|
if (FAILED(hr) || arenaValueAddr == 0) {
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read pages pointer at 0x%016llx.\n", reinterpret_cast<ULONG64>(arena.pages));
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read pages pointer at 0x%016llx.\n", reinterpret_cast<ULONG64>(arena->pages));
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
size_t committedPages = mi_bitmap_count(&pages);
|
size_t committedPages = mi_bitmap_count(pages.get());
|
||||||
totalCommittedPages += committedPages;
|
totalCommittedPages += committedPages;
|
||||||
|
|
||||||
// For abandoned pages, iterate over each bin (0 to MI_BIN_COUNT - 1).
|
// For abandoned pages, iterate over each bin (0 to MI_BIN_COUNT - 1).
|
||||||
size_t abandonedPages = 0;
|
size_t abandonedPages = 0;
|
||||||
for (int bin = 0; bin < MI_BIN_COUNT; bin++) {
|
for (int bin = 0; bin < MI_BIN_COUNT; bin++) {
|
||||||
ULONG64 itemAdr = reinterpret_cast<ULONG64>(arena.pages_abandoned[bin]);
|
ULONG64 itemAdr = reinterpret_cast<ULONG64>(arena->pages_abandoned[bin]);
|
||||||
mi_bitmap_t abandonedBmp {};
|
mi_bitmap_t abandonedBmp {};
|
||||||
hr = ReadMemory(itemAdr, &abandonedBmp, sizeof(mi_bitmap_t));
|
hr = ReadMemory(itemAdr, &abandonedBmp, sizeof(mi_bitmap_t));
|
||||||
if (FAILED(hr) || arenaValueAddr == 0) {
|
if (FAILED(hr) || arenaValueAddr == 0) {
|
||||||
|
@ -245,9 +248,9 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arena(PDEBUG_CLIENT cl
|
||||||
PrintArenaSummary(totalSlices, totalCommittedSlices, totalCommittedPages, totalAbandonedPages);
|
PrintArenaSummary(totalSlices, totalCommittedSlices, totalCommittedPages, totalAbandonedPages);
|
||||||
|
|
||||||
// --- Anomaly Detection ---
|
// --- Anomaly Detection ---
|
||||||
float pctCommittedSlices = (arena.slice_count > 0) ? (committed * 100.0 / arena.slice_count) : 0.0;
|
auto pctCommittedSlices = (arena->slice_count > 0) ? (committed * 100.0 / arena->slice_count) : 0.0;
|
||||||
|
|
||||||
float abandonedPagesRatio = 0.0;
|
double abandonedPagesRatio = 0.0;
|
||||||
if (committedPages > 0 && abandonedPages > 0) {
|
if (committedPages > 0 && abandonedPages > 0) {
|
||||||
abandonedPagesRatio = (abandonedPages * 100.0) / committedPages;
|
abandonedPagesRatio = (abandonedPages * 100.0) / committedPages;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,9 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
Command: !mi_show_help
|
Command: !mi_show_help
|
||||||
*/
|
*/
|
||||||
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_show_help(PDEBUG_CLIENT client, PCSTR args) {
|
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_show_help(PDEBUG_CLIENT client, PCSTR args) {
|
||||||
|
UNREFERENCED_PARAMETER(client);
|
||||||
UNREFERENCED_PARAMETER(args);
|
UNREFERENCED_PARAMETER(args);
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
||||||
|
|
||||||
// Print Help
|
// Print Help
|
||||||
|
|
|
@ -8,6 +8,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
#include "mimalloc_windbg_utils.h"
|
#include "mimalloc_windbg_utils.h"
|
||||||
|
|
||||||
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_options(PDEBUG_CLIENT client, PCSTR args) {
|
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_options(PDEBUG_CLIENT client, PCSTR args) {
|
||||||
|
UNREFERENCED_PARAMETER(client);
|
||||||
UNREFERENCED_PARAMETER(args);
|
UNREFERENCED_PARAMETER(args);
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
|
@ -11,6 +11,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
Command: !mi_dump_process_info
|
Command: !mi_dump_process_info
|
||||||
*/
|
*/
|
||||||
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_process_info(PDEBUG_CLIENT client, PCSTR args) {
|
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_process_info(PDEBUG_CLIENT client, PCSTR args) {
|
||||||
|
UNREFERENCED_PARAMETER(client);
|
||||||
UNREFERENCED_PARAMETER(args);
|
UNREFERENCED_PARAMETER(args);
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
@ -72,13 +73,18 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_process_info(PDEBUG_CL
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the command line string
|
// Read the command line string
|
||||||
std::wstring commandLine;
|
std::wstring commandLineWide;
|
||||||
hr = ReadWideString(cmdLine.Buffer, commandLine, cmdLine.Length / sizeof(WCHAR));
|
hr = ReadWideString(cmdLine.Buffer, commandLineWide, cmdLine.Length / sizeof(WCHAR));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read CommandLine string.\n");
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "ERROR: Failed to read CommandLine string.\n");
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert wide string to narrow string
|
||||||
|
std::string commandLine;
|
||||||
|
commandLine.resize(cmdLine.Length / sizeof(WCHAR) + 1); // +1 for null terminator
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, commandLineWide.c_str(), -1, commandLine.data(), commandLine.size(), nullptr, nullptr);
|
||||||
|
|
||||||
// Get Processor Type (x86, x64, ARM64, etc.)
|
// Get Processor Type (x86, x64, ARM64, etc.)
|
||||||
ULONG processorType = 0;
|
ULONG processorType = 0;
|
||||||
hr = g_DebugControl->GetActualProcessorType(&processorType);
|
hr = g_DebugControl->GetActualProcessorType(&processorType);
|
||||||
|
@ -103,7 +109,7 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_process_info(PDEBUG_CL
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output debuggee process info
|
// Output debuggee process info
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "Debugging Process (From Debuggee Context):\n");
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "Process Info:\n");
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, " Process ID : %u (0x%X)\n", processId, processId);
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, " Process ID : %u (0x%X)\n", processId, processId);
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, " Command Line : %s\n", commandLine.c_str());
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, " Command Line : %s\n", commandLine.c_str());
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, " Architecture : %s\n", arch);
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, " Architecture : %s\n", arch);
|
||||||
|
|
|
@ -11,10 +11,9 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
Command: !mi_show_extension_settings
|
Command: !mi_show_extension_settings
|
||||||
*/
|
*/
|
||||||
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_show_extension_settings(PDEBUG_CLIENT client, PCSTR args) {
|
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_show_extension_settings(PDEBUG_CLIENT client, PCSTR args) {
|
||||||
|
UNREFERENCED_PARAMETER(client);
|
||||||
UNREFERENCED_PARAMETER(args);
|
UNREFERENCED_PARAMETER(args);
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
||||||
|
|
||||||
g_DebugControl->ControlledOutput(DEBUG_OUTCTL_AMBIENT_DML, DEBUG_OUTPUT_NORMAL,
|
g_DebugControl->ControlledOutput(DEBUG_OUTCTL_AMBIENT_DML, DEBUG_OUTPUT_NORMAL,
|
||||||
|
@ -38,6 +37,8 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_show_extension_settings(PDE
|
||||||
Command: !mi_set_extension_setting
|
Command: !mi_set_extension_setting
|
||||||
*/
|
*/
|
||||||
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_set_extension_setting(PDEBUG_CLIENT client, PCSTR args) {
|
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_set_extension_setting(PDEBUG_CLIENT client, PCSTR args) {
|
||||||
|
UNREFERENCED_PARAMETER(client);
|
||||||
|
|
||||||
if (!args || !*args) {
|
if (!args || !*args) {
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "Usage: !mi_set_extension_setting <setting> <value>\n");
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, "Usage: !mi_set_extension_setting <setting> <value>\n");
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
@ -45,8 +46,11 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_set_extension_setting(PDEBU
|
||||||
|
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
||||||
|
|
||||||
char fieldName[64];
|
char fieldName[64] = {};
|
||||||
char valueStr[64];
|
char valueStr[64] = {};
|
||||||
|
|
||||||
|
memset(fieldName, 0, sizeof(fieldName));
|
||||||
|
memset(valueStr, 0, sizeof(valueStr));
|
||||||
|
|
||||||
// Parse the input arguments
|
// Parse the input arguments
|
||||||
if (sscanf_s(args, "%63s %63s", fieldName, (unsigned)_countof(fieldName), valueStr, (unsigned)_countof(valueStr)) != 2) {
|
if (sscanf_s(args, "%63s %63s", fieldName, (unsigned)_countof(fieldName), valueStr, (unsigned)_countof(valueStr)) != 2) {
|
||||||
|
@ -54,8 +58,6 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_set_extension_setting(PDEBU
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
// Update the setting based on the field name
|
// Update the setting based on the field name
|
||||||
if (strcmp(fieldName, "MinCommittedSlicesPct") == 0) {
|
if (strcmp(fieldName, "MinCommittedSlicesPct") == 0) {
|
||||||
double doubleValue = 0.0;
|
double doubleValue = 0.0;
|
||||||
|
|
|
@ -45,6 +45,7 @@ Command: !mi_dump_stats
|
||||||
-
|
-
|
||||||
*/
|
*/
|
||||||
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_stats(PDEBUG_CLIENT client, PCSTR args) {
|
extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_stats(PDEBUG_CLIENT client, PCSTR args) {
|
||||||
|
UNREFERENCED_PARAMETER(client);
|
||||||
UNREFERENCED_PARAMETER(args);
|
UNREFERENCED_PARAMETER(args);
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
|
@ -6,7 +6,6 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "mimalloc_windbg_utils.h"
|
#include "mimalloc_windbg_utils.h"
|
||||||
#include <array>
|
|
||||||
|
|
||||||
ULONG64 g_MiMallocBase = 0;
|
ULONG64 g_MiMallocBase = 0;
|
||||||
|
|
||||||
|
@ -78,7 +77,7 @@ HRESULT GetNtSymbolOffset(const char* typeName, const char* fieldName, ULONG& ou
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to read memory from the debuggee process
|
// Function to read memory from the debuggee process
|
||||||
HRESULT ReadMemory(const char* symbolName, void* outBuffer, size_t bufferSize) {
|
HRESULT ReadMemory(const char* symbolName, void* outBuffer, ULONG bufferSize) {
|
||||||
if (!g_DataSpaces) {
|
if (!g_DataSpaces) {
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +100,7 @@ HRESULT ReadMemory(const char* symbolName, void* outBuffer, size_t bufferSize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to read memory from a specific address
|
// Function to read memory from a specific address
|
||||||
HRESULT ReadMemory(ULONG64 address, void* outBuffer, size_t bufferSize) {
|
HRESULT ReadMemory(ULONG64 address, void* outBuffer, ULONG bufferSize) {
|
||||||
if (!g_DataSpaces) {
|
if (!g_DataSpaces) {
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +131,7 @@ HRESULT ReadString(const char* symbolName, std::string& outBuffer) {
|
||||||
|
|
||||||
// Step 2: Read the actual string data from the debuggee memory
|
// Step 2: Read the actual string data from the debuggee memory
|
||||||
char tempChar = 0;
|
char tempChar = 0;
|
||||||
size_t length = 0;
|
ULONG length = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
hr = g_DataSpaces->ReadVirtual(stringPtr + length, &tempChar, sizeof(char), nullptr);
|
hr = g_DataSpaces->ReadVirtual(stringPtr + length, &tempChar, sizeof(char), nullptr);
|
||||||
|
@ -189,11 +188,12 @@ size_t mi_bitmap_count(mi_bitmap_t* bmp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FormatSize(std::size_t bytes) {
|
std::string FormatSize(std::size_t bytes) {
|
||||||
constexpr std::array<const char*, 6> suffixes = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"};
|
const char* suffixes[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"};
|
||||||
|
constexpr int maxIndex = static_cast<int>(std::size(suffixes)) - 1;
|
||||||
double size = static_cast<double>(bytes);
|
double size = static_cast<double>(bytes);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
while (size >= 1024.0 && index < suffixes.size() - 1) {
|
while (size >= 1024.0 && index < maxIndex) {
|
||||||
size /= 1024.0;
|
size /= 1024.0;
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
@ -202,10 +202,11 @@ std::string FormatSize(std::size_t bytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FormatNumber(double num) {
|
std::string FormatNumber(double num) {
|
||||||
constexpr std::array<const char*, 5> suffixes = {"", "K", "M", "B", "T"};
|
const char* suffixes[] = {"", "K", "M", "B", "T"};
|
||||||
|
constexpr int maxIndex = static_cast<int>(std::size(suffixes)) - 1;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
while (num >= 1000.0 && index < suffixes.size() - 1) {
|
while (num >= 1000.0 && index < maxIndex) {
|
||||||
num /= 1000.0;
|
num /= 1000.0;
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,8 @@ static inline double MaxAbandonedPagesRatio = 0.4; // If abandoned pages exceed
|
||||||
HRESULT FindMimallocBase();
|
HRESULT FindMimallocBase();
|
||||||
HRESULT GetSymbolOffset(const char* symbolName, ULONG64& outOffset);
|
HRESULT GetSymbolOffset(const char* symbolName, ULONG64& outOffset);
|
||||||
HRESULT GetNtSymbolOffset(const char* typeName, const char* fieldName, ULONG& outOffset);
|
HRESULT GetNtSymbolOffset(const char* typeName, const char* fieldName, ULONG& outOffset);
|
||||||
HRESULT ReadMemory(const char* symbolName, void* outBuffer, size_t bufferSize);
|
HRESULT ReadMemory(const char* symbolName, void* outBuffer, ULONG bufferSize);
|
||||||
HRESULT ReadMemory(ULONG64 address, void* outBuffer, size_t bufferSize);
|
HRESULT ReadMemory(ULONG64 address, void* outBuffer, ULONG bufferSize);
|
||||||
HRESULT ReadString(const char* symbolName, std::string& outBuffer);
|
HRESULT ReadString(const char* symbolName, std::string& outBuffer);
|
||||||
HRESULT ReadWideString(ULONG64 address, std::wstring& outString, size_t maxLength = 1024);
|
HRESULT ReadWideString(ULONG64 address, std::wstring& outString, size_t maxLength = 1024);
|
||||||
size_t mi_bitmap_count(mi_bitmap_t* bmp);
|
size_t mi_bitmap_count(mi_bitmap_t* bmp);
|
||||||
|
|
Loading…
Add table
Reference in a new issue