mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-19 18:03:47 +00:00
win: Attempt to fix unloaded modules list by using RtlGetUnloadEventTraceEx
I haven't been able to reproduce this locally, but we see errors in crash dumps where the unloaded module list consists of a number of modules with invalid names and implausible addresses. My assumption is that RTL_UNLOAD_EVENT_TRACE isn't correct for some OS levels. Instead of trying to finesse and test that, use RtlGetUnloadEventTraceEx() instead of RtlGetUnloadEventTrace(), which returns an element size. (This function is Vista+ which is why it wasn't used the first time around.) R=mark@chromium.org BUG=chromium:620175 Change-Id: I4d7080a03623276f9c1c038d6e7329af70e4a64c Reviewed-on: https://chromium-review.googlesource.com/421564 Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
parent
2e80cb7cb4
commit
0567536f86
@ -201,8 +201,8 @@ int CrashyMain(int argc, wchar_t* argv[]) {
|
|||||||
AllocateExtraUnsavedMemory(extra_ranges);
|
AllocateExtraUnsavedMemory(extra_ranges);
|
||||||
|
|
||||||
// Load and unload some uncommonly used modules so we can see them in the list
|
// Load and unload some uncommonly used modules so we can see them in the list
|
||||||
// reported by `lm`. At least two so that we confirm we got the size of
|
// reported by `lm`. At least two so that we confirm we got the element size
|
||||||
// RTL_UNLOAD_EVENT_TRACE right.
|
// advancement of RTL_UNLOAD_EVENT_TRACE correct.
|
||||||
CHECK(GetModuleHandle(L"lz32.dll") == nullptr);
|
CHECK(GetModuleHandle(L"lz32.dll") == nullptr);
|
||||||
CHECK(GetModuleHandle(L"wmerror.dll") == nullptr);
|
CHECK(GetModuleHandle(L"wmerror.dll") == nullptr);
|
||||||
HMODULE lz32 = LoadLibrary(L"lz32.dll");
|
HMODULE lz32 = LoadLibrary(L"lz32.dll");
|
||||||
|
@ -281,21 +281,43 @@ void ProcessSnapshotWin::InitializeUnloadedModules() {
|
|||||||
#error port
|
#error port
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RTL_UNLOAD_EVENT_TRACE<Traits>* unload_event_trace_address =
|
ULONG* element_size;
|
||||||
RtlGetUnloadEventTrace<Traits>();
|
ULONG* element_count;
|
||||||
WinVMAddress address_in_target_process =
|
void* event_trace_address;
|
||||||
reinterpret_cast<WinVMAddress>(unload_event_trace_address);
|
RtlGetUnloadEventTraceEx(&element_size, &element_count, &event_trace_address);
|
||||||
|
|
||||||
std::vector<RTL_UNLOAD_EVENT_TRACE<Traits>> events(
|
if (*element_size < sizeof(RTL_UNLOAD_EVENT_TRACE<Traits>)) {
|
||||||
RTL_UNLOAD_EVENT_TRACE_NUMBER);
|
LOG(ERROR) << "unexpected unloaded module list element size";
|
||||||
if (!process_reader_.ReadMemory(address_in_target_process,
|
|
||||||
events.size() * sizeof(events[0]),
|
|
||||||
&events[0])) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const RTL_UNLOAD_EVENT_TRACE<Traits>& uet : events) {
|
const WinVMAddress address_in_target_process =
|
||||||
if (uet.ImageName[0]) {
|
reinterpret_cast<WinVMAddress>(event_trace_address);
|
||||||
|
|
||||||
|
Traits::Pointer pointer_to_array;
|
||||||
|
if (!process_reader_.ReadMemory(address_in_target_process,
|
||||||
|
sizeof(pointer_to_array),
|
||||||
|
&pointer_to_array)) {
|
||||||
|
LOG(ERROR) << "failed to read target address";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No unloaded modules.
|
||||||
|
if (pointer_to_array == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const size_t data_size = *element_size * *element_count;
|
||||||
|
std::vector<uint8_t> data(data_size);
|
||||||
|
if (!process_reader_.ReadMemory(pointer_to_array, data_size, &data[0])) {
|
||||||
|
LOG(ERROR) << "failed to read unloaded module data";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ULONG i = 0; i < *element_count; ++i) {
|
||||||
|
const uint8_t* base_address = &data[i * *element_size];
|
||||||
|
const auto& uet =
|
||||||
|
*reinterpret_cast<const RTL_UNLOAD_EVENT_TRACE<Traits>*>(base_address);
|
||||||
|
if (uet.ImageName[0] != 0) {
|
||||||
unloaded_modules_.push_back(UnloadedModuleSnapshot(
|
unloaded_modules_.push_back(UnloadedModuleSnapshot(
|
||||||
uet.BaseAddress,
|
uet.BaseAddress,
|
||||||
uet.SizeOfImage,
|
uet.SizeOfImage,
|
||||||
|
@ -42,7 +42,9 @@ NTSTATUS NTAPI NtSuspendProcess(HANDLE);
|
|||||||
|
|
||||||
NTSTATUS NTAPI NtResumeProcess(HANDLE);
|
NTSTATUS NTAPI NtResumeProcess(HANDLE);
|
||||||
|
|
||||||
void* NTAPI RtlGetUnloadEventTrace();
|
VOID NTAPI RtlGetUnloadEventTraceEx(PULONG* ElementSize,
|
||||||
|
PULONG* ElementCount,
|
||||||
|
PVOID* EventTrace);
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
|
|
||||||
@ -145,12 +147,12 @@ NTSTATUS NtResumeProcess(HANDLE handle) {
|
|||||||
return nt_resume_process(handle);
|
return nt_resume_process(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Traits>
|
void RtlGetUnloadEventTraceEx(ULONG** element_size,
|
||||||
RTL_UNLOAD_EVENT_TRACE<Traits>* RtlGetUnloadEventTrace() {
|
ULONG** element_count,
|
||||||
static const auto rtl_get_unload_event_trace =
|
void** event_trace) {
|
||||||
GET_FUNCTION_REQUIRED(L"ntdll.dll", ::RtlGetUnloadEventTrace);
|
static const auto rtl_get_unload_event_trace_ex =
|
||||||
return reinterpret_cast<RTL_UNLOAD_EVENT_TRACE<Traits>*>(
|
GET_FUNCTION_REQUIRED(L"ntdll.dll", ::RtlGetUnloadEventTraceEx);
|
||||||
rtl_get_unload_event_trace());
|
rtl_get_unload_event_trace_ex(element_size, element_count, event_trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicit instantiations with the only 2 valid template arguments to avoid
|
// Explicit instantiations with the only 2 valid template arguments to avoid
|
||||||
@ -169,10 +171,4 @@ template NTSTATUS NtOpenThread<process_types::internal::Traits64>(
|
|||||||
const process_types::CLIENT_ID<process_types::internal::Traits64>*
|
const process_types::CLIENT_ID<process_types::internal::Traits64>*
|
||||||
client_id);
|
client_id);
|
||||||
|
|
||||||
template RTL_UNLOAD_EVENT_TRACE<process_types::internal::Traits32>*
|
|
||||||
RtlGetUnloadEventTrace<process_types::internal::Traits32>();
|
|
||||||
|
|
||||||
template RTL_UNLOAD_EVENT_TRACE<process_types::internal::Traits64>*
|
|
||||||
RtlGetUnloadEventTrace<process_types::internal::Traits64>();
|
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
@ -75,10 +75,7 @@ NTSTATUS NtSuspendProcess(HANDLE handle);
|
|||||||
|
|
||||||
NTSTATUS NtResumeProcess(HANDLE handle);
|
NTSTATUS NtResumeProcess(HANDLE handle);
|
||||||
|
|
||||||
// From https://msdn.microsoft.com/en-us/library/bb432428(VS.85).aspx and
|
// From https://msdn.microsoft.com/en-us/library/cc678403(v=vs.85).aspx.
|
||||||
// http://processhacker.sourceforge.net/doc/struct___r_t_l___u_n_l_o_a_d___e_v_e_n_t___t_r_a_c_e.html
|
|
||||||
#define RTL_UNLOAD_EVENT_TRACE_NUMBER 64
|
|
||||||
|
|
||||||
template <class Traits>
|
template <class Traits>
|
||||||
struct RTL_UNLOAD_EVENT_TRACE {
|
struct RTL_UNLOAD_EVENT_TRACE {
|
||||||
typename Traits::Pointer BaseAddress;
|
typename Traits::Pointer BaseAddress;
|
||||||
@ -87,14 +84,10 @@ struct RTL_UNLOAD_EVENT_TRACE {
|
|||||||
ULONG TimeDateStamp;
|
ULONG TimeDateStamp;
|
||||||
ULONG CheckSum;
|
ULONG CheckSum;
|
||||||
WCHAR ImageName[32];
|
WCHAR ImageName[32];
|
||||||
ULONG Version0;
|
|
||||||
union {
|
|
||||||
ULONG Version1;
|
|
||||||
typename Traits::Pad alignment_for_x64;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Traits>
|
void RtlGetUnloadEventTraceEx(ULONG** element_size,
|
||||||
RTL_UNLOAD_EVENT_TRACE<Traits>* RtlGetUnloadEventTrace();
|
ULONG** element_count,
|
||||||
|
void** event_trace);
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
Loading…
x
Reference in New Issue
Block a user