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/process_state/process_state.h"
16 :
17 : #include <algorithm>
18 :
19 : #include "syzygy/refinery/core/addressed_data.h"
20 : #include "syzygy/refinery/process_state/process_state_util.h"
21 :
22 m : namespace refinery {
23 :
24 m : ProcessState::ProcessState() : has_exception(false), excepting_thread_id(0U) {
25 m : }
26 :
27 m : ProcessState::~ProcessState() {
28 m : }
29 :
30 m : const char* ProcessState::LayerName(LayerEnum layer) {
31 m : switch (layer) {
32 : #define LAYER_NAME_CASE(name) \
33 m : case name##Layer: \
34 m : return #name;
35 :
36 m : PROCESS_STATE_LAYERS(LAYER_NAME_CASE)
37 :
38 : #undef LAYER_NAME_CASE
39 m : default:
40 m : return nullptr;
41 m : }
42 m : }
43 :
44 m : ProcessState::LayerEnum ProcessState::LayerFromName(
45 m : const base::StringPiece& layer_name) {
46 : #define LAYER_FROM_NAME(name) \
47 m : if (layer_name == #name "Layer") \
48 m : return name##Layer;
49 m : PROCESS_STATE_LAYERS(LAYER_FROM_NAME)
50 :
51 : #undef LAYER_FROM_NAME
52 :
53 m : return UnknownLayer;
54 m : }
55 :
56 m : bool ProcessState::FindStackRecord(
57 m : size_t thread_id,
58 m : scoped_refptr<Record<Stack>>* record) {
59 m : StackLayerPtr stack_layer;
60 m : if (!FindLayer(&stack_layer))
61 m : return false;
62 :
63 m : for (StackRecordPtr stack : *stack_layer) {
64 m : const Stack& stack_proto = stack->data();
65 m : DCHECK(stack_proto.has_thread_info());
66 m : DCHECK(stack_proto.thread_info().has_thread_id());
67 m : if (stack_proto.thread_info().thread_id() == thread_id) {
68 m : *record = stack;
69 m : return true;
70 m : }
71 m : }
72 :
73 m : return false;
74 m : }
75 :
76 m : bool ProcessState::GetAll(const AddressRange& range, void* data_ptr) {
77 m : DCHECK(range.IsValid());
78 :
79 : // Get the bytes layer.
80 m : BytesLayerPtr bytes_layer;
81 m : if (!FindLayer(&bytes_layer))
82 m : return false;
83 :
84 : // Search for a single record that spans the desired range.
85 m : std::vector<BytesRecordPtr> matching_records;
86 m : bytes_layer->GetRecordsSpanning(range, &matching_records);
87 m : if (matching_records.empty())
88 m : return false;
89 m : DCHECK_EQ(1U, matching_records.size());
90 :
91 : // Copy the bytes.
92 m : BytesRecordPtr bytes_record = matching_records[0];
93 m : AddressedData record_data(
94 m : bytes_record->range(),
95 m : reinterpret_cast<const void*>(bytes_record->data().data().c_str()));
96 :
97 m : return record_data.GetAt(range, data_ptr);
98 m : }
99 :
100 m : bool ProcessState::GetFrom(const AddressRange& range,
101 m : size_t* data_cnt,
102 m : void* data_ptr) {
103 m : DCHECK(range.IsValid());
104 :
105 : // Find the single record that contains the head of the range.
106 m : BytesRecordPtr record;
107 m : if (!FindSingleRecord(range.start(), &record))
108 m : return false;
109 :
110 : // Determine the range that can be served.
111 m : Address available_end = std::min(range.end(), record->range().end());
112 m : AddressRange available_range(range.start(), available_end - range.start());
113 m : DCHECK(available_range.IsValid());
114 :
115 : // Serve request.
116 m : *data_cnt = available_range.size();
117 m : if (data_ptr == nullptr)
118 m : return true; // Actual bytes not requested.
119 :
120 m : AddressedData record_data(
121 m : record->range(),
122 m : reinterpret_cast<const void*>(record->data().data().c_str()));
123 m : if (!record_data.GetAt(available_range, reinterpret_cast<void*>(data_ptr)))
124 m : return false;
125 :
126 m : return true;
127 m : }
128 :
129 m : bool ProcessState::HasSome(const AddressRange& range) {
130 : // TODO(manzagop): implement.
131 m : return false;
132 m : }
133 :
134 m : bool ProcessState::SetException(const Exception& candidate) {
135 m : DCHECK(candidate.has_thread_id());
136 :
137 m : if (has_exception)
138 m : return false; // There's already an exception.
139 :
140 m : StackRecordPtr stack_record;
141 m : if (!FindStackRecord(candidate.thread_id(), &stack_record))
142 m : return false; // Thread isn't in the process state.
143 :
144 m : DCHECK(stack_record->mutable_data());
145 m : ThreadInformation* thread_info =
146 m : stack_record->mutable_data()->mutable_thread_info();
147 m : DCHECK(!thread_info->has_exception());
148 m : Exception* exception = thread_info->mutable_exception();
149 m : *exception = candidate;
150 :
151 m : has_exception = true;
152 m : excepting_thread_id = exception->thread_id();
153 :
154 m : return true;
155 m : }
156 :
157 m : bool ProcessState::GetExceptingThreadId(size_t* thread_id) {
158 m : if (!has_exception)
159 m : return false;
160 :
161 m : *thread_id = excepting_thread_id;
162 m : return true;
163 m : }
164 :
165 m : } // namespace refinery
|