Chromium Code Reviews| Index: minidump/test/minidump_context_test_util.cc |
| diff --git a/minidump/test/minidump_context_test_util.cc b/minidump/test/minidump_context_test_util.cc |
| index 18995eaa2f7c01c42ccf3e68117abe615206698e..8d9ca31d748bab3fb163fbd46be35e248f7a7f81 100644 |
| --- a/minidump/test/minidump_context_test_util.cc |
| +++ b/minidump/test/minidump_context_test_util.cc |
| @@ -15,7 +15,10 @@ |
| #include "minidump/test/minidump_context_test_util.h" |
| #include "base/basictypes.h" |
| +#include "base/strings/stringprintf.h" |
| #include "gtest/gtest.h" |
| +#include "snapshot/cpu_context.h" |
| +#include "snapshot/test/test_cpu_context.h" |
| namespace crashpad { |
| namespace test { |
| @@ -31,45 +34,59 @@ void InitializeMinidumpContextX86(MinidumpContextX86* context, uint32_t seed) { |
| uint32_t value = seed; |
| + context->eax = value++; |
| + context->ebx = value++; |
| + context->ecx = value++; |
| + context->edx = value++; |
| + context->edi = value++; |
| + context->esi = value++; |
| + context->ebp = value++; |
| + context->esp = value++; |
| + context->eip = value++; |
| + context->eflags = value++; |
| + context->cs = value++ & 0xffff; |
| + context->ds = value++ & 0xffff; |
| + context->es = value++ & 0xffff; |
| + context->fs = value++ & 0xffff; |
| + context->gs = value++ & 0xffff; |
| + context->ss = value++ & 0xffff; |
| + |
| + InitializeCPUContextX86Fxsave(&context->fxsave, &value); |
| + |
| context->dr0 = value++; |
| context->dr1 = value++; |
| context->dr2 = value++; |
| context->dr3 = value++; |
| + value += 2; // Minidumps don’t carry dr4 or dr5. |
|
Robert Sesek
2014/11/03 21:26:57
This comment may be useful in the header that defi
Mark Mentovai
2014/11/03 22:01:21
Robert Sesek wrote:
Robert Sesek
2014/11/03 22:22:06
In addition, as you've done.
|
| context->dr6 = value++; |
| context->dr7 = value++; |
| - context->float_save.control_word = value++; |
| - context->float_save.status_word = value++; |
| - context->float_save.tag_word = value++; |
| - context->float_save.error_offset = value++; |
| - context->float_save.error_selector = value++; |
| - context->float_save.data_offset = value++; |
| - context->float_save.data_selector = value++; |
| - for (size_t index = 0; |
| - index < arraysize(context->float_save.register_area); |
| - ++index) { |
| - context->float_save.register_area[index] = value++; |
| + |
| + // Copy the values that are aliased between the fxsave area |
| + // (context->extended_registers) and the floating-point save area |
| + // (context->float_save). |
| + context->float_save.control_word = context->fxsave.fcw; |
| + context->float_save.status_word = context->fxsave.fsw; |
| + context->float_save.tag_word = CPUContextX86::FxsaveToFsaveTagWord( |
| + context->fxsave.fsw, context->fxsave.ftw, context->fxsave.st_mm); |
| + context->float_save.error_offset = context->fxsave.fpu_ip; |
| + context->float_save.error_selector = context->fxsave.fpu_cs; |
| + context->float_save.data_offset = context->fxsave.fpu_dp; |
| + context->float_save.data_selector = context->fxsave.fpu_ds; |
| + for (size_t st_mm_index = 0; |
| + st_mm_index < arraysize(context->fxsave.st_mm); |
| + ++st_mm_index) { |
| + for (size_t byte = 0; |
| + byte < arraysize(context->fxsave.st_mm[st_mm_index].st); |
| + ++byte) { |
| + size_t st_index = |
| + st_mm_index * arraysize(context->fxsave.st_mm[st_mm_index].st) + byte; |
| + context->float_save.register_area[st_index] = |
| + context->fxsave.st_mm[st_mm_index].st[byte]; |
| + } |
| } |
| + |
| + // Set this field last, because it has no analogue in CPUContextX86. |
| context->float_save.spare_0 = value++; |
| - context->gs = value++; |
| - context->fs = value++; |
| - context->es = value++; |
| - context->ds = value++; |
| - context->edi = value++; |
| - context->esi = value++; |
| - context->ebx = value++; |
| - context->edx = value++; |
| - context->ecx = value++; |
| - context->eax = value++; |
| - context->ebp = value++; |
| - context->eip = value++; |
| - context->cs = value++; |
| - context->eflags = value++; |
| - context->esp = value++; |
| - context->ss = value++; |
| - for (size_t index = 0; index < arraysize(context->extended_registers); |
| - ++index) { |
| - context->extended_registers[index] = value++; |
| - } |
| } |
| void InitializeMinidumpContextAMD64(MinidumpContextAMD64* context, |
| @@ -84,34 +101,14 @@ void InitializeMinidumpContextAMD64(MinidumpContextAMD64* context, |
| uint32_t value = seed; |
| - context->p1_home = value++; |
| - context->p2_home = value++; |
| - context->p3_home = value++; |
| - context->p4_home = value++; |
| - context->p5_home = value++; |
| - context->p6_home = value++; |
| - context->mx_csr = value++; |
| - context->cs = value++; |
| - context->ds = value++; |
| - context->es = value++; |
| - context->fs = value++; |
| - context->gs = value++; |
| - context->ss = value++; |
| - context->eflags = value++; |
| - context->dr0 = value++; |
| - context->dr1 = value++; |
| - context->dr2 = value++; |
| - context->dr3 = value++; |
| - context->dr6 = value++; |
| - context->dr7 = value++; |
| context->rax = value++; |
| + context->rbx = value++; |
| context->rcx = value++; |
| context->rdx = value++; |
| - context->rbx = value++; |
| - context->rsp = value++; |
| - context->rbp = value++; |
| - context->rsi = value++; |
| context->rdi = value++; |
| + context->rsi = value++; |
| + context->rbp = value++; |
| + context->rsp = value++; |
| context->r8 = value++; |
| context->r9 = value++; |
| context->r10 = value++; |
| @@ -121,36 +118,34 @@ void InitializeMinidumpContextAMD64(MinidumpContextAMD64* context, |
| context->r14 = value++; |
| context->r15 = value++; |
| context->rip = value++; |
| - context->float_save.control_word = value++; |
| - context->float_save.status_word = value++; |
| - context->float_save.tag_word = value++; |
| - context->float_save.reserved_1 = value++; |
| - context->float_save.error_opcode = value++; |
| - context->float_save.error_offset = value++; |
| - context->float_save.error_selector = value++; |
| - context->float_save.reserved_2 = value++; |
| - context->float_save.data_offset = value++; |
| - context->float_save.data_selector = value++; |
| - context->float_save.reserved_3 = value++; |
| - context->float_save.mx_csr = value++; |
| - context->float_save.mx_csr_mask = value++; |
| - for (size_t index = 0; |
| - index < arraysize(context->float_save.float_registers); |
| - ++index) { |
| - context->float_save.float_registers[index].lo = value++; |
| - context->float_save.float_registers[index].hi = value++; |
| - } |
| - for (size_t index = 0; |
| - index < arraysize(context->float_save.xmm_registers); |
| - ++index) { |
| - context->float_save.xmm_registers[index].lo = value++; |
| - context->float_save.xmm_registers[index].hi = value++; |
| - } |
| - for (size_t index = 0; |
| - index < arraysize(context->float_save.reserved_4); |
| - ++index) { |
| - context->float_save.reserved_4[index] = value++; |
| - } |
| + context->eflags = value++; |
| + context->cs = value++; |
| + context->fs = value++; |
| + context->gs = value++; |
| + |
| + InitializeCPUContextX86_64Fxsave(&context->fxsave, &value); |
| + |
| + // mxcsr appears twice, and the two values should be aliased. |
| + context->mx_csr = context->fxsave.mxcsr; |
| + |
| + context->dr0 = value++; |
| + context->dr1 = value++; |
| + context->dr2 = value++; |
| + context->dr3 = value++; |
| + value += 2; // Minidumps don’t carry dr4 or dr5. |
| + context->dr6 = value++; |
| + context->dr7 = value++; |
| + |
| + // Set these fields last, because they have no analogues in CPUContextX86_64. |
| + context->p1_home = value++; |
| + context->p2_home = value++; |
| + context->p3_home = value++; |
| + context->p4_home = value++; |
| + context->p5_home = value++; |
| + context->p6_home = value++; |
| + context->ds = value++; |
| + context->es = value++; |
| + context->ss = value++; |
| for (size_t index = 0; index < arraysize(context->vector_register); ++index) { |
| context->vector_register[index].lo = value++; |
| context->vector_register[index].hi = value++; |
| @@ -163,8 +158,69 @@ void InitializeMinidumpContextAMD64(MinidumpContextAMD64* context, |
| context->last_exception_from_rip = value++; |
| } |
| -void ExpectMinidumpContextX86(uint32_t expect_seed, |
| - const MinidumpContextX86* observed) { |
| +namespace { |
| + |
| +// Using gtest assertions, compares |expected| to |observed|. This is |
| +// templatized because the CPUContextX86::Fxsave and CPUContextX86_64::Fxsave |
| +// are nearly identical but have different sizes for the members |xmm|, |
| +// |reserved_4|, and |available|. |
| +template <typename FxsaveType> |
| +void ExpectMinidumpContextFxsave(const FxsaveType* expected, |
| + const FxsaveType* observed) { |
| + EXPECT_EQ(expected->fcw, observed->fcw); |
| + EXPECT_EQ(expected->fsw, observed->fsw); |
| + EXPECT_EQ(expected->ftw, observed->ftw); |
| + EXPECT_EQ(expected->reserved_1, observed->reserved_1); |
| + EXPECT_EQ(expected->fop, observed->fop); |
| + EXPECT_EQ(expected->fpu_ip, observed->fpu_ip); |
| + EXPECT_EQ(expected->fpu_cs, observed->fpu_cs); |
| + EXPECT_EQ(expected->reserved_2, observed->reserved_2); |
| + EXPECT_EQ(expected->fpu_dp, observed->fpu_dp); |
| + EXPECT_EQ(expected->fpu_ds, observed->fpu_ds); |
| + EXPECT_EQ(expected->reserved_3, observed->reserved_3); |
| + EXPECT_EQ(expected->mxcsr, observed->mxcsr); |
| + EXPECT_EQ(expected->mxcsr_mask, observed->mxcsr_mask); |
| + for (size_t st_mm_index = 0; |
| + st_mm_index < arraysize(expected->st_mm); |
| + ++st_mm_index) { |
| + SCOPED_TRACE(base::StringPrintf("st_mm_index %zu", st_mm_index)); |
| + for (size_t byte = 0; |
| + byte < arraysize(expected->st_mm[st_mm_index].st); |
| + ++byte) { |
| + EXPECT_EQ(expected->st_mm[st_mm_index].st[byte], |
| + observed->st_mm[st_mm_index].st[byte]) << "byte " << byte; |
| + } |
| + for (size_t byte = 0; |
| + byte < arraysize(expected->st_mm[st_mm_index].st_reserved); |
| + ++byte) { |
| + EXPECT_EQ(expected->st_mm[st_mm_index].st_reserved[byte], |
| + observed->st_mm[st_mm_index].st_reserved[byte]) |
| + << "byte " << byte; |
| + } |
| + } |
| + for (size_t xmm_index = 0; |
| + xmm_index < arraysize(expected->xmm); |
| + ++xmm_index) { |
| + SCOPED_TRACE(base::StringPrintf("xmm_index %zu", xmm_index)); |
| + for (size_t byte = 0; byte < arraysize(expected->xmm[xmm_index]); ++byte) { |
| + EXPECT_EQ(expected->xmm[xmm_index][byte], observed->xmm[xmm_index][byte]) |
| + << "byte " << byte; |
| + } |
| + } |
| + for (size_t byte = 0; byte < arraysize(expected->reserved_4); ++byte) { |
| + EXPECT_EQ(expected->reserved_4[byte], observed->reserved_4[byte]) |
| + << "byte " << byte; |
| + } |
| + for (size_t byte = 0; byte < arraysize(expected->available); ++byte) { |
| + EXPECT_EQ(expected->available[byte], observed->available[byte]) |
| + << "byte " << byte; |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +void ExpectMinidumpContextX86( |
| + uint32_t expect_seed, const MinidumpContextX86* observed, bool snapshot) { |
| MinidumpContextX86 expected; |
| InitializeMinidumpContextX86(&expected, expect_seed); |
| @@ -175,6 +231,7 @@ void ExpectMinidumpContextX86(uint32_t expect_seed, |
| EXPECT_EQ(expected.dr3, observed->dr3); |
| EXPECT_EQ(expected.dr6, observed->dr6); |
| EXPECT_EQ(expected.dr7, observed->dr7); |
| + |
| EXPECT_EQ(expected.float_save.control_word, |
| observed->float_save.control_word); |
| EXPECT_EQ(expected.float_save.status_word, observed->float_save.status_word); |
| @@ -190,9 +247,14 @@ void ExpectMinidumpContextX86(uint32_t expect_seed, |
| index < arraysize(expected.float_save.register_area); |
| ++index) { |
| EXPECT_EQ(expected.float_save.register_area[index], |
| - observed->float_save.register_area[index]); |
| + observed->float_save.register_area[index]) << "index " << index; |
| } |
| - EXPECT_EQ(expected.float_save.spare_0, observed->float_save.spare_0); |
| + if (snapshot) { |
| + EXPECT_EQ(0u, observed->float_save.spare_0); |
| + } else { |
| + EXPECT_EQ(expected.float_save.spare_0, observed->float_save.spare_0); |
| + } |
| + |
| EXPECT_EQ(expected.gs, observed->gs); |
| EXPECT_EQ(expected.fs, observed->fs); |
| EXPECT_EQ(expected.es, observed->es); |
| @@ -209,40 +271,60 @@ void ExpectMinidumpContextX86(uint32_t expect_seed, |
| EXPECT_EQ(expected.eflags, observed->eflags); |
| EXPECT_EQ(expected.esp, observed->esp); |
| EXPECT_EQ(expected.ss, observed->ss); |
| - for (size_t index = 0; |
| - index < arraysize(expected.extended_registers); |
| - ++index) { |
| - EXPECT_EQ(expected.extended_registers[index], |
| - observed->extended_registers[index]); |
| - } |
| + |
| + ExpectMinidumpContextFxsave(&expected.fxsave, &observed->fxsave); |
| } |
| -void ExpectMinidumpContextAMD64(uint32_t expect_seed, |
| - const MinidumpContextAMD64* observed) { |
| +void ExpectMinidumpContextAMD64( |
| + uint32_t expect_seed, const MinidumpContextAMD64* observed, bool snapshot) { |
| MinidumpContextAMD64 expected; |
| InitializeMinidumpContextAMD64(&expected, expect_seed); |
| EXPECT_EQ(expected.context_flags, observed->context_flags); |
| - EXPECT_EQ(expected.p1_home, observed->p1_home); |
| - EXPECT_EQ(expected.p2_home, observed->p2_home); |
| - EXPECT_EQ(expected.p3_home, observed->p3_home); |
| - EXPECT_EQ(expected.p4_home, observed->p4_home); |
| - EXPECT_EQ(expected.p5_home, observed->p5_home); |
| - EXPECT_EQ(expected.p6_home, observed->p6_home); |
| + |
| + if (snapshot) { |
| + EXPECT_EQ(0u, observed->p1_home); |
| + EXPECT_EQ(0u, observed->p2_home); |
| + EXPECT_EQ(0u, observed->p3_home); |
| + EXPECT_EQ(0u, observed->p4_home); |
| + EXPECT_EQ(0u, observed->p5_home); |
| + EXPECT_EQ(0u, observed->p6_home); |
| + } else { |
| + EXPECT_EQ(expected.p1_home, observed->p1_home); |
| + EXPECT_EQ(expected.p2_home, observed->p2_home); |
| + EXPECT_EQ(expected.p3_home, observed->p3_home); |
| + EXPECT_EQ(expected.p4_home, observed->p4_home); |
| + EXPECT_EQ(expected.p5_home, observed->p5_home); |
| + EXPECT_EQ(expected.p6_home, observed->p6_home); |
| + } |
| + |
| EXPECT_EQ(expected.mx_csr, observed->mx_csr); |
| + |
| EXPECT_EQ(expected.cs, observed->cs); |
| - EXPECT_EQ(expected.ds, observed->ds); |
| - EXPECT_EQ(expected.es, observed->es); |
| + if (snapshot) { |
| + EXPECT_EQ(0u, observed->ds); |
| + EXPECT_EQ(0u, observed->es); |
| + } else { |
| + EXPECT_EQ(expected.ds, observed->ds); |
| + EXPECT_EQ(expected.es, observed->es); |
| + } |
| EXPECT_EQ(expected.fs, observed->fs); |
| EXPECT_EQ(expected.gs, observed->gs); |
| - EXPECT_EQ(expected.ss, observed->ss); |
| + if (snapshot) { |
| + EXPECT_EQ(0u, observed->ss); |
| + } else { |
| + EXPECT_EQ(expected.ss, observed->ss); |
| + } |
| + |
| EXPECT_EQ(expected.eflags, observed->eflags); |
| + |
| EXPECT_EQ(expected.dr0, observed->dr0); |
| EXPECT_EQ(expected.dr1, observed->dr1); |
| EXPECT_EQ(expected.dr2, observed->dr2); |
| EXPECT_EQ(expected.dr3, observed->dr3); |
| EXPECT_EQ(expected.dr6, observed->dr6); |
| EXPECT_EQ(expected.dr7, observed->dr7); |
| + |
| EXPECT_EQ(expected.rax, observed->rax); |
| EXPECT_EQ(expected.rcx, observed->rcx); |
| EXPECT_EQ(expected.rdx, observed->rdx); |
| @@ -260,59 +342,37 @@ void ExpectMinidumpContextAMD64(uint32_t expect_seed, |
| EXPECT_EQ(expected.r14, observed->r14); |
| EXPECT_EQ(expected.r15, observed->r15); |
| EXPECT_EQ(expected.rip, observed->rip); |
| - EXPECT_EQ(expected.float_save.control_word, |
| - observed->float_save.control_word); |
| - EXPECT_EQ(expected.float_save.status_word, observed->float_save.status_word); |
| - EXPECT_EQ(expected.float_save.tag_word, observed->float_save.tag_word); |
| - EXPECT_EQ(expected.float_save.reserved_1, observed->float_save.reserved_1); |
| - EXPECT_EQ(expected.float_save.error_opcode, |
| - observed->float_save.error_opcode); |
| - EXPECT_EQ(expected.float_save.error_offset, |
| - observed->float_save.error_offset); |
| - EXPECT_EQ(expected.float_save.error_selector, |
| - observed->float_save.error_selector); |
| - EXPECT_EQ(expected.float_save.reserved_2, observed->float_save.reserved_2); |
| - EXPECT_EQ(expected.float_save.data_offset, observed->float_save.data_offset); |
| - EXPECT_EQ(expected.float_save.data_selector, |
| - observed->float_save.data_selector); |
| - EXPECT_EQ(expected.float_save.reserved_3, observed->float_save.reserved_3); |
| - EXPECT_EQ(expected.float_save.mx_csr, observed->float_save.mx_csr); |
| - EXPECT_EQ(expected.float_save.mx_csr_mask, observed->float_save.mx_csr_mask); |
| - for (size_t index = 0; |
| - index < arraysize(expected.float_save.float_registers); |
| - ++index) { |
| - EXPECT_EQ(expected.float_save.float_registers[index].lo, |
| - observed->float_save.float_registers[index].lo); |
| - EXPECT_EQ(expected.float_save.float_registers[index].hi, |
| - observed->float_save.float_registers[index].hi); |
| - } |
| - for (size_t index = 0; |
| - index < arraysize(expected.float_save.xmm_registers); |
| - ++index) { |
| - EXPECT_EQ(expected.float_save.xmm_registers[index].lo, |
| - observed->float_save.xmm_registers[index].lo); |
| - EXPECT_EQ(expected.float_save.xmm_registers[index].hi, |
| - observed->float_save.xmm_registers[index].hi); |
| - } |
| - for (size_t index = 0; |
| - index < arraysize(expected.float_save.reserved_4); |
| - ++index) { |
| - EXPECT_EQ(expected.float_save.reserved_4[index], |
| - observed->float_save.reserved_4[index]); |
| - } |
| + |
| + ExpectMinidumpContextFxsave(&expected.fxsave, &observed->fxsave); |
| + |
| for (size_t index = 0; index < arraysize(expected.vector_register); ++index) { |
| - EXPECT_EQ(expected.vector_register[index].lo, |
| - observed->vector_register[index].lo); |
| - EXPECT_EQ(expected.vector_register[index].hi, |
| - observed->vector_register[index].hi); |
| + if (snapshot) { |
| + EXPECT_EQ(0u, observed->vector_register[index].lo) << "index " << index; |
| + EXPECT_EQ(0u, observed->vector_register[index].hi) << "index " << index; |
| + } else { |
| + EXPECT_EQ(expected.vector_register[index].lo, |
| + observed->vector_register[index].lo) << "index " << index; |
| + EXPECT_EQ(expected.vector_register[index].hi, |
| + observed->vector_register[index].hi) << "index " << index; |
| + } |
| + } |
| + |
| + if (snapshot) { |
| + EXPECT_EQ(0u, observed->vector_control); |
| + EXPECT_EQ(0u, observed->debug_control); |
| + EXPECT_EQ(0u, observed->last_branch_to_rip); |
| + EXPECT_EQ(0u, observed->last_branch_from_rip); |
| + EXPECT_EQ(0u, observed->last_exception_to_rip); |
| + EXPECT_EQ(0u, observed->last_exception_from_rip); |
| + } else { |
| + EXPECT_EQ(expected.vector_control, observed->vector_control); |
| + EXPECT_EQ(expected.debug_control, observed->debug_control); |
| + EXPECT_EQ(expected.last_branch_to_rip, observed->last_branch_to_rip); |
| + EXPECT_EQ(expected.last_branch_from_rip, observed->last_branch_from_rip); |
| + EXPECT_EQ(expected.last_exception_to_rip, observed->last_exception_to_rip); |
| + EXPECT_EQ(expected.last_exception_from_rip, |
| + observed->last_exception_from_rip); |
| } |
| - EXPECT_EQ(expected.vector_control, observed->vector_control); |
| - EXPECT_EQ(expected.debug_control, observed->debug_control); |
| - EXPECT_EQ(expected.last_branch_to_rip, observed->last_branch_to_rip); |
| - EXPECT_EQ(expected.last_branch_from_rip, observed->last_branch_from_rip); |
| - EXPECT_EQ(expected.last_exception_to_rip, observed->last_exception_to_rip); |
| - EXPECT_EQ(expected.last_exception_from_rip, |
| - observed->last_exception_from_rip); |
| } |
| } // namespace test |