OLD | NEW |
1 // Copyright 2015 Google Inc. All Rights Reserved. | 1 // Copyright 2015 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 #include "syzygy/experimental/protect/protect_lib/protect_utils.h" |
15 #include "syzygy/instrument/instrumenters/flummox_instrumenter.h" | |
16 | |
17 #include <algorithm> | |
18 #include <sstream> | |
19 | 15 |
20 #include "base/values.h" | 16 #include "base/values.h" |
21 #include "base/files/file_util.h" | |
22 #include "base/json/json_reader.h" | 17 #include "base/json/json_reader.h" |
23 #include "base/strings/string_util.h" | |
24 #include "syzygy/application/application.h" | |
25 | 18 |
26 namespace instrument { | 19 namespace protect { |
27 namespace instrumenters { | |
28 | 20 |
29 namespace { | 21 bool ShouldProcessBlock(const BlockGraph::Block* block, |
| 22 const std::map<std::string, bool> target_names) { |
| 23 return (target_names.find(block->name()) != target_names.end()); |
| 24 } |
| 25 bool ShouldPostProcessBlock( |
| 26 const BlockGraph::Block* block, |
| 27 const std::map<uint64_t, BlockGraph::Label> *id_to_label) { |
| 28 if (block->labels().size() == 0) return false; |
| 29 if (GetBasicBlockIdByLabel(block->labels().begin()->second, |
| 30 id_to_label) == -1) { |
| 31 return false; |
| 32 } |
| 33 return true; |
| 34 } |
| 35 uint64_t GetBasicBlockIdByLabel( |
| 36 const BlockGraph::Label label, |
| 37 const std::map<uint64_t, BlockGraph::Label> *id_to_label){ |
| 38 auto it = id_to_label->begin(); |
| 39 for (; it != id_to_label->end(); ++it) { |
| 40 if (it->second == label) |
| 41 return it->first; |
| 42 } |
| 43 |
| 44 return (uint64_t)-1; |
| 45 } |
| 46 |
| 47 void GetChunkTokensFromlabel(const std::string label, |
| 48 uint64_t *chunk_bb_id, |
| 49 uint32_t *chunk_index){ |
| 50 //split the string |
| 51 std::istringstream iss(label); |
| 52 std::vector<std::string> tokens; |
| 53 copy(std::istream_iterator<std::string>(iss), |
| 54 std::istream_iterator<std::string>(), |
| 55 back_inserter(tokens) |
| 56 ); |
| 57 DCHECK(tokens.size() > 2); |
| 58 *chunk_bb_id = std::stoull(tokens.at(1)); |
| 59 *chunk_index = std::stoul(tokens.at(2)); |
| 60 } |
| 61 |
| 62 uint64_t GetChunkUniqueKey(const uint64_t bb_id, const uint32_t chunk_index){ |
| 63 return std::hash<std::string>()(std::to_string(bb_id) |
| 64 + std::to_string(chunk_index)); |
| 65 } |
30 | 66 |
31 using base::DictionaryValue; | 67 using base::DictionaryValue; |
32 using base::ListValue; | 68 using base::ListValue; |
33 using base::Value; | 69 using base::Value; |
34 | 70 |
35 } // namespace | 71 bool FlummoxConfig::ReadFromJSON(const std::string& json) { |
| 72 bool input_add_copy = false; |
| 73 double input_chunk_coverage = 1.0; |
36 | 74 |
37 bool FlummoxInstrumenter::FlummoxConfig::ReadFromJSON(const std::string& json) { | |
38 bool input_add_copy = false; | |
39 scoped_ptr<Value> value(base::JSONReader::Read(json)); | 75 scoped_ptr<Value> value(base::JSONReader::Read(json)); |
40 if (value.get() == nullptr) { | 76 if (value.get() == nullptr) { |
41 LOG(ERROR) << "Invalid or empty configuration JSON."; | 77 LOG(ERROR) << "Invalid or empty configuration JSON."; |
42 return false; | 78 return false; |
43 } | 79 } |
44 if (value->GetType() != Value::TYPE_DICTIONARY) { | 80 if (value->GetType() != Value::TYPE_DICTIONARY) { |
45 LOG(ERROR) << "Invalid allocation filter transform file."; | 81 LOG(ERROR) << "Invalid allocation filter transform file."; |
46 return false; | 82 return false; |
47 } | 83 } |
48 | 84 |
49 const DictionaryValue* outer_dict = | 85 const DictionaryValue* outer_dict = |
50 reinterpret_cast<const DictionaryValue*>(value.get()); | 86 reinterpret_cast<const DictionaryValue*>(value.get()); |
51 | 87 |
| 88 |
| 89 std::string chunk_coverage_key("chunk_coverage"); |
| 90 if (outer_dict->HasKey(chunk_coverage_key) && |
| 91 !outer_dict->GetDouble(chunk_coverage_key, &input_chunk_coverage)) { |
| 92 LOG(ERROR) << chunk_coverage_key << " must be a double."; |
| 93 return false; |
| 94 } |
| 95 if (input_chunk_coverage > 10.0 || input_chunk_coverage < 0.0) { |
| 96 LOG(ERROR) << chunk_coverage_key << " must be between [0.0,10.0] ."; |
| 97 return false; |
| 98 } |
| 99 |
| 100 |
52 std::string targets_key("targets"); | 101 std::string targets_key("targets"); |
53 const DictionaryValue* targets_dict = nullptr; | 102 const DictionaryValue* targets_dict = nullptr; |
54 | 103 |
55 if (!outer_dict->GetDictionary(targets_key, &targets_dict)) { | 104 if (!outer_dict->GetDictionary(targets_key, &targets_dict)) { |
56 LOG(ERROR) << "Outer dictionary must contain key 'targets'."; | 105 LOG(ERROR) << "Outer dictionary must contain key 'targets'."; |
57 return false; | 106 return false; |
58 } | 107 } |
59 | 108 |
60 std::set<std::string> temp_target_set; | 109 std::set<std::string> temp_target_set; |
61 DictionaryValue::Iterator it(*targets_dict); | 110 DictionaryValue::Iterator it(*targets_dict); |
62 for (; !it.IsAtEnd(); it.Advance()) { | 111 for (; !it.IsAtEnd(); it.Advance()) { |
63 std::string function_name = it.key(); | 112 std::string function_name = it.key(); |
64 const ListValue* strategy_list = nullptr; | 113 const ListValue* strategy_list = nullptr; |
65 if (!it.value().GetAsList(&strategy_list)) { | 114 if (!it.value().GetAsList(&strategy_list)) { |
66 LOG(ERROR) << "Strategy list expected."; | 115 LOG(ERROR) << "Strategy list expected."; |
67 return false; | 116 return false; |
68 } | 117 } |
69 // TODO(huangs): Load strategies. | 118 // TODO(huangs): Load strategies. |
70 // for (const Value* strategy : *strategy_list) { } | 119 // for (const Value* strategy : *strategy_list) { } |
71 temp_target_set.insert(function_name); | 120 temp_target_set.insert(function_name); |
72 } | 121 } |
73 | 122 |
74 std::string add_copy_key("add_copy"); | 123 std::string add_copy_key("add_copy"); |
75 if (outer_dict->HasKey(add_copy_key) && | 124 if (outer_dict->HasKey(add_copy_key) && |
76 !outer_dict->GetBoolean(add_copy_key, &input_add_copy)) { | 125 !outer_dict->GetBoolean(add_copy_key, &input_add_copy)) { |
77 LOG(ERROR) << add_copy_key << " must be a boolean."; | 126 LOG(ERROR) << add_copy_key << " must be a boolean."; |
78 return false; | 127 return false; |
79 } | 128 } |
80 | 129 |
| 130 |
81 // Success! | 131 // Success! |
82 target_set_.swap(temp_target_set); | 132 target_set_.swap(temp_target_set); |
83 add_copy_ = input_add_copy; | 133 add_copy_ = input_add_copy; |
| 134 chunk_checking_coverage_ = input_chunk_coverage; |
84 return true; | 135 return true; |
85 } | 136 } |
86 | 137 |
87 bool FlummoxInstrumenter::FlummoxConfig::ReadFromJSONPath( | 138 bool FlummoxConfig::ReadFromJSONPath( |
88 const base::FilePath& path) { | 139 const base::FilePath& path) { |
89 std::string file_string; | 140 std::string file_string; |
90 if (!base::ReadFileToString(path, &file_string)) { | 141 if (!base::ReadFileToString(path, &file_string)) { |
91 LOG(ERROR) << "Unable to read file to string."; | 142 LOG(ERROR) << "Unable to read file to string."; |
92 return false; | 143 return false; |
93 } | 144 } |
94 if (!ReadFromJSON(file_string)) { | 145 if (!ReadFromJSON(file_string)) { |
95 LOG(ERROR) << "Unable to parse JSON string."; | 146 LOG(ERROR) << "Unable to parse JSON string."; |
96 return false; | 147 return false; |
97 } | 148 } |
98 return true; | 149 return true; |
99 } | 150 } |
100 | 151 |
101 bool FlummoxInstrumenter::InstrumentPrepare() { | 152 } // namespace protect |
102 return config_.ReadFromJSONPath(flummox_config_path_); | |
103 } | |
104 | |
105 bool FlummoxInstrumenter::InstrumentImpl() { | |
106 flummox_transform_.reset( | |
107 new instrument::transforms::FillerTransform( | |
108 config_.target_set(), config_.add_copy())); | |
109 flummox_transform_->set_debug_friendly(debug_friendly_); | |
110 | |
111 if (!relinker_->AppendTransform(flummox_transform_.get())) { | |
112 LOG(ERROR) << "Failed to apply transform."; | |
113 return false; | |
114 } | |
115 | |
116 return true; | |
117 } | |
118 | |
119 bool FlummoxInstrumenter::DoCommandLineParse( | |
120 const base::CommandLine* command_line) { | |
121 DCHECK(command_line != nullptr); | |
122 | |
123 if (!Super::DoCommandLineParse(command_line)) | |
124 return false; | |
125 | |
126 // Parse the target list filename. | |
127 flummox_config_path_ = application::AppImplBase::AbsolutePath( | |
128 command_line->GetSwitchValuePath("flummox-config-path")); | |
129 if (flummox_config_path_.empty()) { | |
130 LOG(ERROR) << "You must specify --flummox-config-path."; | |
131 return false; | |
132 } | |
133 | |
134 return true; | |
135 } | |
136 | |
137 } // namespace instrumenters | |
138 } // namespace instrument | |
OLD | NEW |