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_util.h"
16 :
17 : #include "base/strings/utf_string_conversions.h"
18 : #include "syzygy/core/address.h"
19 : #include "syzygy/refinery/process_state/layer_traits.h"
20 :
21 : namespace refinery {
22 :
23 : namespace {
24 :
25 : template <typename RecordType>
26 : RecordType* CreateRecord(const AddressRange& range,
27 E : ProcessState* process_state) {
28 E : DCHECK(range.IsValid());
29 E : DCHECK(process_state);
30 :
31 E : scoped_refptr<ProcessState::Layer<RecordType>> layer;
32 E : process_state->FindOrCreateLayer(&layer);
33 :
34 E : ProcessState::Layer<RecordType>::RecordPtr record;
35 E : layer->CreateRecord(range, &record);
36 :
37 E : return record->mutable_data();
38 E : }
39 :
40 : } // namespace
41 :
42 : ModuleLayerAccessor::ModuleLayerAccessor(ProcessState* process_state)
43 E : : process_state_(process_state) {
44 E : DCHECK(process_state);
45 E : }
46 :
47 : void ModuleLayerAccessor::AddModuleRecord(const AddressRange& range,
48 : const uint32 checksum,
49 : const uint32 timestamp,
50 E : const std::wstring& path) {
51 E : DCHECK(range.IsValid());
52 :
53 : // Note: we set the preferred loading address to 0.
54 : pe::PEFile::Signature signature(path, core::AbsoluteAddress(0U), range.size(),
55 E : checksum, timestamp);
56 :
57 E : ModuleLayerPtr layer;
58 E : process_state_->FindOrCreateLayer(&layer);
59 E : ModuleId id = layer->mutable_data()->FindOrIndex(signature);
60 :
61 E : Module* module_proto = CreateRecord<Module>(range, process_state_);
62 E : module_proto->set_module_id(id);
63 E : }
64 :
65 : bool ModuleLayerAccessor::GetModuleSignature(const Address va,
66 E : pe::PEFile::Signature* signature) {
67 E : DCHECK(signature);
68 :
69 : // Find the module record corresponding to the virtual address.
70 E : ModuleRecordPtr module_record;
71 E : if (!process_state_->FindSingleRecord(va, &module_record))
72 E : return false;
73 :
74 : // Retrieve the signature.
75 E : const Module& module = module_record->data();
76 E : if (!GetModuleSignature(module.module_id(), signature))
77 i : return false;
78 :
79 : // Set the signature's address.
80 E : const AddressRange& module_range = module_record->range();
81 E : if (!base::IsValueInRangeForNumericType<uint32>(module_range.start())) {
82 i : LOG(ERROR) << "PE::Signature doesn't support 64bit addresses. Address: "
83 : << module_range.start();
84 i : return false;
85 : }
86 : signature->base_address =
87 E : core::AbsoluteAddress(base::checked_cast<uint32>(module_range.start()));
88 :
89 E : return true;
90 E : }
91 :
92 : bool ModuleLayerAccessor::GetModuleSignature(const ModuleId id,
93 E : pe::PEFile::Signature* signature) {
94 E : DCHECK_NE(kNoModuleId, id);
95 E : DCHECK(signature);
96 :
97 E : ModuleLayerPtr layer;
98 E : process_state_->FindOrCreateLayer(&layer);
99 E : return layer->data().Find(id, signature);
100 E : }
101 :
102 E : ModuleId ModuleLayerAccessor::GetModuleId(const Address va) {
103 E : ModuleRecordPtr module_record;
104 E : if (!process_state_->FindSingleRecord(va, &module_record))
105 E : return kNoModuleId;
106 E : return module_record->data().module_id();
107 E : }
108 :
109 : ModuleId ModuleLayerAccessor::GetModuleId(
110 E : const pe::PEFile::Signature& signature) {
111 E : ModuleLayerPtr layer;
112 E : process_state_->FindOrCreateLayer(&layer);
113 E : return layer->data().Find(signature);
114 E : }
115 :
116 : bool AddTypedBlockRecord(const AddressRange& range,
117 : base::StringPiece16 data_name,
118 : ModuleId module_id,
119 : TypeId type_id,
120 E : ProcessState* process_state) {
121 E : DCHECK(range.IsValid());
122 E : DCHECK(process_state);
123 :
124 E : TypedBlock* typedblock_proto = CreateRecord<TypedBlock>(range, process_state);
125 :
126 E : std::string data_name_narrow;
127 E : if (!base::UTF16ToUTF8(data_name.data(), data_name.size(), &data_name_narrow))
128 i : return false;
129 E : typedblock_proto->set_data_name(data_name_narrow);
130 :
131 E : typedblock_proto->set_module_id(module_id);
132 E : typedblock_proto->set_type_id(type_id);
133 :
134 E : return true;
135 E : }
136 :
137 : } // namespace refinery
|