blob: f96e4ab47722ce2e66c078f34db286319a252f4f [file] [log] [blame]
huangs8b91a4c92017-04-25 23:04:581// 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ömfb60ea02021-04-05 21:06:129#include <memory>
10
Hans Wennborge9641ed2020-04-27 17:27:1111#include "base/check.h"
huangs8b91a4c92017-04-25 23:04:5812#include "base/files/file_path.h"
huangs8b91a4c92017-04-25 23:04:5813#include "base/memory/ptr_util.h"
Hans Wennborge9641ed2020-04-27 17:27:1114#include "base/notreached.h"
huangs8b91a4c92017-04-25 23:04:5815#include "base/strings/stringprintf.h"
16#include "courgette/assembly_program.h"
huangs88451332017-05-18 19:50:3417#include "courgette/disassembler.h"
huangs8b91a4c92017-04-25 23:04:5818#include "courgette/encoded_program.h"
19#include "courgette/program_detector.h"
20
21namespace courgette {
22
23/******** CourgetteFlow::Data ********/
24
25CourgetteFlow::Data::Data() = default;
26
27CourgetteFlow::Data::~Data() = default;
28
29/******** CourgetteFlow ********/
30
31CourgetteFlow::CourgetteFlow() = default;
32
33CourgetteFlow::~CourgetteFlow() = default;
34
35// static
36const 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
51CourgetteFlow::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
66bool CourgetteFlow::ok() {
67 return status_ == C_OK;
68}
69
70bool CourgetteFlow::failed() {
71 return status_ != C_OK;
72}
73
74Status CourgetteFlow::status() {
75 return status_;
76}
77
78const std::string& CourgetteFlow::message() {
79 return message_;
80}
81
82void 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
huangs88451332017-05-18 19:50:3493void CourgetteFlow::ReadDisassemblerFromBuffer(Group group,
94 const BasicBuffer& buffer) {
huangs8b91a4c92017-04-25 23:04:5895 if (failed())
96 return;
97 Data* d = data(group);
huangs88451332017-05-18 19:50:3498 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));
huangs8b91a4c92017-04-25 23:04:58101}
102
103void 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
huangs88451332017-05-18 19:50:34114void CourgetteFlow::CreateAssemblyProgramFromDisassembler(Group group,
115 bool annotate) {
huangs8b91a4c92017-04-25 23:04:58116 if (failed())
117 return;
118 Data* d = data(group);
huangs88451332017-05-18 19:50:34119 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
124void CourgetteFlow::CreateEncodedProgramFromDisassemblerAndAssemblyProgram(
125 Group group) {
126 if (failed())
127 return;
128 Data* d = data(group);
Peter Boströmfb60ea02021-04-05 21:06:12129 d->encoded = std::make_unique<EncodedProgram>();
huangs88451332017-05-18 19:50:34130 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 }
huangs8b91a4c92017-04-25 23:04:58135}
136
137void 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
146void 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
157void 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
166void 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
huangs88451332017-05-18 19:50:34173void CourgetteFlow::DestroyDisassembler(Group group) {
174 if (failed())
175 return;
176 data(group)->disassembler.reset();
177}
178
huangs8b91a4c92017-04-25 23:04:58179void CourgetteFlow::DestroyAssemblyProgram(Group group) {
180 if (failed())
181 return;
182 data(group)->program.reset();
183}
184
185void CourgetteFlow::DestroyEncodedProgram(Group group) {
186 if (failed())
187 return;
188 data(group)->encoded.reset();
189}
190
191bool CourgetteFlow::check(Status new_status) {
192 if (new_status == C_OK)
193 return true;
194 status_ = new_status;
195 return false;
196}
197
198bool CourgetteFlow::check(bool success, Status failure_mode) {
199 if (success)
200 return true;
201 status_ = failure_mode;
202 return false;
203}
204
205void 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