huangs | 8b91a4c9 | 2017-04-25 23:04:58 | [diff] [blame] | 1 | // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "courgette/courgette_flow.h" |
| 6 | |
| 7 | #include <stdarg.h> |
| 8 | |
Peter Boström | fb60ea0 | 2021-04-05 21:06:12 | [diff] [blame] | 9 | #include <memory> |
| 10 | |
Hans Wennborg | e9641ed | 2020-04-27 17:27:11 | [diff] [blame] | 11 | #include "base/check.h" |
huangs | 8b91a4c9 | 2017-04-25 23:04:58 | [diff] [blame] | 12 | #include "base/files/file_path.h" |
huangs | 8b91a4c9 | 2017-04-25 23:04:58 | [diff] [blame] | 13 | #include "base/memory/ptr_util.h" |
Hans Wennborg | e9641ed | 2020-04-27 17:27:11 | [diff] [blame] | 14 | #include "base/notreached.h" |
huangs | 8b91a4c9 | 2017-04-25 23:04:58 | [diff] [blame] | 15 | #include "base/strings/stringprintf.h" |
| 16 | #include "courgette/assembly_program.h" |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 17 | #include "courgette/disassembler.h" |
huangs | 8b91a4c9 | 2017-04-25 23:04:58 | [diff] [blame] | 18 | #include "courgette/encoded_program.h" |
| 19 | #include "courgette/program_detector.h" |
| 20 | |
| 21 | namespace courgette { |
| 22 | |
| 23 | /******** CourgetteFlow::Data ********/ |
| 24 | |
| 25 | CourgetteFlow::Data::Data() = default; |
| 26 | |
| 27 | CourgetteFlow::Data::~Data() = default; |
| 28 | |
| 29 | /******** CourgetteFlow ********/ |
| 30 | |
| 31 | CourgetteFlow::CourgetteFlow() = default; |
| 32 | |
| 33 | CourgetteFlow::~CourgetteFlow() = default; |
| 34 | |
| 35 | // static |
| 36 | const char* CourgetteFlow::name(Group group) { |
| 37 | switch (group) { |
| 38 | case ONLY: |
| 39 | return "input"; |
| 40 | case OLD: |
| 41 | return "'old' input"; |
| 42 | case NEW: |
| 43 | return "'new' input"; |
| 44 | default: |
| 45 | NOTREACHED(); |
| 46 | break; |
| 47 | } |
| 48 | return nullptr; |
| 49 | } |
| 50 | |
| 51 | CourgetteFlow::Data* CourgetteFlow::data(Group group) { |
| 52 | switch (group) { |
| 53 | case ONLY: |
| 54 | return &data_only_; |
| 55 | case OLD: |
| 56 | return &data_old_; |
| 57 | case NEW: |
| 58 | return &data_new_; |
| 59 | default: |
| 60 | NOTREACHED(); |
| 61 | break; |
| 62 | } |
| 63 | return nullptr; |
| 64 | } |
| 65 | |
| 66 | bool CourgetteFlow::ok() { |
| 67 | return status_ == C_OK; |
| 68 | } |
| 69 | |
| 70 | bool CourgetteFlow::failed() { |
| 71 | return status_ != C_OK; |
| 72 | } |
| 73 | |
| 74 | Status CourgetteFlow::status() { |
| 75 | return status_; |
| 76 | } |
| 77 | |
| 78 | const std::string& CourgetteFlow::message() { |
| 79 | return message_; |
| 80 | } |
| 81 | |
| 82 | void CourgetteFlow::ReadSourceStreamSetFromBuffer(Group group, |
| 83 | const BasicBuffer& buffer) { |
| 84 | if (failed()) |
| 85 | return; |
| 86 | Data* d = data(group); |
| 87 | if (!check(d->sources.Init(buffer.data(), buffer.length()), |
| 88 | C_GENERAL_ERROR)) { |
| 89 | setMessage("Cannot read %s as SourceStreamSet.", name(group)); |
| 90 | } |
| 91 | } |
| 92 | |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 93 | void CourgetteFlow::ReadDisassemblerFromBuffer(Group group, |
| 94 | const BasicBuffer& buffer) { |
huangs | 8b91a4c9 | 2017-04-25 23:04:58 | [diff] [blame] | 95 | if (failed()) |
| 96 | return; |
| 97 | Data* d = data(group); |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 98 | d->disassembler = DetectDisassembler(buffer.data(), buffer.length()); |
| 99 | if (!check(d->disassembler.get() != nullptr, C_INPUT_NOT_RECOGNIZED)) |
| 100 | setMessage("Cannot detect program for %s.", name(group)); |
huangs | 8b91a4c9 | 2017-04-25 23:04:58 | [diff] [blame] | 101 | } |
| 102 | |
| 103 | void CourgetteFlow::ReadEncodedProgramFromSourceStreamSet( |
| 104 | Group group, |
| 105 | SourceStreamSet* opt_sources /* nullptr */) { |
| 106 | if (failed()) |
| 107 | return; |
| 108 | Data* d = data(group); |
| 109 | SourceStreamSet* sources = opt_sources ? opt_sources : &d->sources; |
| 110 | if (!check(ReadEncodedProgram(sources, &d->encoded))) |
| 111 | setMessage("Cannot read %s as encoded program.", name(group)); |
| 112 | } |
| 113 | |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 114 | void CourgetteFlow::CreateAssemblyProgramFromDisassembler(Group group, |
| 115 | bool annotate) { |
huangs | 8b91a4c9 | 2017-04-25 23:04:58 | [diff] [blame] | 116 | if (failed()) |
| 117 | return; |
| 118 | Data* d = data(group); |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 119 | d->program = d->disassembler->CreateProgram(annotate); |
| 120 | if (!check(d->program.get() != nullptr, C_DISASSEMBLY_FAILED)) |
| 121 | setMessage("Cannot create AssemblyProgram for %s.", name(group)); |
| 122 | } |
| 123 | |
| 124 | void CourgetteFlow::CreateEncodedProgramFromDisassemblerAndAssemblyProgram( |
| 125 | Group group) { |
| 126 | if (failed()) |
| 127 | return; |
| 128 | Data* d = data(group); |
Peter Boström | fb60ea0 | 2021-04-05 21:06:12 | [diff] [blame] | 129 | d->encoded = std::make_unique<EncodedProgram>(); |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 130 | if (!check(d->disassembler->DisassembleAndEncode(d->program.get(), |
| 131 | d->encoded.get()))) { |
| 132 | setMessage("Cannot disassemble to form EncodedProgram for %s.", |
| 133 | name(group)); |
| 134 | } |
huangs | 8b91a4c9 | 2017-04-25 23:04:58 | [diff] [blame] | 135 | } |
| 136 | |
| 137 | void CourgetteFlow::WriteSinkStreamFromSinkStreamSet(Group group, |
| 138 | SinkStream* sink) { |
| 139 | DCHECK(sink); |
| 140 | if (failed()) |
| 141 | return; |
| 142 | if (!check(data(group)->sinks.CopyTo(sink), C_GENERAL_ERROR)) |
| 143 | setMessage("Cannnot combine serialized streams for %s.", name(group)); |
| 144 | } |
| 145 | |
| 146 | void CourgetteFlow::WriteSinkStreamSetFromEncodedProgram( |
| 147 | Group group, |
| 148 | SinkStreamSet* opt_sinks /* nullptr */) { |
| 149 | if (failed()) |
| 150 | return; |
| 151 | Data* d = data(group); |
| 152 | SinkStreamSet* sinks = opt_sinks ? opt_sinks : &d->sinks; |
| 153 | if (!check(WriteEncodedProgram(d->encoded.get(), sinks))) |
| 154 | setMessage("Cannot serialize encoded %s.", name(group)); |
| 155 | } |
| 156 | |
| 157 | void CourgetteFlow::WriteExecutableFromEncodedProgram(Group group, |
| 158 | SinkStream* sink) { |
| 159 | DCHECK(sink); |
| 160 | if (failed()) |
| 161 | return; |
| 162 | if (!check(Assemble(data(group)->encoded.get(), sink))) |
| 163 | setMessage("Cannot assemble %s.", name(group)); |
| 164 | } |
| 165 | |
| 166 | void CourgetteFlow::AdjustNewAssemblyProgramToMatchOld() { |
| 167 | if (failed()) |
| 168 | return; |
| 169 | if (!check(Adjust(*data_old_.program, data_new_.program.get()))) |
| 170 | setMessage("Cannot adjust %s to match %s.", name(OLD), name(NEW)); |
| 171 | } |
| 172 | |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 173 | void CourgetteFlow::DestroyDisassembler(Group group) { |
| 174 | if (failed()) |
| 175 | return; |
| 176 | data(group)->disassembler.reset(); |
| 177 | } |
| 178 | |
huangs | 8b91a4c9 | 2017-04-25 23:04:58 | [diff] [blame] | 179 | void CourgetteFlow::DestroyAssemblyProgram(Group group) { |
| 180 | if (failed()) |
| 181 | return; |
| 182 | data(group)->program.reset(); |
| 183 | } |
| 184 | |
| 185 | void CourgetteFlow::DestroyEncodedProgram(Group group) { |
| 186 | if (failed()) |
| 187 | return; |
| 188 | data(group)->encoded.reset(); |
| 189 | } |
| 190 | |
| 191 | bool CourgetteFlow::check(Status new_status) { |
| 192 | if (new_status == C_OK) |
| 193 | return true; |
| 194 | status_ = new_status; |
| 195 | return false; |
| 196 | } |
| 197 | |
| 198 | bool CourgetteFlow::check(bool success, Status failure_mode) { |
| 199 | if (success) |
| 200 | return true; |
| 201 | status_ = failure_mode; |
| 202 | return false; |
| 203 | } |
| 204 | |
| 205 | void CourgetteFlow::setMessage(const char* format, ...) { |
| 206 | va_list args; |
| 207 | va_start(args, format); |
| 208 | message_ = base::StringPrintV(format, args); |
| 209 | va_end(args); |
| 210 | } |
| 211 | |
| 212 | } // namespace courgette |