Index: syzygy/refinery/analyzers/type_propagator_analyzer.cc |
diff --git a/syzygy/refinery/analyzers/type_propagator_analyzer.cc b/syzygy/refinery/analyzers/type_propagator_analyzer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d3e6787ace6cf8da55996d36dd2e93f7d7de8ccc |
--- /dev/null |
+++ b/syzygy/refinery/analyzers/type_propagator_analyzer.cc |
@@ -0,0 +1,164 @@ |
+// Copyright 2015 Google Inc. All Rights Reserved. |
+// |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
+// you may not use this file except in compliance with the License. |
+// You may obtain a copy of the License at |
+// |
+// http://www.apache.org/licenses/LICENSE-2.0 |
+// |
+// Unless required by applicable law or agreed to in writing, software |
+// distributed under the License is distributed on an "AS IS" BASIS, |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+// See the License for the specific language governing permissions and |
+// limitations under the License. |
+ |
+#include "syzygy/refinery/analyzers/type_propagator_analyzer.h" |
+ |
+#include <queue> |
+ |
+#include "syzygy/refinery/process_state/process_state_util.h" |
+#include "syzygy/refinery/process_state/refinery.pb.h" |
+#include "syzygy/refinery/types/type.h" |
+ |
+namespace refinery { |
+ |
+// static |
+const char TypePropagatorAnalyzer::kTypePropagatorAnalyzerName[] = |
+ "TypePropagatorAnalyzer"; |
+ |
+TypePropagatorAnalyzer::TypePropagatorAnalyzer( |
+ scoped_refptr<SymbolProvider> symbol_provider) |
+ : symbol_provider_(symbol_provider) { |
+ DCHECK(symbol_provider.get() != nullptr); |
+} |
+ |
+Analyzer::AnalysisResult TypePropagatorAnalyzer::Analyze( |
+ const minidump::Minidump& minidump, |
+ ProcessState* process_state) { |
+ DCHECK(process_state != nullptr); |
+ |
+ // Bytes and typed block layer must be present. |
+ BytesLayerPtr bytes_layer; |
+ if (!process_state->FindLayer(&bytes_layer)) { |
+ LOG(ERROR) << "Missing bytes layer."; |
+ return ANALYSIS_ERROR; |
+ } |
+ TypedBlockLayerPtr typed_layer; |
+ if (!process_state->FindLayer(&typed_layer)) { |
+ LOG(ERROR) << "Missing typed block layer."; |
+ return ANALYSIS_ERROR; |
Sigurður Ásgeirsson
2015/11/26 21:45:12
Is this an error, or just unexpected?
manzagop (departed)
2015/11/27 15:20:28
I'm using this as a proxy for "StackFrameAnalyzer
|
+ } |
+ |
+ ModuleLayerAccessor accessor(process_state); |
+ |
+ std::queue<TypedData> process_queue; |
+ |
+ // Recover typed data from the typed block layer. |
+ for (TypedBlockRecordPtr rec : *typed_layer) { |
+ const TypedBlock& typedblock = rec->data(); |
+ |
+ // Recover the type. |
+ pe::PEFile::Signature signature; |
+ if (!accessor.GetModuleSignature(typedblock.module_id(), &signature)) |
+ return ANALYSIS_ERROR; |
+ |
+ scoped_refptr<TypeRepository> type_repository; |
+ if (!symbol_provider_->FindOrCreateTypeRepository(signature, |
+ &type_repository)) { |
+ return ANALYSIS_ERROR; |
+ } |
+ |
+ TypePtr type = type_repository->GetType(typedblock.type_id()); |
+ if (type == nullptr) |
+ return ANALYSIS_ERROR; |
+ |
+ // Queue typed data for processing. |
+ process_queue.emplace(process_state, type, rec->range().start()); |
Sigurður Ásgeirsson
2015/11/26 21:45:12
nit: I don't think we're allowed emplace just yet?
manzagop (departed)
2015/11/27 15:20:28
Haha. I'd actually checked and seen "Use where ele
|
+ } |
+ |
+ // Process typed data looking for pointers or contained pointers. |
+ while (!process_queue.empty()) { |
+ if (!AnalyzeTypedData(process_queue.front(), process_state)) |
+ return ANALYSIS_ERROR; |
+ process_queue.pop(); |
+ } |
+ |
+ return ANALYSIS_COMPLETE; |
Sigurður Ásgeirsson
2015/11/26 21:45:12
Hmmm - I think you want to iterate here until stab
manzagop (departed)
2015/11/27 15:20:28
As you guessed, there's recursion in AnalyzeTypedD
Sigurður Ásgeirsson
2015/11/27 15:33:40
That's not quite the same thing. A single iteratio
manzagop (departed)
2015/11/27 18:17:03
As discussed, there's currently recursion that goe
|
+} |
+ |
+bool TypePropagatorAnalyzer::AnalyzeTypedData(const TypedData& typed_data, |
+ ProcessState* process_state) { |
+ DCHECK(process_state != nullptr); |
+ |
+ TypePtr type = typed_data.type(); |
+ DCHECK(type.get()); |
+ |
+ switch (type->kind()) { |
+ case Type::USER_DEFINED_TYPE_KIND: |
+ return AnalyzeTypedDataUDT(typed_data, process_state); |
+ case Type::POINTER_TYPE_KIND: |
+ return AnalyzeTypedDataPointer(typed_data, process_state); |
+ case Type::ARRAY_TYPE_KIND: |
+ return AnalyzeTypedDataArray(typed_data, process_state); |
+ case Type::BASIC_TYPE_KIND: |
+ case Type::FUNCTION_TYPE_KIND: |
+ case Type::GLOBAL_TYPE_KIND: |
+ case Type::WILDCARD_TYPE_KIND: |
+ // Nothing to do with these. |
+ return true; |
+ default: |
+ DCHECK(false); |
+ return false; |
+ } |
+} |
+ |
+bool TypePropagatorAnalyzer::AnalyzeTypedDataUDT(const TypedData& typed_data, |
+ ProcessState* process_state) { |
+ DCHECK_EQ(Type::USER_DEFINED_TYPE_KIND, typed_data.type()->kind()); |
+ DCHECK(process_state != nullptr); |
+ |
+ // TODO(manzagop): implement. |
Sigurður Ásgeirsson
2015/11/26 21:45:12
aha - this is where you'd recurse?
manzagop (departed)
2015/11/27 15:20:28
That is correct.
|
+ |
+ return true; |
+} |
+ |
+bool TypePropagatorAnalyzer::AnalyzeTypedDataPointer( |
+ const TypedData& typed_data, |
+ ProcessState* process_state) { |
+ DCHECK_EQ(Type::POINTER_TYPE_KIND, typed_data.type()->kind()); |
+ DCHECK(process_state != nullptr); |
+ |
+ TypedData content_data; |
+ typed_data.Dereference(&content_data); |
+ |
+ if (!AddTypedBlock(content_data, process_state)) |
+ return false; |
+ |
+ return AnalyzeTypedData(content_data, process_state); |
+} |
+ |
+bool TypePropagatorAnalyzer::AnalyzeTypedDataArray( |
+ const TypedData& typed_data, |
+ ProcessState* process_state) { |
+ DCHECK_EQ(Type::ARRAY_TYPE_KIND, typed_data.type()->kind()); |
+ DCHECK(process_state != nullptr); |
+ |
+ // TODO(manzagop): implement. |
+ return true; |
+} |
+ |
+bool TypePropagatorAnalyzer::AddTypedBlock(const TypedData& typed_data, |
+ ProcessState* process_state) { |
+ ModuleLayerAccessor accessor(process_state); |
+ pe::PEFile::Signature signature; |
+ if (!typed_data.type()->repository()->GetModuleSignature(&signature)) |
+ return false; |
+ ModuleId module_id = accessor.GetModuleId(signature); |
+ if (module_id == kNoModuleId) |
+ return false; |
+ |
+ return AddTypedBlockRecord(typed_data.GetRange(), L"", module_id, |
+ typed_data.type()->type_id(), process_state); |
+} |
+ |
+} // namespace refinery |