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