forked from win32ss/supermium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
courgette_flow.h
153 lines (115 loc) · 4.83 KB
/
courgette_flow.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COURGETTE_COURGETTE_FLOW_H_
#define COURGETTE_COURGETTE_FLOW_H_
#include <memory>
#include <string>
#include "courgette/courgette.h"
#include "courgette/region.h"
#include "courgette/streams.h"
namespace courgette {
class AssemblyProgram;
class Disassembler;
class EncodedProgram;
// An adaptor for Region as BasicBuffer.
class RegionBuffer : public BasicBuffer {
public:
explicit RegionBuffer(const Region& region) : region_(region) {}
RegionBuffer(const RegionBuffer&) = delete;
RegionBuffer& operator=(const RegionBuffer&) = delete;
~RegionBuffer() override {}
// BasicBuffer:
const uint8_t* data() const override { return region_.start(); }
size_t length() const override { return region_.length(); }
private:
Region region_;
};
// CourgetteFlow stores Courgette data arranged into groups, and exposes
// "commands" that operate on them. On the first occurrence of an error, the
// Courgette error code is recorded, error messages are generated and stored,
// and all subsequent commands become no-op. This allows callers to concisely
// specify high-level logic with minimal code for error handling.
class CourgetteFlow {
public:
// A group of Courgette data, for a single executable. Takes negligible space
// when unused.
struct Data {
Data();
~Data();
std::unique_ptr<Disassembler> disassembler;
std::unique_ptr<AssemblyProgram> program;
std::unique_ptr<EncodedProgram> encoded;
SinkStreamSet sinks;
SourceStreamSet sources;
};
// Group enumeration into |data_*_| fields.
enum Group {
ONLY, // The only file processed.
OLD, // The "old" file during patching.
NEW, // The "new" file during patching.
};
CourgetteFlow();
CourgetteFlow(const CourgetteFlow&) = delete;
CourgetteFlow& operator=(const CourgetteFlow&) = delete;
~CourgetteFlow();
static const char* name(Group group);
Data* data(Group group); // Allows caller to modify.
bool ok();
bool failed();
Status status();
const std::string& message();
// Commands that perform no-op on error. This allows caller to concisely
// specify high-level logic, and perform a single error check at the end. Care
// must be taken w.r.t. error handling if |data()| is harvested between
// commands.
// Reads |buffer| to initialize |data(group)->sources|.
void ReadSourceStreamSetFromBuffer(Group group, const BasicBuffer& buffer);
// Reads |buffer| to initialize |data(group)->disassembler|.
void ReadDisassemblerFromBuffer(Group group, const BasicBuffer& buffer);
// Reads |opt_sources| if given, or else |data(group)->sources| to initialize
// |data(group).encoded|.
void ReadEncodedProgramFromSourceStreamSet(
Group group,
SourceStreamSet* opt_sources = nullptr);
// Uses |data(group)->disassembler| to initialize |data(group)->program|,
// passing |annotate| as initialization parameter (should be true if
// AdjustNewAssemblyProgramToMatchOld() gets called later).
void CreateAssemblyProgramFromDisassembler(Group group, bool annotate);
// Uses |data(group)->disassembler| and |data(group)->program| to initialize
// |data(group)->encoded|.
void CreateEncodedProgramFromDisassemblerAndAssemblyProgram(Group group);
// Serializese |data(group)->sinks| to |sink|.
void WriteSinkStreamFromSinkStreamSet(Group group, SinkStream* sink);
// Serializes |data(group)->encoded| to |opt_sinks| if given, or else to
// |data(group)->sinks|.
void WriteSinkStreamSetFromEncodedProgram(Group group,
SinkStreamSet* opt_sinks = nullptr);
// Converts |data(group)->encoded| to an exectuable and writes the result to
// |sink|.
void WriteExecutableFromEncodedProgram(Group group, SinkStream* sink);
// Adjusts |data(NEW)->program| Labels to match |data(OLD)->program| Labels.
void AdjustNewAssemblyProgramToMatchOld();
// Destructor commands to reduce memory usage.
void DestroyDisassembler(Group group);
void DestroyAssemblyProgram(Group group);
void DestroyEncodedProgram(Group group);
private:
// Utilities to process return values from Courgette functions, and assign
// |status_| and |message_|. Usage:
// if (!check(some_courgette_function(param1, ...)))
// setMessage("format string %s...", value1, ...);
// Reassigns |status_|, and returns true if |C_OK|.
bool check(Status new_status);
// check() alternative for functions that return true on success. On failure
// assigns |status_| to |failure_mode|.
bool check(bool success, Status failure_mode);
void setMessage(const char* format, ...);
Status status_ = C_OK;
std::string message_;
Data data_only_;
Data data_old_;
Data data_new_;
};
} // namespace courgette
#endif // COURGETTE_COURGETTE_FLOW_H_