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

Side by Side Diff: courgette/assembly_program.cc

Issue 2854113002: [Courgette] Reduce AssemblyProgram to reduce Courgette-apply RAM floor and disk churn. (Closed)
Patch Set: Update courgette_fuzzer in libfuzzer. Created 3 years, 7 months 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
« no previous file with comments | « courgette/assembly_program.h ('k') | courgette/courgette_flow.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include <stddef.h>
6
5 #include "courgette/assembly_program.h" 7 #include "courgette/assembly_program.h"
6 8
7 #include "base/callback.h"
8 #include "base/logging.h" 9 #include "base/logging.h"
9 #include "courgette/courgette.h"
10 #include "courgette/disassembler.h"
11 #include "courgette/encoded_program.h" 10 #include "courgette/encoded_program.h"
11 #include "courgette/instruction_utils.h"
12 12
13 namespace courgette { 13 namespace courgette {
14 14
15 namespace { 15 namespace {
16 16
17 // Sets the current address for the emitting instructions. 17 // An instruction receptor that adds each received abs32/rel32 Label* to the
18 class OriginInstruction : public Instruction { 18 // matching VECTOR member variable. Template VECTOR allows code reuse for
19 // counting (CountingVector) and storage (std::vector).
20 template <template <typename T, typename... Args> class CONTAINER>
21 class LabelReceptor : public InstructionReceptor {
19 public: 22 public:
20 explicit OriginInstruction(RVA rva) : Instruction(ORIGIN, 0), rva_(rva) {} 23 using VECTOR = CONTAINER<Label*>;
21 RVA origin_rva() const { return rva_; }
22 private:
23 RVA rva_;
24 };
25 24
26 // Emits an entire PE base relocation table. 25 LabelReceptor() = default;
27 class PeRelocsInstruction : public Instruction { 26 ~LabelReceptor() override = default;
28 public:
29 PeRelocsInstruction() : Instruction(MAKEPERELOCS) {}
30 };
31 27
32 // Emits an ELF relocation table. 28 VECTOR* mutable_abs32_vector() { return &abs32_vector_; }
33 class ElfRelocsInstruction : public Instruction { 29 VECTOR* mutable_rel32_vector() { return &rel32_vector_; }
34 public:
35 ElfRelocsInstruction() : Instruction(MAKEELFRELOCS) {}
36 };
37
38 // Emits an ELF ARM relocation table.
39 class ElfARMRelocsInstruction : public Instruction {
40 public:
41 ElfARMRelocsInstruction() : Instruction(MAKEELFARMRELOCS) {}
42 };
43
44 // Emits a single byte.
45 class ByteInstruction : public Instruction {
46 public:
47 explicit ByteInstruction(uint8_t value) : Instruction(DEFBYTE, value) {}
48 uint8_t byte_value() const { return info_; }
49 };
50
51 // Emits a single byte.
52 class BytesInstruction : public Instruction {
53 public:
54 BytesInstruction(const uint8_t* values, size_t len)
55 : Instruction(DEFBYTES, 0), values_(values), len_(len) {}
56 const uint8_t* byte_values() const { return values_; }
57 size_t len() const { return len_; }
58
59 private:
60 const uint8_t* values_;
61 size_t len_;
62 };
63
64 // A ABS32 to REL32 instruction emits a reference to a label's address.
65 class InstructionWithLabel : public Instruction {
66 public:
67 InstructionWithLabel(OP op, Label* label)
68 : Instruction(op, 0), label_(label) {
69 if (label == NULL) NOTREACHED();
70 }
71 Label* label() const { return label_; }
72 protected:
73 Label* label_;
74 };
75
76 // An ARM REL32 instruction emits a reference to a label's address and
77 // a specially-compressed ARM op.
78 class InstructionWithLabelARM : public InstructionWithLabel {
79 public:
80 InstructionWithLabelARM(OP op,
81 uint16_t compressed_op,
82 Label* label,
83 const uint8_t* arm_op,
84 uint16_t op_size)
85 : InstructionWithLabel(op, label),
86 compressed_op_(compressed_op),
87 arm_op_(arm_op),
88 op_size_(op_size) {
89 if (label == NULL) NOTREACHED();
90 }
91 uint16_t compressed_op() const { return compressed_op_; }
92 const uint8_t* arm_op() const { return arm_op_; }
93 uint16_t op_size() const { return op_size_; }
94
95 private:
96 uint16_t compressed_op_;
97 const uint8_t* arm_op_;
98 uint16_t op_size_;
99 };
100
101 /******** InstructionCountReceptor ********/
102
103 // An InstructionReceptor that counts space occupied by emitted instructions.
104 class InstructionCountReceptor : public InstructionReceptor {
105 public:
106 InstructionCountReceptor() = default;
107
108 size_t abs_count() const { return abs_count_; }
109 size_t rel_count() const { return rel_count_; }
110 30
111 // InstructionReceptor: 31 // InstructionReceptor:
112 CheckBool EmitPeRelocs() override { return true; } 32 CheckBool EmitPeRelocs() override { return true; }
113 CheckBool EmitElfRelocation() override { return true; } 33 CheckBool EmitElfRelocation() override { return true; }
114 CheckBool EmitElfARMRelocation() override { return true; } 34 CheckBool EmitElfARMRelocation() override { return true; }
115 CheckBool EmitOrigin(RVA rva) override { return true; } 35 CheckBool EmitOrigin(RVA rva) override { return true; }
116 CheckBool EmitSingleByte(uint8_t byte) override { return true; } 36 CheckBool EmitSingleByte(uint8_t byte) override { return true; }
117 CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) override { 37 CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) override {
118 return true; 38 return true;
119 } 39 }
120 CheckBool EmitRel32(Label* label) override { 40 CheckBool EmitRel32(Label* label) override {
121 ++rel_count_; 41 rel32_vector_.push_back(label);
122 return true; 42 return true;
123 } 43 }
124 CheckBool EmitRel32ARM(uint16_t op, 44 CheckBool EmitRel32ARM(uint16_t op,
125 Label* label, 45 Label* label,
126 const uint8_t* arm_op, 46 const uint8_t* arm_op,
127 uint16_t op_size) override { 47 uint16_t op_size) override {
128 ++rel_count_; 48 rel32_vector_.push_back(label);
129 return true; 49 return true;
130 } 50 }
131 CheckBool EmitAbs32(Label* label) override { 51 CheckBool EmitAbs32(Label* label) override {
132 ++abs_count_; 52 abs32_vector_.push_back(label);
133 return true; 53 return true;
134 } 54 }
135 CheckBool EmitAbs64(Label* label) override { 55 CheckBool EmitAbs64(Label* label) override {
136 ++abs_count_; 56 abs32_vector_.push_back(label);
137 return true; 57 return true;
138 } 58 }
139 59
140 private: 60 private:
141 size_t abs_count_ = 0; 61 VECTOR abs32_vector_;
142 size_t rel_count_ = 0; 62 VECTOR rel32_vector_;
143 63
144 DISALLOW_COPY_AND_ASSIGN(InstructionCountReceptor); 64 DISALLOW_COPY_AND_ASSIGN(LabelReceptor);
145 };
146
147 /******** InstructionStoreReceptor ********/
148
149 // An InstructionReceptor that stores emitted instructions.
150 class InstructionStoreReceptor : public InstructionReceptor {
151 public:
152 InstructionStoreReceptor(AssemblyProgram* program, bool annotate_labels)
153 : program_(program), annotate_labels_(annotate_labels) {
154 CHECK(program_);
155 }
156
157 // TODO(huangs): 2017/04: Add Reserve().
158
159 // InstructionReceptor:
160 // TODO(huangs): 2017/04: Move implementations here.
161 CheckBool EmitPeRelocs() override { return program_->EmitPeRelocs(); }
162 CheckBool EmitElfRelocation() override {
163 return program_->EmitElfRelocation();
164 }
165 CheckBool EmitElfARMRelocation() override {
166 return program_->EmitElfARMRelocation();
167 }
168 CheckBool EmitOrigin(RVA rva) override { return program_->EmitOrigin(rva); }
169 CheckBool EmitSingleByte(uint8_t byte) override {
170 return program_->EmitSingleByte(byte);
171 }
172 CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) override {
173 return program_->EmitMultipleBytes(bytes, len);
174 }
175 CheckBool EmitRel32(Label* label) override {
176 if (annotate_labels_)
177 program_->mutable_rel32_label_annotations()->push_back(label);
178 return program_->EmitRel32(label);
179 }
180 CheckBool EmitRel32ARM(uint16_t op,
181 Label* label,
182 const uint8_t* arm_op,
183 uint16_t op_size) override {
184 if (annotate_labels_)
185 program_->mutable_rel32_label_annotations()->push_back(label);
186 return program_->EmitRel32ARM(op, label, arm_op, op_size);
187 }
188 CheckBool EmitAbs32(Label* label) override {
189 if (annotate_labels_)
190 program_->mutable_abs32_label_annotations()->push_back(label);
191 return program_->EmitAbs32(label);
192 }
193 CheckBool EmitAbs64(Label* label) override {
194 if (annotate_labels_)
195 program_->mutable_abs32_label_annotations()->push_back(label);
196 return program_->EmitAbs64(label);
197 }
198
199 private:
200 AssemblyProgram* program_;
201 const bool annotate_labels_;
202
203 DISALLOW_COPY_AND_ASSIGN(InstructionStoreReceptor);
204 }; 65 };
205 66
206 } // namespace 67 } // namespace
207 68
208 /******** AssemblyProgram ********/
209
210 AssemblyProgram::AssemblyProgram(ExecutableType kind, uint64_t image_base) 69 AssemblyProgram::AssemblyProgram(ExecutableType kind, uint64_t image_base)
211 : kind_(kind), image_base_(image_base) {} 70 : kind_(kind), image_base_(image_base) {}
212 71
213 AssemblyProgram::~AssemblyProgram() { 72 AssemblyProgram::~AssemblyProgram() = default;
214 for (size_t i = 0; i < instructions_.size(); ++i) {
215 Instruction* instruction = instructions_[i];
216 if (instruction->op() != DEFBYTE) // Owned by byte_instruction_cache_.
217 UncheckedDelete(instruction);
218 }
219 if (byte_instruction_cache_.get()) {
220 for (size_t i = 0; i < 256; ++i)
221 UncheckedDelete(byte_instruction_cache_[i]);
222 }
223 }
224
225 CheckBool AssemblyProgram::EmitPeRelocs() {
226 return Emit(ScopedInstruction(UncheckedNew<PeRelocsInstruction>()));
227 }
228
229 CheckBool AssemblyProgram::EmitElfRelocation() {
230 return Emit(ScopedInstruction(UncheckedNew<ElfRelocsInstruction>()));
231 }
232
233 CheckBool AssemblyProgram::EmitElfARMRelocation() {
234 return Emit(ScopedInstruction(UncheckedNew<ElfARMRelocsInstruction>()));
235 }
236
237 CheckBool AssemblyProgram::EmitOrigin(RVA rva) {
238 return Emit(ScopedInstruction(UncheckedNew<OriginInstruction>(rva)));
239 }
240
241 CheckBool AssemblyProgram::EmitSingleByte(uint8_t byte) {
242 return EmitShared(GetByteInstruction(byte));
243 }
244
245 CheckBool AssemblyProgram::EmitMultipleBytes(const uint8_t* bytes, size_t len) {
246 return Emit(ScopedInstruction(UncheckedNew<BytesInstruction>(bytes, len)));
247 }
248
249 CheckBool AssemblyProgram::EmitRel32(Label* label) {
250 return Emit(
251 ScopedInstruction(UncheckedNew<InstructionWithLabel>(REL32, label)));
252 }
253
254 CheckBool AssemblyProgram::EmitRel32ARM(uint16_t op,
255 Label* label,
256 const uint8_t* arm_op,
257 uint16_t op_size) {
258 return Emit(ScopedInstruction(UncheckedNew<InstructionWithLabelARM>(
259 REL32ARM, op, label, arm_op, op_size)));
260 }
261
262 CheckBool AssemblyProgram::EmitAbs32(Label* label) {
263 return Emit(
264 ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS32, label)));
265 }
266
267 CheckBool AssemblyProgram::EmitAbs64(Label* label) {
268 return Emit(
269 ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS64, label)));
270 }
271 73
272 void AssemblyProgram::PrecomputeLabels(RvaVisitor* abs32_visitor, 74 void AssemblyProgram::PrecomputeLabels(RvaVisitor* abs32_visitor,
273 RvaVisitor* rel32_visitor) { 75 RvaVisitor* rel32_visitor) {
274 abs32_label_manager_.Read(abs32_visitor); 76 abs32_label_manager_.Read(abs32_visitor);
275 rel32_label_manager_.Read(rel32_visitor); 77 rel32_label_manager_.Read(rel32_visitor);
276 TrimLabels(); 78 TrimLabels();
277 } 79 }
278 80
279 // Chosen empirically to give the best reduction in payload size for 81 // Chosen empirically to give the best reduction in payload size for
280 // an update from daisy_3701.98.0 to daisy_4206.0.0. 82 // an update from daisy_3701.98.0 to daisy_4206.0.0.
(...skipping 27 matching lines...) Expand all
308 } 110 }
309 111
310 Label* AssemblyProgram::FindAbs32Label(RVA rva) { 112 Label* AssemblyProgram::FindAbs32Label(RVA rva) {
311 return abs32_label_manager_.Find(rva); 113 return abs32_label_manager_.Find(rva);
312 } 114 }
313 115
314 Label* AssemblyProgram::FindRel32Label(RVA rva) { 116 Label* AssemblyProgram::FindRel32Label(RVA rva) {
315 return rel32_label_manager_.Find(rva); 117 return rel32_label_manager_.Find(rva);
316 } 118 }
317 119
318 CheckBool AssemblyProgram::GenerateInstructions(const InstructionGenerator& gen, 120 CheckBool AssemblyProgram::AnnotateLabels(const InstructionGenerator& gen) {
319 bool annotate_labels) { 121 // Pass 1: Compute required space.
320 // Pass 1: Count storage space required and reserve in advance. 122 LabelReceptor<CountingVector> count_receptor;
321 InstructionCountReceptor count_receptor;
322 if (!gen.Run(&count_receptor)) 123 if (!gen.Run(&count_receptor))
323 return false; 124 return false;
324 125
325 if (annotate_labels) { 126 // Pass 2: Reserve and store annotations.
326 DCHECK(abs32_label_annotations_.empty()); 127 LabelReceptor<std::vector> annotate_receptor;
327 abs32_label_annotations_.reserve(count_receptor.abs_count()); 128 annotate_receptor.mutable_abs32_vector()->reserve(
328 DCHECK(rel32_label_annotations_.empty()); 129 count_receptor.mutable_abs32_vector()->size());
329 rel32_label_annotations_.reserve(count_receptor.rel_count()); 130 annotate_receptor.mutable_rel32_vector()->reserve(
330 } 131 count_receptor.mutable_rel32_vector()->size());
132 if (!gen.Run(&annotate_receptor))
133 return false;
331 134
332 // Pass 2: Emit all instructions to reserved buffer (uses Phase 1 count). 135 // Move results to |abs32_label_annotations_| and |re32_label_annotations_|.
333 // Populates |abs32_label_annotations_| and |re32_label_annotations_| if 136 abs32_label_annotations_.swap(*annotate_receptor.mutable_abs32_vector());
334 // |annotate_labels| is true. 137 rel32_label_annotations_.swap(*annotate_receptor.mutable_rel32_vector());
335 InstructionStoreReceptor store_receptor(this, annotate_labels);
336 return gen.Run(&store_receptor);
337 }
338
339 CheckBool AssemblyProgram::Emit(ScopedInstruction instruction) {
340 if (!instruction || !instructions_.push_back(instruction.get()))
341 return false;
342 // Ownership successfully passed to instructions_.
343 ignore_result(instruction.release());
344 return true; 138 return true;
345 } 139 }
346 140
347 CheckBool AssemblyProgram::EmitShared(Instruction* instruction) { 141 bool AssemblyProgram::PrepareEncodedProgram(EncodedProgram* encoded) const {
348 DCHECK(!instruction || instruction->op() == DEFBYTE);
349 return instruction && instructions_.push_back(instruction);
350 }
351
352 std::unique_ptr<EncodedProgram> AssemblyProgram::Encode() const {
353 std::unique_ptr<EncodedProgram> encoded(new EncodedProgram());
354
355 encoded->set_image_base(image_base_); 142 encoded->set_image_base(image_base_);
356 143 return encoded->ImportLabels(abs32_label_manager_, rel32_label_manager_);
357 if (!encoded->ImportLabels(abs32_label_manager_, rel32_label_manager_))
358 return nullptr;
359
360 for (size_t i = 0; i < instructions_.size(); ++i) {
361 Instruction* instruction = instructions_[i];
362
363 switch (instruction->op()) {
364 case ORIGIN: {
365 OriginInstruction* org = static_cast<OriginInstruction*>(instruction);
366 if (!encoded->AddOrigin(org->origin_rva()))
367 return nullptr;
368 break;
369 }
370 case DEFBYTE: {
371 uint8_t b = static_cast<ByteInstruction*>(instruction)->byte_value();
372 if (!encoded->AddCopy(1, &b))
373 return nullptr;
374 break;
375 }
376 case DEFBYTES: {
377 const uint8_t* byte_values =
378 static_cast<BytesInstruction*>(instruction)->byte_values();
379 size_t len = static_cast<BytesInstruction*>(instruction)->len();
380
381 if (!encoded->AddCopy(len, byte_values))
382 return nullptr;
383 break;
384 }
385 case REL32: {
386 Label* label = static_cast<InstructionWithLabel*>(instruction)->label();
387 if (!encoded->AddRel32(label->index_))
388 return nullptr;
389 break;
390 }
391 case REL32ARM: {
392 Label* label =
393 static_cast<InstructionWithLabelARM*>(instruction)->label();
394 uint16_t compressed_op =
395 static_cast<InstructionWithLabelARM*>(instruction)->compressed_op();
396 if (!encoded->AddRel32ARM(compressed_op, label->index_))
397 return nullptr;
398 break;
399 }
400 case ABS32: {
401 Label* label = static_cast<InstructionWithLabel*>(instruction)->label();
402 if (!encoded->AddAbs32(label->index_))
403 return nullptr;
404 break;
405 }
406 case ABS64: {
407 Label* label = static_cast<InstructionWithLabel*>(instruction)->label();
408 if (!encoded->AddAbs64(label->index_))
409 return nullptr;
410 break;
411 }
412 case MAKEPERELOCS: {
413 if (!encoded->AddPeMakeRelocs(kind_))
414 return nullptr;
415 break;
416 }
417 case MAKEELFRELOCS: {
418 if (!encoded->AddElfMakeRelocs())
419 return nullptr;
420 break;
421 }
422 case MAKEELFARMRELOCS: {
423 if (!encoded->AddElfARMMakeRelocs())
424 return nullptr;
425 break;
426 }
427 default: {
428 NOTREACHED() << "Unknown Insn OP kind";
429 }
430 }
431 }
432
433 return encoded;
434 }
435
436 Instruction* AssemblyProgram::GetByteInstruction(uint8_t byte) {
437 if (!byte_instruction_cache_) {
438 Instruction** ram = nullptr;
439 if (!base::UncheckedMalloc(sizeof(Instruction*) * 256,
440 reinterpret_cast<void**>(&ram))) {
441 return nullptr;
442 }
443 byte_instruction_cache_.reset(ram);
444
445 for (int i = 0; i < 256; ++i) {
446 byte_instruction_cache_[i] =
447 UncheckedNew<ByteInstruction>(static_cast<uint8_t>(i));
448 if (!byte_instruction_cache_[i]) {
449 for (int j = 0; j < i; ++j)
450 UncheckedDelete(byte_instruction_cache_[j]);
451 byte_instruction_cache_.reset();
452 return nullptr;
453 }
454 }
455 }
456
457 return byte_instruction_cache_[byte];
458 }
459
460 ////////////////////////////////////////////////////////////////////////////////
461
462 Status Encode(const AssemblyProgram& program,
463 std::unique_ptr<EncodedProgram>* output) {
464 // Explicitly release any memory associated with the output before encoding.
465 output->reset();
466
467 *output = program.Encode();
468 return (*output) ? C_OK : C_GENERAL_ERROR;
469 } 144 }
470 145
471 } // namespace courgette 146 } // namespace courgette
OLDNEW
« no previous file with comments | « courgette/assembly_program.h ('k') | courgette/courgette_flow.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698