1 : // Copyright 2012 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 : // Implements the AddIndexedFrequencyDataTransform class.
16 :
17 : #include "syzygy/instrument/transforms/add_indexed_frequency_data_transform.h"
18 :
19 : #include "syzygy/block_graph/typed_block.h"
20 : #include "syzygy/pe/pe_utils.h"
21 :
22 : namespace instrument {
23 : namespace transforms {
24 :
25 : const char AddIndexedFrequencyDataTransform::kTransformName[] =
26 : "AddFrequencyDataTransform";
27 :
28 : AddIndexedFrequencyDataTransform::AddIndexedFrequencyDataTransform(
29 : uint32_t agent_id,
30 : const base::StringPiece& freq_name,
31 : uint32_t version,
32 : IndexedFrequencyData::DataType data_type,
33 : size_t indexed_frequency_data_size)
34 E : : agent_id_(agent_id),
35 E : freq_name_(freq_name.begin(), freq_name.end()),
36 E : version_(version),
37 E : data_type_(data_type),
38 E : frequency_data_block_(NULL),
39 E : frequency_data_block_size_(indexed_frequency_data_size),
40 E : frequency_data_buffer_block_(NULL) {
41 E : DCHECK_LE(sizeof(IndexedFrequencyData), indexed_frequency_data_size);
42 E : }
43 :
44 : bool AddIndexedFrequencyDataTransform::TransformBlockGraph(
45 : const TransformPolicyInterface* policy,
46 : BlockGraph* block_graph,
47 E : BlockGraph::Block* header_block) {
48 E : DCHECK(block_graph != NULL);
49 E : DCHECK(header_block != NULL);
50 E : DCHECK(frequency_data_block_ == NULL);
51 E : DCHECK(data_type_ != IndexedFrequencyData::INVALID_DATA_TYPE);
52 :
53 : // Get the read/write ".data" section. We will add our blocks to it.
54 E : BlockGraph::Section* section = block_graph->FindOrAddSection(
55 : pe::kReadWriteDataSectionName, pe::kReadWriteDataCharacteristics);
56 E : if (section == NULL) {
57 i : LOG(ERROR) << "Failed to find/add read-write data section \""
58 : << pe::kReadWriteDataSectionName << "\".";
59 i : return false;
60 : }
61 :
62 : // Add a block for the frequency data.
63 : BlockGraph::Block* data_block =
64 E : block_graph->AddBlock(BlockGraph::DATA_BLOCK,
65 : frequency_data_block_size_,
66 : freq_name_);
67 E : if (data_block == NULL) {
68 i : LOG(ERROR) << "Failed to add the " << freq_name_ << " block.";
69 i : return false;
70 : }
71 :
72 : // Add a block for the array of frequency data. We give this block an initial
73 : // size of 1 because drawing a reference to an empty block is not possible.
74 E : BlockGraph::Block* buffer_block = block_graph->AddBlock(
75 : BlockGraph::DATA_BLOCK, 1, freq_name_ + " Buffer");
76 E : if (buffer_block == NULL) {
77 i : LOG(ERROR) << "Failed to allocate frequency data buffer block.";
78 i : return false;
79 : }
80 :
81 : // Put them both in the data section.
82 E : data_block->set_section(section->id());
83 E : buffer_block->set_section(section->id());
84 :
85 : // Allocate the data that will be used to initialize the static instance.
86 : // The allocated bytes will be zero-initialized.
87 : IndexedFrequencyData* frequency_data =
88 : reinterpret_cast<IndexedFrequencyData*>(
89 E : data_block->AllocateData(data_block->size()));
90 E : if (frequency_data == NULL) {
91 i : LOG(ERROR) << "Failed to allocate frequency data.";
92 i : return false;
93 : }
94 : // Initialize the non-zero fields of the structure.
95 E : frequency_data->agent_id = agent_id_;
96 E : frequency_data->version = version_;
97 E : frequency_data->data_type = data_type_;
98 :
99 : // Setup the frequency_data pointer such that it points to the newly allocated
100 : // buffer.
101 E : if (!data_block->SetReference(
102 : offsetof(IndexedFrequencyData, frequency_data),
103 : BlockGraph::Reference(BlockGraph::ABSOLUTE_REF,
104 : BlockGraph::Reference::kMaximumSize,
105 : buffer_block,
106 : 0,
107 : 0))) {
108 i : LOG(ERROR) << "Failed to initialize frequency_data buffer pointer.";
109 i : return false;
110 : }
111 :
112 : // Remember the new blocks.
113 E : frequency_data_block_ = data_block;
114 E : frequency_data_buffer_block_ = buffer_block;
115 :
116 : // And we're done.
117 E : return true;
118 E : }
119 :
120 : bool AddIndexedFrequencyDataTransform::ConfigureFrequencyDataBuffer(
121 : uint32_t num_entries,
122 : uint32_t num_columns,
123 E : uint8_t frequency_size) {
124 E : DCHECK_NE(0U, num_entries);
125 E : DCHECK_NE(0U, num_columns);
126 E : DCHECK(frequency_size == 1 || frequency_size == 2 || frequency_size == 4);
127 E : DCHECK(frequency_data_block_ != NULL);
128 E : DCHECK(frequency_data_buffer_block_ != NULL);
129 E : DCHECK_EQ(frequency_data_block_size_,
130 E : frequency_data_block_->data_size());
131 :
132 : // Update the related fields in the data structure.
133 E : block_graph::TypedBlock<IndexedFrequencyData> frequency_data;
134 E : CHECK(frequency_data.Init(0, frequency_data_block_));
135 E : frequency_data->num_entries = num_entries;
136 E : frequency_data->num_columns = num_columns;
137 E : frequency_data->frequency_size = frequency_size;
138 :
139 : // Resize the buffer block.
140 E : size_t buffer_size = num_entries * num_columns * frequency_size;
141 E : frequency_data_buffer_block_->set_size(buffer_size);
142 :
143 : // And we're done.
144 E : return true;
145 E : }
146 :
147 : } // namespace transforms
148 : } // namespace instrument
|