Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: courgette/assembly_program.h

Issue 2462993003: [Courgette] Refactor: Add and use Instruction*Receptor classes; call ParseFile() in 2 passes. (Closed)
Patch Set: Fix style and comments; lint; remove size param from InstructionStoreReceptor ctor. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef COURGETTE_ASSEMBLY_PROGRAM_H_ 5 #ifndef COURGETTE_ASSEMBLY_PROGRAM_H_
6 #define COURGETTE_ASSEMBLY_PROGRAM_H_ 6 #define COURGETTE_ASSEMBLY_PROGRAM_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
11 #include <map> 11 #include <map>
12 #include <memory> 12 #include <memory>
13 #include <set> 13 #include <set>
14 #include <vector> 14 #include <vector>
15 15
16 #include "base/bind.h" 16 #include "base/bind.h"
17 #include "base/macros.h" 17 #include "base/macros.h"
18 #include "base/memory/free_deleter.h" 18 #include "base/memory/free_deleter.h"
19 #include "courgette/courgette.h" 19 #include "courgette/courgette.h"
20 #include "courgette/image_utils.h" 20 #include "courgette/image_utils.h"
21 #include "courgette/label_manager.h" 21 #include "courgette/label_manager.h"
22 #include "courgette/memory_allocator.h" 22 #include "courgette/memory_allocator.h"
23 23
24 namespace courgette { 24 namespace courgette {
25 25
26 class AssemblyProgram;
26 class EncodedProgram; 27 class EncodedProgram;
27 28
28 // Opcodes of simple assembly language 29 // Opcodes of simple assembly language
29 enum OP { 30 enum OP {
30 ORIGIN, // ORIGIN <rva> - set current address for assembly. 31 ORIGIN, // ORIGIN <rva> - set current address for assembly.
31 MAKEPERELOCS, // Generates a base relocation table. 32 MAKEPERELOCS, // Generates a base relocation table.
32 MAKEELFRELOCS, // Generates a base relocation table. 33 MAKEELFRELOCS, // Generates a base relocation table.
33 DEFBYTE, // DEFBYTE <value> - emit a byte literal. 34 DEFBYTE, // DEFBYTE <value> - emit a byte literal.
34 REL32, // REL32 <label> - emit a rel32 encoded reference to 'label'. 35 REL32, // REL32 <label> - emit a rel32 encoded reference to 'label'.
35 ABS32, // ABS32 <label> - emit an abs32 encoded reference to 'label'. 36 ABS32, // ABS32 <label> - emit an abs32 encoded reference to 'label'.
(...skipping 14 matching lines...) Expand all
50 explicit Instruction(OP op) : op_(op), info_(0) {} 51 explicit Instruction(OP op) : op_(op), info_(0) {}
51 Instruction(OP op, unsigned int info) : op_(op), info_(info) {} 52 Instruction(OP op, unsigned int info) : op_(op), info_(info) {}
52 53
53 uint32_t op_ : 4; // A few bits to store the OP code. 54 uint32_t op_ : 4; // A few bits to store the OP code.
54 uint32_t info_ : 28; // Remaining bits in first word available to subclass. 55 uint32_t info_ : 28; // Remaining bits in first word available to subclass.
55 56
56 private: 57 private:
57 DISALLOW_COPY_AND_ASSIGN(Instruction); 58 DISALLOW_COPY_AND_ASSIGN(Instruction);
58 }; 59 };
59 60
60 typedef NoThrowBuffer<Instruction*> InstructionVector; 61 class InstructionReceptor {
62 public:
63 InstructionReceptor() = default;
64 virtual ~InstructionReceptor() = default;
65
66 // Generates an entire base relocation table.
67 virtual CheckBool EmitPeRelocs() WARN_UNUSED_RESULT = 0;
68
69 // Generates an ELF style relocation table for X86.
70 virtual CheckBool EmitElfRelocation() WARN_UNUSED_RESULT = 0;
71
72 // Generates an ELF style relocation table for ARM.
73 virtual CheckBool EmitElfARMRelocation() WARN_UNUSED_RESULT = 0;
74
75 // Following instruction will be assembled at address 'rva'.
76 virtual CheckBool EmitOrigin(RVA rva) WARN_UNUSED_RESULT = 0;
77
78 // Generates a single byte of data or machine instruction.
79 virtual CheckBool EmitSingleByte(uint8_t byte) WARN_UNUSED_RESULT = 0;
80
81 // Generates multiple bytes of data or machine instructions.
82 virtual CheckBool EmitMultipleBytes(const uint8_t* bytes,
83 size_t len) WARN_UNUSED_RESULT = 0;
84
85 // Generates a 4-byte relative reference to address of 'label'.
86 virtual CheckBool EmitRel32(Label* label) WARN_UNUSED_RESULT = 0;
87
88 // Generates a 4-byte relative reference to address of 'label' for ARM.
89 virtual CheckBool EmitRel32ARM(uint16_t op,
90 Label* label,
91 const uint8_t* arm_op,
92 uint16_t op_size) WARN_UNUSED_RESULT = 0;
93
94 // Generates a 4-byte absolute reference to address of 'label'.
95 virtual CheckBool EmitAbs32(Label* label) WARN_UNUSED_RESULT = 0;
96
97 // Generates an 8-byte absolute reference to address of 'label'.
98 virtual CheckBool EmitAbs64(Label* label) WARN_UNUSED_RESULT = 0;
99
100 private:
101 DISALLOW_COPY_AND_ASSIGN(InstructionReceptor);
102 };
103
104 class InstructionCountReceptor : public InstructionReceptor {
105 public:
106 InstructionCountReceptor() = default;
107
108 size_t size() const { return size_; }
109
110 // InstructionReceptor:
111 CheckBool EmitPeRelocs() override WARN_UNUSED_RESULT;
112 CheckBool EmitElfRelocation() override WARN_UNUSED_RESULT;
113 CheckBool EmitElfARMRelocation() override WARN_UNUSED_RESULT;
114 CheckBool EmitOrigin(RVA rva) override WARN_UNUSED_RESULT;
115 CheckBool EmitSingleByte(uint8_t byte) override WARN_UNUSED_RESULT;
116 CheckBool EmitMultipleBytes(const uint8_t* bytes,
117 size_t len) override WARN_UNUSED_RESULT;
118 CheckBool EmitRel32(Label* label) override WARN_UNUSED_RESULT;
119 CheckBool EmitRel32ARM(uint16_t op,
120 Label* label,
121 const uint8_t* arm_op,
122 uint16_t op_size) override WARN_UNUSED_RESULT;
123 CheckBool EmitAbs32(Label* label) override WARN_UNUSED_RESULT;
124 CheckBool EmitAbs64(Label* label) override WARN_UNUSED_RESULT;
125
126 private:
127 size_t size_ = 0;
128
129 DISALLOW_COPY_AND_ASSIGN(InstructionCountReceptor);
130 };
131
132 class InstructionStoreReceptor : public InstructionReceptor {
133 public:
134 explicit InstructionStoreReceptor(AssemblyProgram* program);
135
136 // TODO(huangs): 2016/11: Add Reserve().
137
138 // InstructionReceptor:
139 CheckBool EmitPeRelocs() override WARN_UNUSED_RESULT;
140 CheckBool EmitElfRelocation() override WARN_UNUSED_RESULT;
141 CheckBool EmitElfARMRelocation() override WARN_UNUSED_RESULT;
142 CheckBool EmitOrigin(RVA rva) override WARN_UNUSED_RESULT;
143 CheckBool EmitSingleByte(uint8_t byte) override WARN_UNUSED_RESULT;
144 CheckBool EmitMultipleBytes(const uint8_t* bytes,
145 size_t len) override WARN_UNUSED_RESULT;
146 CheckBool EmitRel32(Label* label) override WARN_UNUSED_RESULT;
147 CheckBool EmitRel32ARM(uint16_t op,
148 Label* label,
149 const uint8_t* arm_op,
150 uint16_t op_size) override WARN_UNUSED_RESULT;
151 CheckBool EmitAbs32(Label* label) override WARN_UNUSED_RESULT;
152 CheckBool EmitAbs64(Label* label) override WARN_UNUSED_RESULT;
153
154 private:
155 AssemblyProgram* program_;
156
157 DISALLOW_COPY_AND_ASSIGN(InstructionStoreReceptor);
158 };
61 159
62 // An AssemblyProgram is the result of disassembling an executable file. 160 // An AssemblyProgram is the result of disassembling an executable file.
63 // 161 //
64 // * The disassembler creates labels in the AssemblyProgram and emits 162 // * The disassembler creates labels in the AssemblyProgram and emits
65 // 'Instructions'. 163 // 'Instructions'.
66 // * The disassembler then calls DefaultAssignIndexes to assign 164 // * The disassembler then calls DefaultAssignIndexes to assign
67 // addresses to positions in the address tables. 165 // addresses to positions in the address tables.
68 // * [Optional step] 166 // * [Optional step]
69 // * At this point the AssemblyProgram can be converted into an 167 // * At this point the AssemblyProgram can be converted into an
70 // EncodedProgram and serialized to an output stream. 168 // EncodedProgram and serialized to an output stream.
71 // * Later, the EncodedProgram can be deserialized and assembled into 169 // * Later, the EncodedProgram can be deserialized and assembled into
72 // the original file. 170 // the original file.
73 // 171 //
74 // The optional step is to modify the AssemblyProgram. One form of modification 172 // The optional step is to modify the AssemblyProgram. One form of modification
75 // is to assign indexes in such a way as to make the EncodedProgram for this 173 // is to assign indexes in such a way as to make the EncodedProgram for this
76 // AssemblyProgram look more like the EncodedProgram for some other 174 // AssemblyProgram look more like the EncodedProgram for some other
77 // AssemblyProgram. The modification process should call UnassignIndexes, do 175 // AssemblyProgram. The modification process should call UnassignIndexes, do
78 // its own assignment, and then call AssignRemainingIndexes to ensure all 176 // its own assignment, and then call AssignRemainingIndexes to ensure all
79 // indexes are assigned. 177 // indexes are assigned.
80 // 178
81 class AssemblyProgram { 179 class AssemblyProgram {
82 public: 180 public:
83 using LabelHandler = base::Callback<void(Label*)>; 181 using LabelHandler = base::Callback<void(Label*)>;
84 using LabelHandlerMap = std::map<OP, LabelHandler>; 182 using LabelHandlerMap = std::map<OP, LabelHandler>;
85 183
86 explicit AssemblyProgram(ExecutableType kind); 184 explicit AssemblyProgram(ExecutableType kind);
87 ~AssemblyProgram(); 185 ~AssemblyProgram();
88 186
89 ExecutableType kind() const { return kind_; } 187 ExecutableType kind() const { return kind_; }
90 188
91 void set_image_base(uint64_t image_base) { image_base_ = image_base; } 189 void set_image_base(uint64_t image_base) { image_base_ = image_base; }
92 190
93 // Instructions will be assembled in the order they are emitted.
94
95 // Generates an entire base relocation table.
96 CheckBool EmitPeRelocsInstruction() WARN_UNUSED_RESULT;
97
98 // Generates an ELF style relocation table for X86.
99 CheckBool EmitElfRelocationInstruction() WARN_UNUSED_RESULT;
100
101 // Generates an ELF style relocation table for ARM.
102 CheckBool EmitElfARMRelocationInstruction() WARN_UNUSED_RESULT;
103
104 // Following instruction will be assembled at address 'rva'.
105 CheckBool EmitOriginInstruction(RVA rva) WARN_UNUSED_RESULT;
106
107 // Generates a single byte of data or machine instruction.
108 CheckBool EmitByteInstruction(uint8_t byte) WARN_UNUSED_RESULT;
109
110 // Generates multiple bytes of data or machine instructions.
111 CheckBool EmitBytesInstruction(const uint8_t* value,
112 size_t len) WARN_UNUSED_RESULT;
113
114 // Generates 4-byte relative reference to address of 'label'.
115 CheckBool EmitRel32(Label* label) WARN_UNUSED_RESULT;
116
117 // Generates 4-byte relative reference to address of 'label' for
118 // ARM.
119 CheckBool EmitRel32ARM(uint16_t op,
120 Label* label,
121 const uint8_t* arm_op,
122 uint16_t op_size) WARN_UNUSED_RESULT;
123
124 // Generates 4-byte absolute reference to address of 'label'.
125 CheckBool EmitAbs32(Label* label) WARN_UNUSED_RESULT;
126
127 // Generates 8-byte absolute reference to address of 'label'.
128 CheckBool EmitAbs64(Label* label) WARN_UNUSED_RESULT;
129
130 // Traverses RVAs in |abs32_visitor| and |rel32_visitor| to precompute Labels. 191 // Traverses RVAs in |abs32_visitor| and |rel32_visitor| to precompute Labels.
131 void PrecomputeLabels(RvaVisitor* abs32_visitor, RvaVisitor* rel32_visitor); 192 void PrecomputeLabels(RvaVisitor* abs32_visitor, RvaVisitor* rel32_visitor);
132 193
133 // Removes underused Labels. Thresholds used (0 = no trimming) is 194 // Removes underused Labels. Thresholds used (0 = no trimming) is
134 // architecture-dependent. 195 // architecture-dependent.
135 void TrimLabels(); 196 void TrimLabels();
136 197
137 void UnassignIndexes(); 198 void UnassignIndexes();
138 void DefaultAssignIndexes(); 199 void DefaultAssignIndexes();
139 void AssignRemainingIndexes(); 200 void AssignRemainingIndexes();
140 201
141 // Looks up abs32 label. Returns null if none found. 202 // Looks up abs32 label. Returns null if none found.
142 Label* FindAbs32Label(RVA rva); 203 Label* FindAbs32Label(RVA rva);
143 204
144 // Looks up rel32 label. Returns null if none found. 205 // Looks up rel32 label. Returns null if none found.
145 Label* FindRel32Label(RVA rva); 206 Label* FindRel32Label(RVA rva);
146 207
147 std::unique_ptr<EncodedProgram> Encode() const; 208 std::unique_ptr<EncodedProgram> Encode() const;
148 209
149 // For each |instruction| in |instructions_|, looks up its opcode from 210 // For each |instruction| in |instructions_|, looks up its opcode from
150 // |handler_map| for a handler. If a handler exists, invoke it by passing the 211 // |handler_map| for a handler. If a handler exists, invoke it by passing the
151 // |instruction|'s label. We assume that |handler_map| has correct keys, i.e., 212 // |instruction|'s label. We assume that |handler_map| has correct keys, i.e.,
152 // opcodes for an instruction that have label. 213 // opcodes for an instruction that have label.
153 void HandleInstructionLabels(const LabelHandlerMap& handler_map) const; 214 void HandleInstructionLabels(const LabelHandlerMap& handler_map) const;
154 215
216 // Returns via |ret| the InstructionCountReceptor instance owned by |this|.
217 // Must only be called once. Returns true on success.
218 CheckBool CreateInstructionCountReceptor(InstructionCountReceptor** ret);
grt (UTC plus 2) 2016/11/07 09:36:17 consumers of these methods don't need to know the
huangs 2016/11/07 19:46:52 Move implementations entirely into .cc file.
219
220 // Returns via |ret| the InstructionStoreReceptor instance owned by |this|.
221 // Must only be called once, and only after CreateInstructionCountReceptor()
222 // has been called. Returns true on success.
223 CheckBool CreateInstructionStoreReceptor(InstructionStoreReceptor** ret);
224
155 private: 225 private:
226 using InstructionVector = NoThrowBuffer<Instruction*>;
227
156 using ScopedInstruction = 228 using ScopedInstruction =
157 std::unique_ptr<Instruction, UncheckedDeleter<Instruction>>; 229 std::unique_ptr<Instruction, UncheckedDeleter<Instruction>>;
158 230
231 friend InstructionStoreReceptor;
232
233 // Instructions will be assembled in the order they are emitted.
234
235 // TODO(huangs): Implement these in InstructionStoreReceptor.
236
237 // Generates an entire base relocation table.
238 CheckBool EmitPeRelocs() WARN_UNUSED_RESULT;
239
240 // Generates an ELF style relocation table for X86.
241 CheckBool EmitElfRelocation() WARN_UNUSED_RESULT;
242
243 // Generates an ELF style relocation table for ARM.
244 CheckBool EmitElfARMRelocation() WARN_UNUSED_RESULT;
245
246 // Following instruction will be assembled at address 'rva'.
247 CheckBool EmitOrigin(RVA rva) WARN_UNUSED_RESULT;
248
249 // Generates a single byte of data or machine instruction.
250 CheckBool EmitSingleByte(uint8_t byte) WARN_UNUSED_RESULT;
251
252 // Generates multiple bytes of data or machine instructions.
253 CheckBool EmitMultipleBytes(const uint8_t* bytes,
254 size_t len) WARN_UNUSED_RESULT;
255
256 // Generates a 4-byte relative reference to address of 'label'.
257 CheckBool EmitRel32(Label* label) WARN_UNUSED_RESULT;
258
259 // Generates a 4-byte relative reference to address of 'label' for ARM.
260 CheckBool EmitRel32ARM(uint16_t op,
261 Label* label,
262 const uint8_t* arm_op,
263 uint16_t op_size) WARN_UNUSED_RESULT;
264
265 // Generates a 4-byte absolute reference to address of 'label'.
266 CheckBool EmitAbs32(Label* label) WARN_UNUSED_RESULT;
267
268 // Generates an 8-byte absolute reference to address of 'label'.
269 CheckBool EmitAbs64(Label* label) WARN_UNUSED_RESULT;
270
159 ExecutableType kind_; 271 ExecutableType kind_;
160 272
161 CheckBool Emit(ScopedInstruction instruction) WARN_UNUSED_RESULT; 273 CheckBool Emit(ScopedInstruction instruction) WARN_UNUSED_RESULT;
162 CheckBool EmitShared(Instruction* instruction) WARN_UNUSED_RESULT; 274 CheckBool EmitShared(Instruction* instruction) WARN_UNUSED_RESULT;
163 275
164 static const int kLabelLowerLimit; 276 static const int kLabelLowerLimit;
165 277
166 // Looks up a label or creates a new one. Might return NULL. 278 // Looks up a label or creates a new one. Might return NULL.
167 Label* FindLabel(RVA rva, RVAToLabel* labels); 279 Label* FindLabel(RVA rva, RVAToLabel* labels);
168 280
169 // Helper methods for the public versions. 281 // Helper methods for the public versions.
170 static void UnassignIndexes(RVAToLabel* labels); 282 static void UnassignIndexes(RVAToLabel* labels);
171 static void DefaultAssignIndexes(RVAToLabel* labels); 283 static void DefaultAssignIndexes(RVAToLabel* labels);
172 static void AssignRemainingIndexes(RVAToLabel* labels); 284 static void AssignRemainingIndexes(RVAToLabel* labels);
173 285
174 // Sharing instructions that emit a single byte saves a lot of space. 286 // Sharing instructions that emit a single byte saves a lot of space.
175 Instruction* GetByteInstruction(uint8_t byte); 287 Instruction* GetByteInstruction(uint8_t byte);
176 std::unique_ptr<Instruction* [], base::FreeDeleter> byte_instruction_cache_; 288 std::unique_ptr<Instruction* [], base::FreeDeleter> byte_instruction_cache_;
177 289
178 uint64_t image_base_; // Desired or mandated base address of image. 290 uint64_t image_base_; // Desired or mandated base address of image.
179 291
180 InstructionVector instructions_; // All the instructions in program. 292 InstructionVector instructions_; // All the instructions in program.
181 293
182 // Storage and lookup of Labels associated with target addresses. We use 294 // Storage and lookup of Labels associated with target addresses. We use
183 // separate abs32 and rel32 labels. 295 // separate abs32 and rel32 labels.
184 LabelManager abs32_label_manager_; 296 LabelManager abs32_label_manager_;
185 LabelManager rel32_label_manager_; 297 LabelManager rel32_label_manager_;
186 298
299 std::unique_ptr<InstructionCountReceptor> count_receptor_;
300 std::unique_ptr<InstructionStoreReceptor> store_receptor_;
301
187 DISALLOW_COPY_AND_ASSIGN(AssemblyProgram); 302 DISALLOW_COPY_AND_ASSIGN(AssemblyProgram);
188 }; 303 };
189 304
190 // Converts |program| into encoded form, returning it as |*output|. 305 // Converts |program| into encoded form, returning it as |*output|.
191 // Returns C_OK if succeeded, otherwise returns an error status and sets 306 // Returns C_OK if succeeded, otherwise returns an error status and sets
192 // |*output| to null. 307 // |*output| to null.
193 Status Encode(const AssemblyProgram& program, 308 Status Encode(const AssemblyProgram& program,
194 std::unique_ptr<EncodedProgram>* output); 309 std::unique_ptr<EncodedProgram>* output);
195 310
196 } // namespace courgette 311 } // namespace courgette
197 312
198 #endif // COURGETTE_ASSEMBLY_PROGRAM_H_ 313 #endif // COURGETTE_ASSEMBLY_PROGRAM_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698