minidump_dump: bug fixes.

- Convert time_t values to UTC correctly. It is incorrect to cast a uint32_t*
   to time_t* because the two types may have different widths. This is the
   case on many 64-bit systems, where time_t is a 64-bit signed integer.
   Conversion is unified in a single function, and additional uses of time_t
   in minidump files not previously displayed in UTC are now displayed.
 - Interpret the IMAGE_DEBUG_MISC structure correctly.
 - When printing MINIDUMP_SYSTEM_INFO structures, always show the "x86" side
   of the union, and state whether it's expected to be valid. (Existing
   Breakpad-produced non-Windows minidumps for x86_64 use the "x86" side of
   union, but Windows minidumps for x86_64 use the "other" side, so I want to
   print both.)

R=ivanpe@chromium.org

Review URL: https://breakpad.appspot.com/5674002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1339 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
mark@chromium.org 2014-06-17 18:03:31 +00:00
parent fe34e3f9fe
commit a5da1e193c

View File

@ -366,6 +366,24 @@ static void PrintValueOrInvalid(bool valid,
} }
} }
// Converts a time_t to a string showing the time in UTC.
string TimeTToUTCString(time_t tt) {
struct tm timestruct;
#ifdef _WIN32
gmtime_s(&timestruct, &tt);
#else
gmtime_r(&tt, &timestruct);
#endif
char timestr[20];
int rv = strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
if (rv == 0) {
return string();
}
return string(timestr);
}
// //
// MinidumpObject // MinidumpObject
@ -2797,8 +2815,9 @@ void MinidumpModule::Print() {
module_.size_of_image); module_.size_of_image);
printf(" checksum = 0x%x\n", printf(" checksum = 0x%x\n",
module_.checksum); module_.checksum);
printf(" time_date_stamp = 0x%x\n", printf(" time_date_stamp = 0x%x %s\n",
module_.time_date_stamp); module_.time_date_stamp,
TimeTToUTCString(module_.time_date_stamp).c_str());
printf(" module_name_rva = 0x%x\n", printf(" module_name_rva = 0x%x\n",
module_.module_name_rva); module_.module_name_rva);
printf(" version_info.signature = 0x%x\n", printf(" version_info.signature = 0x%x\n",
@ -2872,8 +2891,9 @@ void MinidumpModule::Print() {
cv_record_20->cv_header.signature); cv_record_20->cv_header.signature);
printf(" (cv_record).cv_header.offset = 0x%x\n", printf(" (cv_record).cv_header.offset = 0x%x\n",
cv_record_20->cv_header.offset); cv_record_20->cv_header.offset);
printf(" (cv_record).signature = 0x%x\n", printf(" (cv_record).signature = 0x%x %s\n",
cv_record_20->signature); cv_record_20->signature,
TimeTToUTCString(cv_record_20->signature).c_str());
printf(" (cv_record).age = %d\n", printf(" (cv_record).age = %d\n",
cv_record_20->age); cv_record_20->age);
printf(" (cv_record).pdb_file_name = \"%s\"\n", printf(" (cv_record).pdb_file_name = \"%s\"\n",
@ -2899,13 +2919,19 @@ void MinidumpModule::Print() {
misc_record->length); misc_record->length);
printf(" (misc_record).unicode = %d\n", printf(" (misc_record).unicode = %d\n",
misc_record->unicode); misc_record->unicode);
// Don't bother printing the UTF-16, we don't really even expect to ever if (misc_record->unicode) {
// see this misc_record anyway. string misc_record_data_utf8;
if (misc_record->unicode) ConvertUTF16BufferToUTF8String(
reinterpret_cast<const uint16_t*>(misc_record->data),
misc_record->length - offsetof(MDImageDebugMisc, data),
&misc_record_data_utf8,
false); // already swapped
printf(" (misc_record).data = \"%s\"\n",
misc_record_data_utf8.c_str());
} else {
printf(" (misc_record).data = \"%s\"\n", printf(" (misc_record).data = \"%s\"\n",
misc_record->data); misc_record->data);
else }
printf(" (misc_record).data = (UTF-16)\n");
} else { } else {
printf(" (misc_record) = (null)\n"); printf(" (misc_record) = (null)\n");
} }
@ -3830,6 +3856,12 @@ void MinidumpSystemInfo::Print() {
system_info_.csd_version_rva); system_info_.csd_version_rva);
printf(" suite_mask = 0x%x\n", printf(" suite_mask = 0x%x\n",
system_info_.suite_mask); system_info_.suite_mask);
if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) {
printf(" cpu.x86_cpu_info (valid):\n");
} else {
printf(" cpu.x86_cpu_info (invalid):\n");
}
for (unsigned int i = 0; i < 3; ++i) { for (unsigned int i = 0; i < 3; ++i) {
printf(" cpu.x86_cpu_info.vendor_id[%d] = 0x%x\n", printf(" cpu.x86_cpu_info.vendor_id[%d] = 0x%x\n",
i, system_info_.cpu.x86_cpu_info.vendor_id[i]); i, system_info_.cpu.x86_cpu_info.vendor_id[i]);
@ -3840,6 +3872,14 @@ void MinidumpSystemInfo::Print() {
system_info_.cpu.x86_cpu_info.feature_information); system_info_.cpu.x86_cpu_info.feature_information);
printf(" cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n", printf(" cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n",
system_info_.cpu.x86_cpu_info.amd_extended_cpu_features); system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
if (system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86 &&
system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86_WIN64) {
printf(" cpu.other_cpu_info (valid):\n");
for (unsigned int i = 0; i < 2; ++i) {
printf(" cpu.other_cpu_info.processor_features[%d] = 0x%" PRIx64 "\n",
i, system_info_.cpu.other_cpu_info.processor_features[i]);
}
}
const string* csd_version = GetCSDVersion(); const string* csd_version = GetCSDVersion();
if (csd_version) { if (csd_version) {
printf(" (csd_version) = \"%s\"\n", printf(" (csd_version) = \"%s\"\n",
@ -3964,19 +4004,9 @@ void MinidumpMiscInfo::Print() {
PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_ID, PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_ID,
kNumberFormatDecimal, misc_info_.process_id); kNumberFormatDecimal, misc_info_.process_id);
if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES) { if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES) {
struct tm timestruct;
#ifdef _WIN32
gmtime_s(&timestruct,
reinterpret_cast<time_t*>(&misc_info_.process_create_time));
#else
gmtime_r(reinterpret_cast<time_t*>(&misc_info_.process_create_time),
&timestruct);
#endif
char timestr[20];
strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
printf(" process_create_time = 0x%x %s\n", printf(" process_create_time = 0x%x %s\n",
misc_info_.process_create_time, misc_info_.process_create_time,
timestr); TimeTToUTCString(misc_info_.process_create_time).c_str());
} else { } else {
printf(" process_create_time = (invalid)\n"); printf(" process_create_time = (invalid)\n");
} }
@ -4786,16 +4816,9 @@ void Minidump::Print() {
printf(" stream_count = %d\n", header_.stream_count); printf(" stream_count = %d\n", header_.stream_count);
printf(" stream_directory_rva = 0x%x\n", header_.stream_directory_rva); printf(" stream_directory_rva = 0x%x\n", header_.stream_directory_rva);
printf(" checksum = 0x%x\n", header_.checksum); printf(" checksum = 0x%x\n", header_.checksum);
struct tm timestruct; printf(" time_date_stamp = 0x%x %s\n",
#ifdef _WIN32 header_.time_date_stamp,
gmtime_s(&timestruct, reinterpret_cast<time_t*>(&header_.time_date_stamp)); TimeTToUTCString(header_.time_date_stamp).c_str());
#else
gmtime_r(reinterpret_cast<time_t*>(&header_.time_date_stamp), &timestruct);
#endif
char timestr[20];
strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
printf(" time_date_stamp = 0x%x %s\n", header_.time_date_stamp,
timestr);
printf(" flags = 0x%" PRIx64 "\n", header_.flags); printf(" flags = 0x%" PRIx64 "\n", header_.flags);
printf("\n"); printf("\n");