1 : // Copyright 2015 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/refinery/analyzers/thread_analyzer.h"
16 :
17 : #include <dbghelp.h>
18 :
19 : #include "base/macros.h"
20 : #include "syzygy/refinery/analyzers/analyzer_util.h"
21 : #include "syzygy/refinery/process_state/refinery.pb.h"
22 :
23 : namespace refinery {
24 :
25 : // static
26 : const char ThreadAnalyzer::kThreadAnalyzerName[] = "ThreadAnalyzer";
27 :
28 : Analyzer::AnalysisResult ThreadAnalyzer::Analyze(
29 : const minidump::Minidump& minidump,
30 E : ProcessState* process_state) {
31 E : DCHECK(process_state != nullptr);
32 :
33 E : scoped_refptr<ProcessState::Layer<Stack>> stack_layer;
34 E : process_state->FindOrCreateLayer(&stack_layer);
35 :
36 : minidump::Minidump::Stream thread_list =
37 E : minidump.FindNextStream(nullptr, ThreadListStream);
38 E : if (!thread_list.IsValid())
39 i : return ANALYSIS_ERROR;
40 :
41 E : ULONG32 num_threads = 0;
42 E : if (!thread_list.ReadElement(&num_threads))
43 i : return ANALYSIS_ERROR;
44 :
45 E : for (size_t i = 0; i < num_threads; ++i) {
46 : // Note: if the dump were full memory, we would need to read a
47 : // MINIDUMP_THREAD based on a MINIDUMP_MEMORY_DESCRIPTOR64.
48 E : MINIDUMP_THREAD thread = {};
49 E : if (!thread_list.ReadElement(&thread))
50 i : return ANALYSIS_ERROR;
51 :
52 : // Create the stack record.
53 E : scoped_refptr<ProcessState::Record<Stack>> stack_record;
54 : AddressRange range(thread.Stack.StartOfMemoryRange,
55 E : thread.Stack.Memory.DataSize);
56 E : if (!range.IsValid())
57 i : return ANALYSIS_ERROR;
58 E : stack_layer->CreateRecord(range, &stack_record);
59 : ThreadInformation* thread_info =
60 E : stack_record->mutable_data()->mutable_thread_info();
61 E : if (thread_info == nullptr)
62 i : return ANALYSIS_ERROR;
63 :
64 E : thread_info->set_thread_id(thread.ThreadId);
65 E : thread_info->set_suspend_count(thread.SuspendCount);
66 E : thread_info->set_priority_class(thread.PriorityClass);
67 E : thread_info->set_priority(thread.Priority);
68 E : thread_info->set_teb_address(thread.Teb);
69 :
70 : // TODO(siggi): Add to bytes layer?
71 : minidump::Minidump::Stream thread_memory =
72 E : minidump.GetStreamFor(thread.Stack.Memory);
73 E : if (!thread_memory.IsValid())
74 i : return ANALYSIS_ERROR;
75 :
76 : minidump::Minidump::Stream thread_context =
77 E : minidump.GetStreamFor(thread.ThreadContext);
78 E : if (!thread_context.IsValid())
79 i : return ANALYSIS_ERROR;
80 :
81 : // TODO(siggi): This ought to probe for the architecture somehow.
82 E : CONTEXT ctx = {};
83 E : if (!thread_context.ReadElement(&ctx))
84 i : return ANALYSIS_ERROR;
85 E : ParseContext(ctx, thread_info->mutable_register_info());
86 E : }
87 :
88 E : return ANALYSIS_COMPLETE;
89 E : }
90 :
91 : } // namespace refinery
|