Index: syzygy/refinery/analyzers/stack_analysis_unittest.cc |
diff --git a/syzygy/refinery/analyzers/stack_analysis_unittest.cc b/syzygy/refinery/analyzers/stack_analysis_unittest.cc |
index eed8ff6317a604a1e3ec4065b074a52888da268b..29b3fe3cb506d50fa398b9a30a801d5a05286035 100644 |
--- a/syzygy/refinery/analyzers/stack_analysis_unittest.cc |
+++ b/syzygy/refinery/analyzers/stack_analysis_unittest.cc |
@@ -54,51 +54,6 @@ __declspec(noinline) DWORD GetEip() { |
return reinterpret_cast<DWORD>(_ReturnAddress()); |
} |
-bool AnalyzeMinidump(const base::FilePath& minidump_path, |
- ProcessState* process_state) { |
- minidump::Minidump minidump; |
- if (!minidump.Open(minidump_path)) |
- return false; |
- |
- scoped_refptr<DiaSymbolProvider> dia_symbol_provider(new DiaSymbolProvider()); |
- scoped_refptr<SymbolProvider> symbol_provider(new SymbolProvider()); |
- |
- AnalysisRunner runner; |
- scoped_ptr<Analyzer> analyzer(new refinery::MemoryAnalyzer()); |
- runner.AddAnalyzer(analyzer.Pass()); |
- analyzer.reset(new refinery::ThreadAnalyzer()); |
- runner.AddAnalyzer(analyzer.Pass()); |
- analyzer.reset(new refinery::ExceptionAnalyzer()); |
- runner.AddAnalyzer(analyzer.Pass()); |
- analyzer.reset(new refinery::ModuleAnalyzer()); |
- runner.AddAnalyzer(analyzer.Pass()); |
- analyzer.reset(new refinery::StackAnalyzer(dia_symbol_provider)); |
- runner.AddAnalyzer(analyzer.Pass()); |
- analyzer.reset( |
- new refinery::StackFrameAnalyzer(dia_symbol_provider, symbol_provider)); |
- runner.AddAnalyzer(analyzer.Pass()); |
- |
- return runner.Analyze(minidump, process_state) == Analyzer::ANALYSIS_COMPLETE; |
-} |
- |
-void ValidateTypedBlock(ProcessState* process_state, |
- Address expected_address, |
- Size expected_size, |
- const std::string& expected_variable_name, |
- const std::string& expected_type_name) { |
- TypedBlockRecordPtr typedblock_record; |
- // Note: using FindSingleRecord as there should be no typed block overlap in |
- // the context of this test. |
- ASSERT_TRUE( |
- process_state->FindSingleRecord(expected_address, &typedblock_record)); |
- |
- ASSERT_EQ(expected_address, typedblock_record->range().addr()); |
- ASSERT_EQ(expected_size, typedblock_record->range().size()); |
- const TypedBlock& typedblock = typedblock_record->data(); |
- ASSERT_EQ(expected_variable_name, typedblock.data_name()); |
- ASSERT_EQ(expected_type_name, typedblock.type_name()); |
-} |
- |
} // namespace |
class StackAndFrameAnalyzersTest : public testing::Test { |
@@ -107,6 +62,8 @@ class StackAndFrameAnalyzersTest : public testing::Test { |
// Override NT symbol path. |
ASSERT_TRUE(scoped_symbol_path_.Setup()); |
+ symbol_provider_ = new SymbolProvider(); |
+ |
expected_esp_ = 0U; |
eip_lowerbound_ = 0U; |
eip_upperbound_ = 0U; |
@@ -155,9 +112,72 @@ class StackAndFrameAnalyzersTest : public testing::Test { |
return success; |
} |
+ bool AnalyzeMinidump(ProcessState* process_state) { |
+ minidump::Minidump minidump; |
+ if (!minidump.Open(minidump_path())) |
+ return false; |
+ |
+ scoped_refptr<DiaSymbolProvider> dia_symbol_provider( |
+ new DiaSymbolProvider()); |
+ |
+ AnalysisRunner runner; |
+ scoped_ptr<Analyzer> analyzer(new refinery::MemoryAnalyzer()); |
+ runner.AddAnalyzer(analyzer.Pass()); |
+ analyzer.reset(new refinery::ThreadAnalyzer()); |
+ runner.AddAnalyzer(analyzer.Pass()); |
+ analyzer.reset(new refinery::ExceptionAnalyzer()); |
+ runner.AddAnalyzer(analyzer.Pass()); |
+ analyzer.reset(new refinery::ModuleAnalyzer()); |
+ runner.AddAnalyzer(analyzer.Pass()); |
+ analyzer.reset(new refinery::StackAnalyzer(dia_symbol_provider)); |
+ runner.AddAnalyzer(analyzer.Pass()); |
+ analyzer.reset(new refinery::StackFrameAnalyzer(dia_symbol_provider, |
+ symbol_provider_)); |
+ runner.AddAnalyzer(analyzer.Pass()); |
+ |
+ return runner.Analyze(minidump, process_state) == |
+ Analyzer::ANALYSIS_COMPLETE; |
+ } |
+ |
+ void ValidateTypedBlock(ProcessState* process_state, |
+ Address expected_address, |
+ Size expected_size, |
+ ModuleId expected_module_id, |
+ const std::string& expected_variable_name, |
+ const base::string16& expected_type_name) { |
+ TypedBlockRecordPtr typedblock_record; |
+ // Note: using FindSingleRecord as there should be no typed block overlap in |
+ // the context of this test. |
+ ASSERT_TRUE( |
+ process_state->FindSingleRecord(expected_address, &typedblock_record)); |
+ |
+ ASSERT_EQ(expected_address, typedblock_record->range().addr()); |
+ ASSERT_EQ(expected_size, typedblock_record->range().size()); |
+ |
+ const TypedBlock& typedblock = typedblock_record->data(); |
+ ASSERT_EQ(expected_module_id, typedblock.module_id()); |
+ |
+ // Validate the recovered type id corresponds to the expected name. |
+ ModuleLayerAccessor accessor(process_state); |
+ pe::PEFile::Signature signature; |
+ ASSERT_TRUE(accessor.GetModuleSignature(expected_module_id, &signature)); |
+ |
+ scoped_refptr<TypeRepository> type_repository; |
+ ASSERT_TRUE(symbol_provider_->FindOrCreateTypeRepository(signature, |
+ &type_repository)); |
+ |
+ TypePtr recovered_type = type_repository->GetType(typedblock.type_id()); |
+ ASSERT_NE(nullptr, recovered_type); |
+ ASSERT_EQ(expected_type_name, recovered_type->name()); |
+ |
+ ASSERT_EQ(expected_variable_name, typedblock.data_name()); |
+ } |
+ |
private: |
testing::ScopedMinidump scoped_minidump_; |
+ scoped_refptr<SymbolProvider> symbol_provider_; |
+ |
// For stack frame validation. |
uint32 expected_esp_; |
uint32 eip_lowerbound_; |
@@ -197,7 +217,7 @@ TEST_F(StackAndFrameAnalyzersTest, BasicTest) { |
ASSERT_TRUE(SetupStackFrameAndGenerateMinidump(dummy_argument)); |
ProcessState process_state; |
- ASSERT_TRUE(AnalyzeMinidump(minidump_path(), &process_state)); |
+ ASSERT_TRUE(AnalyzeMinidump(&process_state)); |
// Ensure the test's thread was successfully walked. |
StackRecordPtr stack; |
@@ -233,17 +253,23 @@ TEST_F(StackAndFrameAnalyzersTest, BasicTest) { |
// the frame base, to account for ebp. |
// Validate typed block layer for SetupStackFrameAndGenerateMinidump. |
+ ModuleLayerAccessor accessor(&process_state); |
+ ModuleId expected_module_id = accessor.GetModuleId(recovered_eip); |
+ ASSERT_NE(kNoModuleId, expected_module_id); |
+ |
// - Validate some locals. |
- ASSERT_NO_FATAL_FAILURE(ValidateTypedBlock( |
- &process_state, expected_udt_address(), sizeof(SimpleUDT), "udt_local", |
- "refinery::`anonymous-namespace'::SimpleUDT")); |
+ ASSERT_NO_FATAL_FAILURE( |
+ ValidateTypedBlock(&process_state, expected_udt_address(), |
+ sizeof(SimpleUDT), expected_module_id, "udt_local", |
+ L"refinery::`anonymous-namespace'::SimpleUDT")); |
ASSERT_NO_FATAL_FAILURE(ValidateTypedBlock( |
&process_state, expected_udt_ptr_address(), sizeof(SimpleUDT*), |
- "udt_ptr_local", "refinery::`anonymous-namespace'::SimpleUDT*")); |
+ expected_module_id, "udt_ptr_local", |
+ L"refinery::`anonymous-namespace'::SimpleUDT*")); |
// - Validate a parameter. |
ASSERT_NO_FATAL_FAILURE( |
ValidateTypedBlock(&process_state, expected_param_address(), sizeof(int), |
- "dummy_param", "int32_t")); |
+ expected_module_id, "dummy_param", L"int32_t")); |
} |
} // namespace refinery |