| 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 #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 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 explicit Instruction(OP op) : op_(op), info_(0) {} | 50 explicit Instruction(OP op) : op_(op), info_(0) {} |
| 51 Instruction(OP op, unsigned int info) : op_(op), info_(info) {} | 51 Instruction(OP op, unsigned int info) : op_(op), info_(info) {} |
| 52 | 52 |
| 53 uint32_t op_ : 4; // A few bits to store the OP code. | 53 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. | 54 uint32_t info_ : 28; // Remaining bits in first word available to subclass. |
| 55 | 55 |
| 56 private: | 56 private: |
| 57 DISALLOW_COPY_AND_ASSIGN(Instruction); | 57 DISALLOW_COPY_AND_ASSIGN(Instruction); |
| 58 }; | 58 }; |
| 59 | 59 |
| 60 typedef NoThrowBuffer<Instruction*> InstructionVector; | 60 // An interface to receive emitted instructions parsed from an executable. |
| 61 class InstructionReceptor { |
| 62 public: |
| 63 InstructionReceptor() = default; |
| 64 virtual ~InstructionReceptor() = default; |
| 65 |
| 66 // Generates an entire base relocation table. |
| 67 virtual CheckBool EmitPeRelocs() = 0; |
| 68 |
| 69 // Generates an ELF style relocation table for X86. |
| 70 virtual CheckBool EmitElfRelocation() = 0; |
| 71 |
| 72 // Generates an ELF style relocation table for ARM. |
| 73 virtual CheckBool EmitElfARMRelocation() = 0; |
| 74 |
| 75 // Following instruction will be assembled at address 'rva'. |
| 76 virtual CheckBool EmitOrigin(RVA rva) = 0; |
| 77 |
| 78 // Generates a single byte of data or machine instruction. |
| 79 virtual CheckBool EmitSingleByte(uint8_t byte) = 0; |
| 80 |
| 81 // Generates multiple bytes of data or machine instructions. |
| 82 virtual CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) = 0; |
| 83 |
| 84 // Generates a 4-byte relative reference to address of 'label'. |
| 85 virtual CheckBool EmitRel32(Label* label) = 0; |
| 86 |
| 87 // Generates a 4-byte relative reference to address of 'label' for ARM. |
| 88 virtual CheckBool EmitRel32ARM(uint16_t op, |
| 89 Label* label, |
| 90 const uint8_t* arm_op, |
| 91 uint16_t op_size) = 0; |
| 92 |
| 93 // Generates a 4-byte absolute reference to address of 'label'. |
| 94 virtual CheckBool EmitAbs32(Label* label) = 0; |
| 95 |
| 96 // Generates an 8-byte absolute reference to address of 'label'. |
| 97 virtual CheckBool EmitAbs64(Label* label) = 0; |
| 98 |
| 99 private: |
| 100 DISALLOW_COPY_AND_ASSIGN(InstructionReceptor); |
| 101 }; |
| 61 | 102 |
| 62 // An AssemblyProgram is the result of disassembling an executable file. | 103 // An AssemblyProgram is the result of disassembling an executable file. |
| 63 // | 104 // |
| 64 // * The disassembler creates labels in the AssemblyProgram and emits | 105 // * The disassembler creates labels in the AssemblyProgram and emits |
| 65 // 'Instructions'. | 106 // 'Instructions'. |
| 66 // * The disassembler then calls DefaultAssignIndexes to assign | 107 // * The disassembler then calls DefaultAssignIndexes to assign |
| 67 // addresses to positions in the address tables. | 108 // addresses to positions in the address tables. |
| 68 // * [Optional step] | 109 // * [Optional step] |
| 69 // * At this point the AssemblyProgram can be converted into an | 110 // * At this point the AssemblyProgram can be converted into an |
| 70 // EncodedProgram and serialized to an output stream. | 111 // EncodedProgram and serialized to an output stream. |
| 71 // * Later, the EncodedProgram can be deserialized and assembled into | 112 // * Later, the EncodedProgram can be deserialized and assembled into |
| 72 // the original file. | 113 // the original file. |
| 73 // | 114 // |
| 74 // The optional step is to modify the AssemblyProgram. One form of modification | 115 // 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 | 116 // 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 | 117 // AssemblyProgram look more like the EncodedProgram for some other |
| 77 // AssemblyProgram. The modification process should call UnassignIndexes, do | 118 // AssemblyProgram. The modification process should call UnassignIndexes, do |
| 78 // its own assignment, and then call AssignRemainingIndexes to ensure all | 119 // its own assignment, and then call AssignRemainingIndexes to ensure all |
| 79 // indexes are assigned. | 120 // indexes are assigned. |
| 80 // | 121 |
| 81 class AssemblyProgram { | 122 class AssemblyProgram { |
| 82 public: | 123 public: |
| 83 using LabelHandler = base::Callback<void(Label*)>; | 124 using LabelHandler = base::Callback<void(Label*)>; |
| 84 using LabelHandlerMap = std::map<OP, LabelHandler>; | 125 using LabelHandlerMap = std::map<OP, LabelHandler>; |
| 85 | 126 |
| 127 // A callback for GenerateInstructions() to emit instructions. The first |
| 128 // argument (AssemblyProgram*) is provided for Label-related feature access. |
| 129 // The second argument (InstructionReceptor*) is a receptor for instructions. |
| 130 // The callback (which gets called in 2 passes) should return true on success, |
| 131 // and false otherwise. |
| 132 using InstructionGenerator = |
| 133 base::Callback<CheckBool(AssemblyProgram*, InstructionReceptor*)>; |
| 134 |
| 86 explicit AssemblyProgram(ExecutableType kind); | 135 explicit AssemblyProgram(ExecutableType kind); |
| 87 ~AssemblyProgram(); | 136 ~AssemblyProgram(); |
| 88 | 137 |
| 89 ExecutableType kind() const { return kind_; } | 138 ExecutableType kind() const { return kind_; } |
| 90 | 139 |
| 91 void set_image_base(uint64_t image_base) { image_base_ = image_base; } | 140 void set_image_base(uint64_t image_base) { image_base_ = image_base; } |
| 92 | 141 |
| 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. | 142 // Traverses RVAs in |abs32_visitor| and |rel32_visitor| to precompute Labels. |
| 131 void PrecomputeLabels(RvaVisitor* abs32_visitor, RvaVisitor* rel32_visitor); | 143 void PrecomputeLabels(RvaVisitor* abs32_visitor, RvaVisitor* rel32_visitor); |
| 132 | 144 |
| 133 // Removes underused Labels. Thresholds used (0 = no trimming) is | 145 // Removes underused Labels. Thresholds used (0 = no trimming) is |
| 134 // architecture-dependent. | 146 // architecture-dependent. |
| 135 void TrimLabels(); | 147 void TrimLabels(); |
| 136 | 148 |
| 137 void UnassignIndexes(); | 149 void UnassignIndexes(); |
| 138 void DefaultAssignIndexes(); | 150 void DefaultAssignIndexes(); |
| 139 void AssignRemainingIndexes(); | 151 void AssignRemainingIndexes(); |
| 140 | 152 |
| 141 // Looks up abs32 label. Returns null if none found. | 153 // Looks up abs32 label. Returns null if none found. |
| 142 Label* FindAbs32Label(RVA rva); | 154 Label* FindAbs32Label(RVA rva); |
| 143 | 155 |
| 144 // Looks up rel32 label. Returns null if none found. | 156 // Looks up rel32 label. Returns null if none found. |
| 145 Label* FindRel32Label(RVA rva); | 157 Label* FindRel32Label(RVA rva); |
| 146 | 158 |
| 147 std::unique_ptr<EncodedProgram> Encode() const; | 159 std::unique_ptr<EncodedProgram> Encode() const; |
| 148 | 160 |
| 149 // For each |instruction| in |instructions_|, looks up its opcode from | 161 // 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 | 162 // |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., | 163 // |instruction|'s label. We assume that |handler_map| has correct keys, i.e., |
| 152 // opcodes for an instruction that have label. | 164 // opcodes for an instruction that have label. |
| 153 void HandleInstructionLabels(const LabelHandlerMap& handler_map) const; | 165 void HandleInstructionLabels(const LabelHandlerMap& handler_map) const; |
| 154 | 166 |
| 167 // Calls |gen| in 2 passes to emit instructions. In pass 1 we provide a |
| 168 // receptor to count space requirement. In pass 2 we provide a receptor to |
| 169 // store instructions. |
| 170 CheckBool GenerateInstructions(const InstructionGenerator& gen); |
| 171 |
| 172 // TODO(huangs): Implement these in InstructionStoreReceptor. |
| 173 // Instructions will be assembled in the order they are emitted. |
| 174 |
| 175 // Generates an entire base relocation table. |
| 176 CheckBool EmitPeRelocs() WARN_UNUSED_RESULT; |
| 177 |
| 178 // Generates an ELF style relocation table for X86. |
| 179 CheckBool EmitElfRelocation() WARN_UNUSED_RESULT; |
| 180 |
| 181 // Generates an ELF style relocation table for ARM. |
| 182 CheckBool EmitElfARMRelocation() WARN_UNUSED_RESULT; |
| 183 |
| 184 // Following instruction will be assembled at address 'rva'. |
| 185 CheckBool EmitOrigin(RVA rva) WARN_UNUSED_RESULT; |
| 186 |
| 187 // Generates a single byte of data or machine instruction. |
| 188 CheckBool EmitSingleByte(uint8_t byte) WARN_UNUSED_RESULT; |
| 189 |
| 190 // Generates multiple bytes of data or machine instructions. |
| 191 CheckBool EmitMultipleBytes(const uint8_t* bytes, |
| 192 size_t len) WARN_UNUSED_RESULT; |
| 193 |
| 194 // Generates a 4-byte relative reference to address of 'label'. |
| 195 CheckBool EmitRel32(Label* label) WARN_UNUSED_RESULT; |
| 196 |
| 197 // Generates a 4-byte relative reference to address of 'label' for ARM. |
| 198 CheckBool EmitRel32ARM(uint16_t op, |
| 199 Label* label, |
| 200 const uint8_t* arm_op, |
| 201 uint16_t op_size) WARN_UNUSED_RESULT; |
| 202 |
| 203 // Generates a 4-byte absolute reference to address of 'label'. |
| 204 CheckBool EmitAbs32(Label* label) WARN_UNUSED_RESULT; |
| 205 |
| 206 // Generates an 8-byte absolute reference to address of 'label'. |
| 207 CheckBool EmitAbs64(Label* label) WARN_UNUSED_RESULT; |
| 208 |
| 155 private: | 209 private: |
| 210 using InstructionVector = NoThrowBuffer<Instruction*>; |
| 211 |
| 156 using ScopedInstruction = | 212 using ScopedInstruction = |
| 157 std::unique_ptr<Instruction, UncheckedDeleter<Instruction>>; | 213 std::unique_ptr<Instruction, UncheckedDeleter<Instruction>>; |
| 158 | 214 |
| 159 ExecutableType kind_; | 215 ExecutableType kind_; |
| 160 | 216 |
| 161 CheckBool Emit(ScopedInstruction instruction) WARN_UNUSED_RESULT; | 217 CheckBool Emit(ScopedInstruction instruction) WARN_UNUSED_RESULT; |
| 162 CheckBool EmitShared(Instruction* instruction) WARN_UNUSED_RESULT; | 218 CheckBool EmitShared(Instruction* instruction) WARN_UNUSED_RESULT; |
| 163 | 219 |
| 164 static const int kLabelLowerLimit; | 220 static const int kLabelLowerLimit; |
| 165 | 221 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 189 | 245 |
| 190 // Converts |program| into encoded form, returning it as |*output|. | 246 // Converts |program| into encoded form, returning it as |*output|. |
| 191 // Returns C_OK if succeeded, otherwise returns an error status and sets | 247 // Returns C_OK if succeeded, otherwise returns an error status and sets |
| 192 // |*output| to null. | 248 // |*output| to null. |
| 193 Status Encode(const AssemblyProgram& program, | 249 Status Encode(const AssemblyProgram& program, |
| 194 std::unique_ptr<EncodedProgram>* output); | 250 std::unique_ptr<EncodedProgram>* output); |
| 195 | 251 |
| 196 } // namespace courgette | 252 } // namespace courgette |
| 197 | 253 |
| 198 #endif // COURGETTE_ASSEMBLY_PROGRAM_H_ | 254 #endif // COURGETTE_ASSEMBLY_PROGRAM_H_ |
| OLD | NEW |