OLD | NEW |
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 Loading... |
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 |
OLD | NEW |