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 "courgette/assembly_program.h" | 5 #include "courgette/assembly_program.h" |
6 | 6 |
7 #include <memory.h> | 7 #include <memory.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 const uint8_t* arm_op_; | 104 const uint8_t* arm_op_; |
105 uint16_t op_size_; | 105 uint16_t op_size_; |
106 }; | 106 }; |
107 | 107 |
108 } // namespace | 108 } // namespace |
109 | 109 |
110 AssemblyProgram::AssemblyProgram(ExecutableType kind) | 110 AssemblyProgram::AssemblyProgram(ExecutableType kind) |
111 : kind_(kind), image_base_(0) { | 111 : kind_(kind), image_base_(0) { |
112 } | 112 } |
113 | 113 |
114 static void DeleteContainedLabels(const RVAToLabel& labels) { | |
115 for (RVAToLabel::const_iterator p = labels.begin(); p != labels.end(); ++p) | |
116 UncheckedDelete(p->second); | |
117 } | |
118 | |
119 AssemblyProgram::~AssemblyProgram() { | 114 AssemblyProgram::~AssemblyProgram() { |
120 for (size_t i = 0; i < instructions_.size(); ++i) { | 115 for (size_t i = 0; i < instructions_.size(); ++i) { |
121 Instruction* instruction = instructions_[i]; | 116 Instruction* instruction = instructions_[i]; |
122 if (instruction->op() != DEFBYTE) // Owned by byte_instruction_cache_. | 117 if (instruction->op() != DEFBYTE) // Owned by byte_instruction_cache_. |
123 UncheckedDelete(instruction); | 118 UncheckedDelete(instruction); |
124 } | 119 } |
125 if (byte_instruction_cache_.get()) { | 120 if (byte_instruction_cache_.get()) { |
126 for (size_t i = 0; i < 256; ++i) | 121 for (size_t i = 0; i < 256; ++i) |
127 UncheckedDelete(byte_instruction_cache_[i]); | 122 UncheckedDelete(byte_instruction_cache_[i]); |
128 } | 123 } |
129 DeleteContainedLabels(rel32_labels_); | |
130 DeleteContainedLabels(abs32_labels_); | |
131 } | 124 } |
132 | 125 |
133 CheckBool AssemblyProgram::EmitPeRelocsInstruction() { | 126 CheckBool AssemblyProgram::EmitPeRelocsInstruction() { |
134 return Emit(ScopedInstruction(UncheckedNew<PeRelocsInstruction>())); | 127 return Emit(ScopedInstruction(UncheckedNew<PeRelocsInstruction>())); |
135 } | 128 } |
136 | 129 |
137 CheckBool AssemblyProgram::EmitElfRelocationInstruction() { | 130 CheckBool AssemblyProgram::EmitElfRelocationInstruction() { |
138 return Emit(ScopedInstruction(UncheckedNew<ElfRelocsInstruction>())); | 131 return Emit(ScopedInstruction(UncheckedNew<ElfRelocsInstruction>())); |
139 } | 132 } |
140 | 133 |
(...skipping 30 matching lines...) Expand all Loading... |
171 CheckBool AssemblyProgram::EmitAbs32(Label* label) { | 164 CheckBool AssemblyProgram::EmitAbs32(Label* label) { |
172 return Emit( | 165 return Emit( |
173 ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS32, label))); | 166 ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS32, label))); |
174 } | 167 } |
175 | 168 |
176 CheckBool AssemblyProgram::EmitAbs64(Label* label) { | 169 CheckBool AssemblyProgram::EmitAbs64(Label* label) { |
177 return Emit( | 170 return Emit( |
178 ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS64, label))); | 171 ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS64, label))); |
179 } | 172 } |
180 | 173 |
181 Label* AssemblyProgram::FindOrMakeAbs32Label(RVA rva) { | 174 void AssemblyProgram::PrecomputeLabels(RvaVisitor* abs32_visitor, |
182 return FindLabel(rva, &abs32_labels_); | 175 RvaVisitor* rel32_visitor) { |
| 176 abs32_label_manager_.Read(abs32_visitor); |
| 177 rel32_label_manager_.Read(rel32_visitor); |
| 178 TrimLabels(); |
183 } | 179 } |
184 | 180 |
185 Label* AssemblyProgram::FindOrMakeRel32Label(RVA rva) { | 181 // Chosen empirically to give the best reduction in payload size for |
186 return FindLabel(rva, &rel32_labels_); | 182 // an update from daisy_3701.98.0 to daisy_4206.0.0. |
| 183 const int AssemblyProgram::kLabelLowerLimit = 5; |
| 184 |
| 185 void AssemblyProgram::TrimLabels() { |
| 186 // For now only trim for ARM binaries. |
| 187 if (kind() != EXE_ELF_32_ARM) |
| 188 return; |
| 189 |
| 190 int lower_limit = kLabelLowerLimit; |
| 191 |
| 192 VLOG(1) << "TrimLabels: threshold " << lower_limit; |
| 193 |
| 194 rel32_label_manager_.RemoveUnderusedLabels(lower_limit); |
| 195 } |
| 196 |
| 197 void AssemblyProgram::UnassignIndexes() { |
| 198 abs32_label_manager_.UnassignIndexes(); |
| 199 rel32_label_manager_.UnassignIndexes(); |
187 } | 200 } |
188 | 201 |
189 void AssemblyProgram::DefaultAssignIndexes() { | 202 void AssemblyProgram::DefaultAssignIndexes() { |
190 DefaultAssignIndexes(&abs32_labels_); | 203 abs32_label_manager_.DefaultAssignIndexes(); |
191 DefaultAssignIndexes(&rel32_labels_); | 204 rel32_label_manager_.DefaultAssignIndexes(); |
192 } | |
193 | |
194 void AssemblyProgram::UnassignIndexes() { | |
195 UnassignIndexes(&abs32_labels_); | |
196 UnassignIndexes(&rel32_labels_); | |
197 } | 205 } |
198 | 206 |
199 void AssemblyProgram::AssignRemainingIndexes() { | 207 void AssemblyProgram::AssignRemainingIndexes() { |
200 AssignRemainingIndexes(&abs32_labels_); | 208 abs32_label_manager_.AssignRemainingIndexes(); |
201 AssignRemainingIndexes(&rel32_labels_); | 209 rel32_label_manager_.AssignRemainingIndexes(); |
| 210 } |
| 211 |
| 212 Label* AssemblyProgram::FindAbs32Label(RVA rva) { |
| 213 return abs32_label_manager_.Find(rva); |
| 214 } |
| 215 |
| 216 Label* AssemblyProgram::FindRel32Label(RVA rva) { |
| 217 return rel32_label_manager_.Find(rva); |
202 } | 218 } |
203 | 219 |
204 Label* AssemblyProgram::InstructionAbs32Label( | 220 Label* AssemblyProgram::InstructionAbs32Label( |
205 const Instruction* instruction) const { | 221 const Instruction* instruction) const { |
206 if (instruction->op() == ABS32) | 222 if (instruction->op() == ABS32) |
207 return static_cast<const InstructionWithLabel*>(instruction)->label(); | 223 return static_cast<const InstructionWithLabel*>(instruction)->label(); |
208 return NULL; | 224 return NULL; |
209 } | 225 } |
210 | 226 |
211 Label* AssemblyProgram::InstructionAbs64Label( | 227 Label* AssemblyProgram::InstructionAbs64Label( |
(...skipping 19 matching lines...) Expand all Loading... |
231 // Ownership successfully passed to instructions_. | 247 // Ownership successfully passed to instructions_. |
232 ignore_result(instruction.release()); | 248 ignore_result(instruction.release()); |
233 return true; | 249 return true; |
234 } | 250 } |
235 | 251 |
236 CheckBool AssemblyProgram::EmitShared(Instruction* instruction) { | 252 CheckBool AssemblyProgram::EmitShared(Instruction* instruction) { |
237 DCHECK(!instruction || instruction->op() == DEFBYTE); | 253 DCHECK(!instruction || instruction->op() == DEFBYTE); |
238 return instruction && instructions_.push_back(instruction); | 254 return instruction && instructions_.push_back(instruction); |
239 } | 255 } |
240 | 256 |
241 Label* AssemblyProgram::FindLabel(RVA rva, RVAToLabel* labels) { | |
242 Label*& slot = (*labels)[rva]; | |
243 if (slot == NULL) { | |
244 slot = UncheckedNew<Label>(rva); | |
245 if (slot == NULL) | |
246 return NULL; | |
247 } | |
248 slot->count_++; | |
249 return slot; | |
250 } | |
251 | |
252 void AssemblyProgram::UnassignIndexes(RVAToLabel* labels) { | 257 void AssemblyProgram::UnassignIndexes(RVAToLabel* labels) { |
253 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) { | 258 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) { |
254 Label* current = p->second; | 259 Label* current = p->second; |
255 current->index_ = Label::kNoIndex; | 260 current->index_ = Label::kNoIndex; |
256 } | 261 } |
257 } | 262 } |
258 | 263 |
259 // DefaultAssignIndexes takes a set of labels and assigns indexes in increasing | 264 // DefaultAssignIndexes takes a set of labels and assigns indexes in increasing |
260 // address order. | 265 // address order. |
261 // | 266 // |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 VLOG(1) << " fill forward " << fill_forward_count | 365 VLOG(1) << " fill forward " << fill_forward_count |
361 << " backward " << fill_backward_count | 366 << " backward " << fill_backward_count |
362 << " infill " << fill_infill_count; | 367 << " infill " << fill_infill_count; |
363 } | 368 } |
364 | 369 |
365 std::unique_ptr<EncodedProgram> AssemblyProgram::Encode() const { | 370 std::unique_ptr<EncodedProgram> AssemblyProgram::Encode() const { |
366 std::unique_ptr<EncodedProgram> encoded(new EncodedProgram()); | 371 std::unique_ptr<EncodedProgram> encoded(new EncodedProgram()); |
367 | 372 |
368 encoded->set_image_base(image_base_); | 373 encoded->set_image_base(image_base_); |
369 | 374 |
370 if (!encoded->DefineLabels(abs32_labels_, rel32_labels_)) | 375 if (!encoded->ImportLabels(abs32_label_manager_, rel32_label_manager_)) |
371 return nullptr; | 376 return nullptr; |
372 | 377 |
373 for (size_t i = 0; i < instructions_.size(); ++i) { | 378 for (size_t i = 0; i < instructions_.size(); ++i) { |
374 Instruction* instruction = instructions_[i]; | 379 Instruction* instruction = instructions_[i]; |
375 | 380 |
376 switch (instruction->op()) { | 381 switch (instruction->op()) { |
377 case ORIGIN: { | 382 case ORIGIN: { |
378 OriginInstruction* org = static_cast<OriginInstruction*>(instruction); | 383 OriginInstruction* org = static_cast<OriginInstruction*>(instruction); |
379 if (!encoded->AddOrigin(org->origin_rva())) | 384 if (!encoded->AddOrigin(org->origin_rva())) |
380 return nullptr; | 385 return nullptr; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 UncheckedDelete(byte_instruction_cache_[j]); | 468 UncheckedDelete(byte_instruction_cache_[j]); |
464 byte_instruction_cache_.reset(); | 469 byte_instruction_cache_.reset(); |
465 return nullptr; | 470 return nullptr; |
466 } | 471 } |
467 } | 472 } |
468 } | 473 } |
469 | 474 |
470 return byte_instruction_cache_[byte]; | 475 return byte_instruction_cache_[byte]; |
471 } | 476 } |
472 | 477 |
473 // Chosen empirically to give the best reduction in payload size for | |
474 // an update from daisy_3701.98.0 to daisy_4206.0.0. | |
475 const int AssemblyProgram::kLabelLowerLimit = 5; | |
476 | |
477 CheckBool AssemblyProgram::TrimLabels() { | |
478 // For now only trim for ARM binaries. | |
479 if (kind() != EXE_ELF_32_ARM) | |
480 return true; | |
481 | |
482 int lower_limit = kLabelLowerLimit; | |
483 | |
484 VLOG(1) << "TrimLabels: threshold " << lower_limit; | |
485 | |
486 // Walk through the list of instructions, replacing trimmed labels | |
487 // with the original machine instruction. | |
488 for (size_t i = 0; i < instructions_.size(); ++i) { | |
489 Instruction* instruction = instructions_[i]; | |
490 switch (instruction->op()) { | |
491 case REL32ARM: { | |
492 Label* label = | |
493 static_cast<InstructionWithLabelARM*>(instruction)->label(); | |
494 if (label->count_ <= lower_limit) { | |
495 const uint8_t* arm_op = | |
496 static_cast<InstructionWithLabelARM*>(instruction)->arm_op(); | |
497 uint16_t op_size = | |
498 static_cast<InstructionWithLabelARM*>(instruction)->op_size(); | |
499 | |
500 if (op_size < 1) | |
501 return false; | |
502 UncheckedDelete(instruction); | |
503 instructions_[i] = UncheckedNew<BytesInstruction>(arm_op, op_size); | |
504 if (!instructions_[i]) | |
505 return false; | |
506 } | |
507 break; | |
508 } | |
509 default: | |
510 break; | |
511 } | |
512 } | |
513 | |
514 // Remove and deallocate underused Labels. | |
515 RVAToLabel::iterator it = rel32_labels_.begin(); | |
516 while (it != rel32_labels_.end()) { | |
517 if (it->second->count_ <= lower_limit) { | |
518 UncheckedDelete(it->second); | |
519 rel32_labels_.erase(it++); | |
520 } else { | |
521 ++it; | |
522 } | |
523 } | |
524 | |
525 return true; | |
526 } | |
527 | |
528 //////////////////////////////////////////////////////////////////////////////// | 478 //////////////////////////////////////////////////////////////////////////////// |
529 | 479 |
530 Status Encode(const AssemblyProgram& program, | 480 Status Encode(const AssemblyProgram& program, |
531 std::unique_ptr<EncodedProgram>* output) { | 481 std::unique_ptr<EncodedProgram>* output) { |
532 // Explicitly release any memory associated with the output before encoding. | 482 // Explicitly release any memory associated with the output before encoding. |
533 output->reset(); | 483 output->reset(); |
534 | 484 |
535 *output = program.Encode(); | 485 *output = program.Encode(); |
536 return (*output) ? C_OK : C_GENERAL_ERROR; | 486 return (*output) ? C_OK : C_GENERAL_ERROR; |
537 } | 487 } |
538 | 488 |
539 } // namespace courgette | 489 } // namespace courgette |
OLD | NEW |