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