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

Unified Diff: courgette/assembly_program.cc

Issue 2476863004: [Courgette] AssemblyProgram: Serialize data to single raw buffer, instead of storing pointer of obj… (Closed)
Patch Set: Sync and merge. 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « courgette/assembly_program.h ('k') | courgette/courgette.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: courgette/assembly_program.cc
diff --git a/courgette/assembly_program.cc b/courgette/assembly_program.cc
index f1502a9ee324e956f034578b1776e9afc3aa29fd..1eb267a0c1696a1e6b8b86af3fc36da0c33abdd2 100644
--- a/courgette/assembly_program.cc
+++ b/courgette/assembly_program.cc
@@ -21,93 +21,286 @@ namespace courgette {
namespace {
-// Sets the current address for the emitting instructions.
-class OriginInstruction : public Instruction {
+// AssemblyProgram stores a sequence of instructions. The main uses are:
+// - Serialization (write): InstructionStoreReceptor::Emit*() produces and
+// serializes instructions into AssemblyProgram::instruction_raw_data_.
+// - Encode (read): AssemblyProgram::Encode() iterates over serialized
+// instructions and sends them to EncodedProgram.
+// - Label extraction (read): AssemblyProgram::HandleInstructionLabels()
+// iterates over serialized instructions and process only instructions with
+// Labels.
+
+/******** Instruction ********/
+
+// Each instruction type (AssemblyOp::OP) has a corresponding class, and these
+// classes have a common base class (Instruction). To simplify serialization,
+// we want to write entire objects into buffer using pointer casting. However,
+// the naive approach has 2 problems:
+// (1) C++ struct can add padding, which wastes space.
+// (2) Virtual function usage adds bloat to object size.
+// Problem (1) is solved using #pragma pack() directives. Problem 2 is solved
+// by decoupling storage (Data* structs) from behavior (Instruction* classes).
+
+// Instruction interfaces that don't use templates. Instead of directly storing
+// data, Instruction provides a "view" into a provided buffer, and keeps a
+// "cursor" pointer to access the data. The base interface is only used by
+// "read" use cases (encode & label extraction).
+class Instruction {
public:
- explicit OriginInstruction(RVA rva) : Instruction(ORIGIN, 0), rva_(rva) {}
- RVA origin_rva() const { return rva_; }
+ Instruction() = default;
+ virtual ~Instruction() = default;
+
+// All data payload for inherited classes of Instruction.
+#pragma pack(push, 1)
+ // If we nest these classes then we won't be able to use initializer list.
+ struct Data {
+ AssemblyOp::OP op;
+ };
+
+ struct DataWithRVA {
+ AssemblyOp::OP op;
+ RVA rva;
+ };
+
+ struct DataWithExecutableType {
+ AssemblyOp::OP op;
+ ExecutableType exe_type;
+ };
+
+ struct DataWithByte {
+ AssemblyOp::OP op;
+ uint8_t byte;
+ };
+
+ struct DataWithBytesAndSize {
+ AssemblyOp::OP op;
+ const uint8_t* bytes;
+ serialized_size_t size;
+ };
+
+ struct DataWithLabel {
+ AssemblyOp::OP op;
+ Label* label;
+ };
+
+ struct DataWithLabelAndARMRel32 {
+ AssemblyOp::OP op;
+ Label* label;
+ uint16_t compressed_op;
+ const uint8_t* arm_op; // TODO(huangs): Looks unused? Remove.
+ uint16_t op_size; // TODO(huangs): Looks unused? Remove.
+ };
+#pragma pack(pop)
+
+ // Getters for basic info.
+ virtual AssemblyOp::OP GetOp() const = 0;
+ virtual size_t GetSize() const = 0;
+
+ // If the instruction located at |it| has a Label, returns it. Otherwise
+ // returns null.
+ virtual Label* ReadLabel(AssemblyRawDataVector::const_iterator it) const {
+ return nullptr;
+ }
+
+ // Sends the instruction to |encoded|, possibly using config from |prog|.
+ virtual bool Encode(AssemblyRawDataVector::const_iterator it,
+ EncodedProgram* encoded) const = 0;
+
private:
- RVA rva_;
+ DISALLOW_COPY_AND_ASSIGN(Instruction);
};
-// Emits an entire PE base relocation table.
-class PeRelocsInstruction : public Instruction {
- public:
- PeRelocsInstruction() : Instruction(MAKEPERELOCS) {}
-};
+/******** InstructionImpl ********/
-// Emits an ELF relocation table.
-class ElfRelocsInstruction : public Instruction {
+// Intermediate Instruction class using templates.
+template <int OP_USE, typename DATA_T>
+class InstructionImpl : public Instruction {
public:
- ElfRelocsInstruction() : Instruction(MAKEELFRELOCS) {}
-};
+ using This = InstructionImpl<OP_USE, DATA_T>;
+
+ static constexpr AssemblyOp::OP kOpUse = static_cast<AssemblyOp::OP>(OP_USE);
+ static constexpr size_t kSize = sizeof(DATA_T);
+
+ InstructionImpl() {}
+ ~InstructionImpl() override = default;
+
+ // Instruction:
+ AssemblyOp::OP GetOp() const override { return kOpUse; }
+ size_t GetSize() const override { return kSize; }
+ bool Encode(AssemblyRawDataVector::const_iterator it,
+ EncodedProgram* encoded) const override = 0;
+
+ // Allocates space at end of |raw_data|, and writes |data_in| there.
+ CheckBool Serialize(AssemblyRawDataVector* raw_data, DATA_T data_in) {
+ size_t pos = raw_data->size();
+ if (!raw_data->resize(pos + kSize, 0))
+ return false;
+ DCHECK(pos + sizeof(DATA_T) <= raw_data->size());
+ *reinterpret_cast<DATA_T*>(&(*raw_data)[pos]) = data_in;
+ return true;
+ }
-// Emits an ELF ARM relocation table.
-class ElfARMRelocsInstruction : public Instruction {
- public:
- ElfARMRelocsInstruction() : Instruction(MAKEELFARMRELOCS) {}
+ protected:
+ const DATA_T* SeekRead(AssemblyRawDataVector::const_iterator it) const {
+ return reinterpret_cast<const DATA_T*>(&(*it));
+ }
};
-// Emits a single byte.
-class ByteInstruction : public Instruction {
- public:
- explicit ByteInstruction(uint8_t value) : Instruction(DEFBYTE, value) {}
- uint8_t byte_value() const { return info_; }
+/******** InstructionWithLabel ********/
+
+// Common code for the "Label extraction" use case.
+template <int OP_USE, typename DATA_T>
+class InstructionWithLabel : public InstructionImpl<OP_USE, DATA_T> {
+ // Instruction:
+ Label* ReadLabel(AssemblyRawDataVector::const_iterator it) const override {
+ return SeekRead(it)->label;
+ }
};
-// Emits a single byte.
-class BytesInstruction : public Instruction {
- public:
- BytesInstruction(const uint8_t* values, size_t len)
- : Instruction(DEFBYTES, 0), values_(values), len_(len) {}
- const uint8_t* byte_values() const { return values_; }
- size_t len() const { return len_; }
+/******** Instruction*, one for each AssemblyOp:OP value ********/
- private:
- const uint8_t* values_;
- size_t len_;
+struct InstructionMakePERelocs
+ : public InstructionImpl<AssemblyOp::MAKEPERELOCS,
+ Instruction::DataWithExecutableType> {
+ bool Encode(AssemblyRawDataVector::const_iterator it,
+ EncodedProgram* encoded) const override {
+ return encoded->AddPeMakeRelocs(SeekRead(it)->exe_type);
+ }
+ static InstructionMakePERelocs instance;
};
+InstructionMakePERelocs InstructionMakePERelocs::instance;
-// A ABS32 to REL32 instruction emits a reference to a label's address.
-class InstructionWithLabel : public Instruction {
- public:
- InstructionWithLabel(OP op, Label* label)
- : Instruction(op, 0), label_(label) {
- if (label == NULL) NOTREACHED();
+struct InstructionMakeELFRelocs
+ : public InstructionImpl<AssemblyOp::MAKEELFRELOCS, Instruction::Data> {
+ bool Encode(AssemblyRawDataVector::const_iterator it,
+ EncodedProgram* encoded) const override {
+ return encoded->AddElfMakeRelocs();
}
- Label* label() const { return label_; }
- protected:
- Label* label_;
+ static InstructionMakeELFRelocs instance;
};
+InstructionMakeELFRelocs InstructionMakeELFRelocs::instance;
-// An ARM REL32 instruction emits a reference to a label's address and
-// a specially-compressed ARM op.
-class InstructionWithLabelARM : public InstructionWithLabel {
- public:
- InstructionWithLabelARM(OP op,
- uint16_t compressed_op,
- Label* label,
- const uint8_t* arm_op,
- uint16_t op_size)
- : InstructionWithLabel(op, label),
- compressed_op_(compressed_op),
- arm_op_(arm_op),
- op_size_(op_size) {
- if (label == NULL) NOTREACHED();
- }
- uint16_t compressed_op() const { return compressed_op_; }
- const uint8_t* arm_op() const { return arm_op_; }
- uint16_t op_size() const { return op_size_; }
+struct InstructionMakeELFARMRelocs
+ : public InstructionImpl<AssemblyOp::MAKEELFARMRELOCS, Instruction::Data> {
+ bool Encode(AssemblyRawDataVector::const_iterator it,
+ EncodedProgram* encoded) const override {
+ return encoded->AddElfARMMakeRelocs();
+ }
+ static InstructionMakeELFARMRelocs instance;
+};
+InstructionMakeELFARMRelocs InstructionMakeELFARMRelocs::instance;
- private:
- uint16_t compressed_op_;
- const uint8_t* arm_op_;
- uint16_t op_size_;
+struct InstructionOrigin
+ : public InstructionImpl<AssemblyOp::ORIGIN, Instruction::DataWithRVA> {
+ bool Encode(AssemblyRawDataVector::const_iterator it,
+ EncodedProgram* encoded) const override {
+ return encoded->AddOrigin(SeekRead(it)->rva);
+ }
+ static InstructionOrigin instance;
+};
+InstructionOrigin InstructionOrigin::instance;
+
+struct InstructionSingleByte
+ : public InstructionImpl<AssemblyOp::SINGLEBYTE,
+ Instruction::DataWithByte> {
+ bool Encode(AssemblyRawDataVector::const_iterator it,
+ EncodedProgram* encoded) const override {
+ return encoded->AddCopy(1, &SeekRead(it)->byte);
+ }
+ static InstructionSingleByte instance;
+};
+InstructionSingleByte InstructionSingleByte::instance;
+
+struct InstructionMultipleBytes
+ : public InstructionImpl<AssemblyOp::MULTIPLEBYTES,
+ Instruction::DataWithBytesAndSize> {
+ bool Encode(AssemblyRawDataVector::const_iterator it,
+ EncodedProgram* encoded) const override {
+ const auto* cursor = SeekRead(it);
+ return encoded->AddCopy(cursor->size, cursor->bytes);
+ }
+ static InstructionMultipleBytes instance;
+};
+InstructionMultipleBytes InstructionMultipleBytes::instance;
+
+struct InstructionRel32
+ : public InstructionWithLabel<AssemblyOp::REL32,
+ Instruction::DataWithLabel> {
+ bool Encode(AssemblyRawDataVector::const_iterator it,
+ EncodedProgram* encoded) const override {
+ return encoded->AddRel32(SeekRead(it)->label->index_);
+ }
+ static InstructionRel32 instance;
+};
+InstructionRel32 InstructionRel32::instance;
+
+struct InstructionRel32ARM
+ : public InstructionWithLabel<AssemblyOp::REL32ARM,
+ Instruction::DataWithLabelAndARMRel32> {
+ bool Encode(AssemblyRawDataVector::const_iterator it,
+ EncodedProgram* encoded) const override {
+ const auto* cursor = SeekRead(it);
+ return encoded->AddRel32ARM(cursor->compressed_op, cursor->label->index_);
+ }
+ static InstructionRel32ARM instance;
};
+InstructionRel32ARM InstructionRel32ARM::instance;
+
+struct InstructionAbs32
+ : public InstructionWithLabel<AssemblyOp::ABS32,
+ Instruction::DataWithLabel> {
+ bool Encode(AssemblyRawDataVector::const_iterator it,
+ EncodedProgram* encoded) const override {
+ return encoded->AddAbs32(SeekRead(it)->label->index_);
+ }
+ static InstructionAbs32 instance;
+};
+InstructionAbs32 InstructionAbs32::instance;
+
+struct InstructionAbs64
+ : public InstructionWithLabel<AssemblyOp::ABS64,
+ Instruction::DataWithLabel> {
+ bool Encode(AssemblyRawDataVector::const_iterator it,
+ EncodedProgram* encoded) const override {
+ return encoded->AddAbs64(SeekRead(it)->label->index_);
+ }
+ static InstructionAbs64 instance;
+};
+InstructionAbs64 InstructionAbs64::instance;
+
+/******** Utility Functions ********/
+
+// A collection of reusable Instruction instances.
+Instruction* FindInstruction(AssemblyOp::OP op) {
+ switch (op) {
+ case InstructionOrigin::kOpUse:
+ return &InstructionOrigin::instance;
+ case InstructionMakePERelocs::kOpUse:
+ return &InstructionMakePERelocs::instance;
+ case InstructionMakeELFRelocs::kOpUse:
+ return &InstructionMakeELFRelocs::instance;
+ case InstructionSingleByte::kOpUse:
+ return &InstructionSingleByte::instance;
+ case InstructionRel32::kOpUse:
+ return &InstructionRel32::instance;
+ case InstructionAbs32::kOpUse:
+ return &InstructionAbs32::instance;
+ case InstructionRel32ARM::kOpUse:
+ return &InstructionRel32ARM::instance;
+ case InstructionMakeELFARMRelocs::kOpUse:
+ return &InstructionMakeELFARMRelocs::instance;
+ case InstructionMultipleBytes::kOpUse:
+ return &InstructionMultipleBytes::instance;
+ case InstructionAbs64::kOpUse:
+ return &InstructionAbs64::instance;
+ }
+ NOTREACHED();
+ return nullptr;
+}
/******** InstructionCountReceptor ********/
-// An InstructionReceptor that counts space occupied by emitted instructions.
+// An InstructionReceptor to count space occupied by emitted instructions.
class InstructionCountReceptor : public InstructionReceptor {
public:
InstructionCountReceptor() = default;
@@ -115,26 +308,35 @@ class InstructionCountReceptor : public InstructionReceptor {
size_t size() const { return size_; }
// InstructionReceptor:
- // TODO(huangs): 2016/11: Populate these with size_ += ...
- CheckBool EmitPeRelocs() override { return true; }
- CheckBool EmitElfRelocation() override { return true; }
- CheckBool EmitElfARMRelocation() override { return true; }
- CheckBool EmitOrigin(RVA rva) override { return true; }
- CheckBool EmitSingleByte(uint8_t byte) override { return true; }
- CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) override {
- return true;
+ CheckBool EmitPeRelocs() { return Add<InstructionMakePERelocs>(); }
+ CheckBool EmitElfRelocation() { return Add<InstructionMakeELFRelocs>(); }
+ CheckBool EmitElfARMRelocation() {
+ return Add<InstructionMakeELFARMRelocs>();
+ }
+ CheckBool EmitOrigin(RVA rva) { return Add<InstructionOrigin>(); }
+ CheckBool EmitSingleByte(uint8_t byte) {
+ return Add<InstructionSingleByte>();
}
- CheckBool EmitRel32(Label* label) override { return true; }
- CheckBool EmitRel32ARM(uint16_t op,
+ CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) {
+ return Add<InstructionMultipleBytes>();
+ }
+ CheckBool EmitRel32(Label* label) { return Add<InstructionRel32>(); }
+ CheckBool EmitRel32ARM(uint16_t compressed_op,
Label* label,
const uint8_t* arm_op,
- uint16_t op_size) override {
- return true;
+ uint16_t op_size) {
+ return Add<InstructionRel32ARM>();
}
- CheckBool EmitAbs32(Label* label) override { return true; }
- CheckBool EmitAbs64(Label* label) override { return true; }
+ CheckBool EmitAbs32(Label* label) { return Add<InstructionAbs32>(); }
+ CheckBool EmitAbs64(Label* label) { return Add<InstructionAbs64>(); }
private:
+ template <typename T>
+ inline bool Add() {
+ size_ += T::kSize;
+ return true;
+ }
+
size_t size_ = 0;
DISALLOW_COPY_AND_ASSIGN(InstructionCountReceptor);
@@ -142,50 +344,67 @@ class InstructionCountReceptor : public InstructionReceptor {
/******** InstructionStoreReceptor ********/
-// An InstructionReceptor that stores emitted instructions.
+// An InstructionReceptor to store emitted instructions.
class InstructionStoreReceptor : public InstructionReceptor {
public:
- explicit InstructionStoreReceptor(AssemblyProgram* program)
- : program_(program) {
- CHECK(program_);
- }
-
- // TODO(huangs): 2016/11: Add Reserve().
+ InstructionStoreReceptor(ExecutableType exe_type,
+ AssemblyRawDataVector* raw_data)
+ : exe_type_(exe_type), raw_data_(raw_data) {}
// InstructionReceptor:
- // TODO(huangs): 2016/11: Replace stub with implementation.
- CheckBool EmitPeRelocs() override { return program_->EmitPeRelocs(); }
- CheckBool EmitElfRelocation() override {
- return program_->EmitElfRelocation();
+ CheckBool EmitPeRelocs() {
+ InstructionMakePERelocs instr;
+ return instr.Serialize(raw_data_, {instr.GetOp(), exe_type_});
+ }
+ CheckBool EmitElfRelocation() {
+ InstructionMakeELFRelocs instr;
+ return instr.Serialize(raw_data_, {instr.GetOp()});
}
- CheckBool EmitElfARMRelocation() override {
- return program_->EmitElfARMRelocation();
+ CheckBool EmitElfARMRelocation() {
+ InstructionMakeELFARMRelocs instr;
+ return instr.Serialize(raw_data_, {instr.GetOp()});
}
- CheckBool EmitOrigin(RVA rva) override { return program_->EmitOrigin(rva); }
- CheckBool EmitSingleByte(uint8_t byte) override {
- return program_->EmitSingleByte(byte);
+ CheckBool EmitOrigin(RVA rva) {
+ InstructionOrigin instr;
+ return instr.Serialize(raw_data_, {instr.GetOp(), rva});
}
- CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) override {
- return program_->EmitMultipleBytes(bytes, len);
+ CheckBool EmitSingleByte(uint8_t byte) {
+ InstructionSingleByte instr;
+ return instr.Serialize(raw_data_, {instr.GetOp(), byte});
}
- CheckBool EmitRel32(Label* label) override {
- return program_->EmitRel32(label);
+ CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) {
+ InstructionMultipleBytes instr;
+ return instr.Serialize(
+ raw_data_, {instr.GetOp(), bytes, static_cast<serialized_size_t>(len)});
}
- CheckBool EmitRel32ARM(uint16_t op,
+ CheckBool EmitRel32(Label* label) {
+ InstructionRel32 instr;
+ return instr.Serialize(raw_data_, {instr.GetOp(), label});
+ }
+ CheckBool EmitRel32ARM(uint16_t compressed_op,
Label* label,
const uint8_t* arm_op,
- uint16_t op_size) override {
- return program_->EmitRel32ARM(op, label, arm_op, op_size);
+ uint16_t op_size) {
+ InstructionRel32ARM instr;
+ // Note that |label| is moved before |compressed_op|.
+ return instr.Serialize(
+ raw_data_, {instr.GetOp(), label, compressed_op, arm_op, op_size});
}
- CheckBool EmitAbs32(Label* label) override {
- return program_->EmitAbs32(label);
+ CheckBool EmitAbs32(Label* label) {
+ InstructionAbs32 instr;
+ return instr.Serialize(raw_data_, {instr.GetOp(), label});
}
- CheckBool EmitAbs64(Label* label) override {
- return program_->EmitAbs64(label);
+ CheckBool EmitAbs64(Label* label) {
+ InstructionAbs64 instr;
+ return instr.Serialize(raw_data_, {instr.GetOp(), label});
}
private:
- AssemblyProgram* program_;
+ // Executable type for PE relocation.
+ const ExecutableType exe_type_;
+
+ // Storage of raw instruction data, owned by this instance's owner.
+ AssemblyRawDataVector* raw_data_;
DISALLOW_COPY_AND_ASSIGN(InstructionStoreReceptor);
};
@@ -194,68 +413,7 @@ class InstructionStoreReceptor : public InstructionReceptor {
/******** AssemblyProgram ********/
-AssemblyProgram::AssemblyProgram(ExecutableType kind)
- : kind_(kind), image_base_(0) {
-}
-
-AssemblyProgram::~AssemblyProgram() {
- for (size_t i = 0; i < instructions_.size(); ++i) {
- Instruction* instruction = instructions_[i];
- if (instruction->op() != DEFBYTE) // Owned by byte_instruction_cache_.
- UncheckedDelete(instruction);
- }
- if (byte_instruction_cache_.get()) {
- for (size_t i = 0; i < 256; ++i)
- UncheckedDelete(byte_instruction_cache_[i]);
- }
-}
-
-CheckBool AssemblyProgram::EmitPeRelocs() {
- return Emit(ScopedInstruction(UncheckedNew<PeRelocsInstruction>()));
-}
-
-CheckBool AssemblyProgram::EmitElfRelocation() {
- return Emit(ScopedInstruction(UncheckedNew<ElfRelocsInstruction>()));
-}
-
-CheckBool AssemblyProgram::EmitElfARMRelocation() {
- return Emit(ScopedInstruction(UncheckedNew<ElfARMRelocsInstruction>()));
-}
-
-CheckBool AssemblyProgram::EmitOrigin(RVA rva) {
- return Emit(ScopedInstruction(UncheckedNew<OriginInstruction>(rva)));
-}
-
-CheckBool AssemblyProgram::EmitSingleByte(uint8_t byte) {
- return EmitShared(GetByteInstruction(byte));
-}
-
-CheckBool AssemblyProgram::EmitMultipleBytes(const uint8_t* bytes, size_t len) {
- return Emit(ScopedInstruction(UncheckedNew<BytesInstruction>(bytes, len)));
-}
-
-CheckBool AssemblyProgram::EmitRel32(Label* label) {
- return Emit(
- ScopedInstruction(UncheckedNew<InstructionWithLabel>(REL32, label)));
-}
-
-CheckBool AssemblyProgram::EmitRel32ARM(uint16_t op,
- Label* label,
- const uint8_t* arm_op,
- uint16_t op_size) {
- return Emit(ScopedInstruction(UncheckedNew<InstructionWithLabelARM>(
- REL32ARM, op, label, arm_op, op_size)));
-}
-
-CheckBool AssemblyProgram::EmitAbs32(Label* label) {
- return Emit(
- ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS32, label)));
-}
-
-CheckBool AssemblyProgram::EmitAbs64(Label* label) {
- return Emit(
- ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS64, label)));
-}
+AssemblyProgram::AssemblyProgram(ExecutableType kind) : kind_(kind) {}
void AssemblyProgram::PrecomputeLabels(RvaVisitor* abs32_visitor,
RvaVisitor* rel32_visitor) {
@@ -305,40 +463,45 @@ Label* AssemblyProgram::FindRel32Label(RVA rva) {
void AssemblyProgram::HandleInstructionLabels(
const AssemblyProgram::LabelHandlerMap& handler_map) const {
- for (const Instruction* instruction : instructions_) {
- LabelHandlerMap::const_iterator it = handler_map.find(instruction->op());
- if (it != handler_map.end()) {
- it->second.Run(
- static_cast<const InstructionWithLabel*>(instruction)->label());
+ auto it = instruction_raw_data_.begin();
+ auto end = instruction_raw_data_.end();
+ while (it < end) {
+ // Get the instruction from the operation.
+ AssemblyOp::OP op = static_cast<AssemblyOp::OP>(*it);
+ Instruction* instr = FindInstruction(op);
+ DCHECK_LE(it + instr->GetSize(), end);
+
+ // If Label exists and is handled, then handle it.
+ Label* label = instr->ReadLabel(it);
+ if (label) {
+ LabelHandlerMap::const_iterator label_it = handler_map.find(op);
+ if (label_it != handler_map.end())
+ label_it->second.Run(label);
}
+ it += instr->GetSize();
}
}
CheckBool AssemblyProgram::GenerateInstructions(
const InstructionGenerator& gen) {
+ CHECK(instruction_raw_data_.empty());
+
// Pass 1: Count the space needed to store instructions.
InstructionCountReceptor count_receptor;
if (!gen.Run(this, &count_receptor))
return false;
- // Pass 2: Emit all instructions to preallocated buffer (uses Phase 1 count).
- InstructionStoreReceptor store_receptor(this);
- // TODO(huangs): 2016/11: Pass |count_receptor_->size()| to |store_receptor_|
- // to reserve space for raw data.
- return gen.Run(this, &store_receptor);
-}
+ // Reserve space for raw data, using count from Phase 1.
+ if (!instruction_raw_data_.reserve(count_receptor.size()))
+ return false;
-CheckBool AssemblyProgram::Emit(ScopedInstruction instruction) {
- if (!instruction || !instructions_.push_back(instruction.get()))
+ // Pass 2: Emit all instructions to preallocated buffer (uses Phase 1 count).
+ InstructionStoreReceptor store_receptor(kind(), &instruction_raw_data_);
+ if (!gen.Run(this, &store_receptor))
return false;
- // Ownership successfully passed to instructions_.
- ignore_result(instruction.release());
- return true;
-}
-CheckBool AssemblyProgram::EmitShared(Instruction* instruction) {
- DCHECK(!instruction || instruction->op() == DEFBYTE);
- return instruction && instructions_.push_back(instruction);
+ CHECK_EQ(count_receptor.size(), instruction_raw_data_.size());
+ return true;
}
void AssemblyProgram::UnassignIndexes(RVAToLabel* labels) {
@@ -367,7 +530,7 @@ void AssemblyProgram::AssignRemainingIndexes(RVAToLabel* labels) {
// An address table compresses best when each index is associated with an
// address that is slight larger than the previous index.
- // First see which indexes have not been used. The 'available' vector could
+ // First see which indexes have not been used. The 'available' vector could
// grow even bigger, but the number of addresses is a better starting size
// than empty.
std::vector<bool> available(labels->size(), true);
@@ -458,106 +621,20 @@ std::unique_ptr<EncodedProgram> AssemblyProgram::Encode() const {
if (!encoded->ImportLabels(abs32_label_manager_, rel32_label_manager_))
return nullptr;
- for (size_t i = 0; i < instructions_.size(); ++i) {
- Instruction* instruction = instructions_[i];
+ auto it = instruction_raw_data_.begin();
+ auto end = instruction_raw_data_.end();
+ while (it < end) {
+ // Get the instruction from the operation.
+ AssemblyOp::OP op = static_cast<AssemblyOp::OP>(*it);
+ Instruction* instr = FindInstruction(op);
+ DCHECK_LE(it + instr->GetSize(), end);
- switch (instruction->op()) {
- case ORIGIN: {
- OriginInstruction* org = static_cast<OriginInstruction*>(instruction);
- if (!encoded->AddOrigin(org->origin_rva()))
- return nullptr;
- break;
- }
- case DEFBYTE: {
- uint8_t b = static_cast<ByteInstruction*>(instruction)->byte_value();
- if (!encoded->AddCopy(1, &b))
- return nullptr;
- break;
- }
- case DEFBYTES: {
- const uint8_t* byte_values =
- static_cast<BytesInstruction*>(instruction)->byte_values();
- size_t len = static_cast<BytesInstruction*>(instruction)->len();
-
- if (!encoded->AddCopy(len, byte_values))
- return nullptr;
- break;
- }
- case REL32: {
- Label* label = static_cast<InstructionWithLabel*>(instruction)->label();
- if (!encoded->AddRel32(label->index_))
- return nullptr;
- break;
- }
- case REL32ARM: {
- Label* label =
- static_cast<InstructionWithLabelARM*>(instruction)->label();
- uint16_t compressed_op =
- static_cast<InstructionWithLabelARM*>(instruction)->compressed_op();
- if (!encoded->AddRel32ARM(compressed_op, label->index_))
- return nullptr;
- break;
- }
- case ABS32: {
- Label* label = static_cast<InstructionWithLabel*>(instruction)->label();
- if (!encoded->AddAbs32(label->index_))
- return nullptr;
- break;
- }
- case ABS64: {
- Label* label = static_cast<InstructionWithLabel*>(instruction)->label();
- if (!encoded->AddAbs64(label->index_))
- return nullptr;
- break;
- }
- case MAKEPERELOCS: {
- if (!encoded->AddPeMakeRelocs(kind_))
- return nullptr;
- break;
- }
- case MAKEELFRELOCS: {
- if (!encoded->AddElfMakeRelocs())
- return nullptr;
- break;
- }
- case MAKEELFARMRELOCS: {
- if (!encoded->AddElfARMMakeRelocs())
- return nullptr;
- break;
- }
- default: {
- NOTREACHED() << "Unknown Insn OP kind";
- }
- }
+ instr->Encode(it, encoded.get());
+ it += instr->GetSize();
}
-
return encoded;
}
-Instruction* AssemblyProgram::GetByteInstruction(uint8_t byte) {
- if (!byte_instruction_cache_) {
- Instruction** ram = nullptr;
- if (!base::UncheckedMalloc(sizeof(Instruction*) * 256,
- reinterpret_cast<void**>(&ram))) {
- return nullptr;
- }
- byte_instruction_cache_.reset(ram);
-
- for (int i = 0; i < 256; ++i) {
- byte_instruction_cache_[i] =
- UncheckedNew<ByteInstruction>(static_cast<uint8_t>(i));
- if (!byte_instruction_cache_[i]) {
- for (int j = 0; j < i; ++j)
- UncheckedDelete(byte_instruction_cache_[j]);
- byte_instruction_cache_.reset();
- return nullptr;
- }
- }
- }
-
- return byte_instruction_cache_[byte];
-}
-
////////////////////////////////////////////////////////////////////////////////
Status Encode(const AssemblyProgram& program,
« no previous file with comments | « courgette/assembly_program.h ('k') | courgette/courgette.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698