Chromium Code Reviews| 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 |
| 11 #include <map> | 11 #include <map> |
| 12 #include <memory> | 12 #include <memory> |
| 13 #include <set> | 13 #include <set> |
| 14 #include <vector> | 14 #include <vector> |
| 15 | 15 |
| 16 #include "base/bind.h" | 16 #include "base/bind.h" |
| 17 #include "base/macros.h" | 17 #include "base/macros.h" |
| 18 #include "base/memory/free_deleter.h" | 18 #include "base/memory/free_deleter.h" |
| 19 #include "courgette/courgette.h" | 19 #include "courgette/courgette.h" |
| 20 #include "courgette/image_utils.h" | 20 #include "courgette/image_utils.h" |
| 21 #include "courgette/label_manager.h" | 21 #include "courgette/label_manager.h" |
| 22 #include "courgette/memory_allocator.h" | 22 #include "courgette/memory_allocator.h" |
| 23 | 23 |
| 24 namespace courgette { | 24 namespace courgette { |
| 25 | 25 |
| 26 class AssemblyProgram; | |
| 26 class EncodedProgram; | 27 class EncodedProgram; |
| 27 | 28 |
| 28 // Opcodes of simple assembly language | 29 // Opcodes of simple assembly language |
| 29 enum OP { | 30 enum OP { |
| 30 ORIGIN, // ORIGIN <rva> - set current address for assembly. | 31 ORIGIN, // ORIGIN <rva> - set current address for assembly. |
| 31 MAKEPERELOCS, // Generates a base relocation table. | 32 MAKEPERELOCS, // Generates a base relocation table. |
| 32 MAKEELFRELOCS, // Generates a base relocation table. | 33 MAKEELFRELOCS, // Generates a base relocation table. |
| 33 DEFBYTE, // DEFBYTE <value> - emit a byte literal. | 34 DEFBYTE, // DEFBYTE <value> - emit a byte literal. |
| 34 REL32, // REL32 <label> - emit a rel32 encoded reference to 'label'. | 35 REL32, // REL32 <label> - emit a rel32 encoded reference to 'label'. |
| 35 ABS32, // ABS32 <label> - emit an abs32 encoded reference to 'label'. | 36 ABS32, // ABS32 <label> - emit an abs32 encoded reference to 'label'. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 50 explicit Instruction(OP op) : op_(op), info_(0) {} | 51 explicit Instruction(OP op) : op_(op), info_(0) {} |
| 51 Instruction(OP op, unsigned int info) : op_(op), info_(info) {} | 52 Instruction(OP op, unsigned int info) : op_(op), info_(info) {} |
| 52 | 53 |
| 53 uint32_t op_ : 4; // A few bits to store the OP code. | 54 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. | 55 uint32_t info_ : 28; // Remaining bits in first word available to subclass. |
| 55 | 56 |
| 56 private: | 57 private: |
| 57 DISALLOW_COPY_AND_ASSIGN(Instruction); | 58 DISALLOW_COPY_AND_ASSIGN(Instruction); |
| 58 }; | 59 }; |
| 59 | 60 |
| 60 typedef NoThrowBuffer<Instruction*> InstructionVector; | 61 class InstructionReceptor { |
| 62 public: | |
| 63 InstructionReceptor() = default; | |
| 64 virtual ~InstructionReceptor() = default; | |
| 65 | |
| 66 // Generates an entire base relocation table. | |
| 67 virtual CheckBool EmitPeRelocs() WARN_UNUSED_RESULT = 0; | |
| 68 | |
| 69 // Generates an ELF style relocation table for X86. | |
| 70 virtual CheckBool EmitElfRelocation() WARN_UNUSED_RESULT = 0; | |
| 71 | |
| 72 // Generates an ELF style relocation table for ARM. | |
| 73 virtual CheckBool EmitElfARMRelocation() WARN_UNUSED_RESULT = 0; | |
| 74 | |
| 75 // Following instruction will be assembled at address 'rva'. | |
| 76 virtual CheckBool EmitOrigin(RVA rva) WARN_UNUSED_RESULT = 0; | |
| 77 | |
| 78 // Generates a single byte of data or machine instruction. | |
| 79 virtual CheckBool EmitSingleByte(uint8_t byte) WARN_UNUSED_RESULT = 0; | |
| 80 | |
| 81 // Generates multiple bytes of data or machine instructions. | |
| 82 virtual CheckBool EmitMultipleBytes(const uint8_t* bytes, | |
| 83 size_t len) WARN_UNUSED_RESULT = 0; | |
| 84 | |
| 85 // Generates a 4-byte relative reference to address of 'label'. | |
| 86 virtual CheckBool EmitRel32(Label* label) WARN_UNUSED_RESULT = 0; | |
| 87 | |
| 88 // Generates a 4-byte relative reference to address of 'label' for ARM. | |
| 89 virtual CheckBool EmitRel32ARM(uint16_t op, | |
| 90 Label* label, | |
| 91 const uint8_t* arm_op, | |
| 92 uint16_t op_size) WARN_UNUSED_RESULT = 0; | |
| 93 | |
| 94 // Generates a 4-byte absolute reference to address of 'label'. | |
| 95 virtual CheckBool EmitAbs32(Label* label) WARN_UNUSED_RESULT = 0; | |
| 96 | |
| 97 // Generates an 8-byte absolute reference to address of 'label'. | |
| 98 virtual CheckBool EmitAbs64(Label* label) WARN_UNUSED_RESULT = 0; | |
| 99 | |
| 100 private: | |
| 101 DISALLOW_COPY_AND_ASSIGN(InstructionReceptor); | |
| 102 }; | |
| 103 | |
| 104 class InstructionCountReceptor : public InstructionReceptor { | |
| 105 public: | |
| 106 InstructionCountReceptor() = default; | |
| 107 | |
| 108 size_t size() const { return size_; } | |
| 109 | |
| 110 // InstructionReceptor: | |
| 111 CheckBool EmitPeRelocs() override WARN_UNUSED_RESULT; | |
| 112 CheckBool EmitElfRelocation() override WARN_UNUSED_RESULT; | |
| 113 CheckBool EmitElfARMRelocation() override WARN_UNUSED_RESULT; | |
| 114 CheckBool EmitOrigin(RVA rva) override WARN_UNUSED_RESULT; | |
| 115 CheckBool EmitSingleByte(uint8_t byte) override WARN_UNUSED_RESULT; | |
| 116 CheckBool EmitMultipleBytes(const uint8_t* bytes, | |
| 117 size_t len) override WARN_UNUSED_RESULT; | |
| 118 CheckBool EmitRel32(Label* label) override WARN_UNUSED_RESULT; | |
| 119 CheckBool EmitRel32ARM(uint16_t op, | |
| 120 Label* label, | |
| 121 const uint8_t* arm_op, | |
| 122 uint16_t op_size) override WARN_UNUSED_RESULT; | |
| 123 CheckBool EmitAbs32(Label* label) override WARN_UNUSED_RESULT; | |
| 124 CheckBool EmitAbs64(Label* label) override WARN_UNUSED_RESULT; | |
| 125 | |
| 126 private: | |
| 127 size_t size_ = 0; | |
| 128 | |
| 129 DISALLOW_COPY_AND_ASSIGN(InstructionCountReceptor); | |
| 130 }; | |
| 131 | |
| 132 class InstructionStoreReceptor : public InstructionReceptor { | |
| 133 public: | |
| 134 explicit InstructionStoreReceptor(AssemblyProgram* program); | |
| 135 | |
| 136 // TODO(huangs): 2016/11: Add Reserve(). | |
| 137 | |
| 138 // InstructionReceptor: | |
| 139 CheckBool EmitPeRelocs() override WARN_UNUSED_RESULT; | |
| 140 CheckBool EmitElfRelocation() override WARN_UNUSED_RESULT; | |
| 141 CheckBool EmitElfARMRelocation() override WARN_UNUSED_RESULT; | |
| 142 CheckBool EmitOrigin(RVA rva) override WARN_UNUSED_RESULT; | |
| 143 CheckBool EmitSingleByte(uint8_t byte) override WARN_UNUSED_RESULT; | |
| 144 CheckBool EmitMultipleBytes(const uint8_t* bytes, | |
| 145 size_t len) override WARN_UNUSED_RESULT; | |
| 146 CheckBool EmitRel32(Label* label) override WARN_UNUSED_RESULT; | |
| 147 CheckBool EmitRel32ARM(uint16_t op, | |
| 148 Label* label, | |
| 149 const uint8_t* arm_op, | |
| 150 uint16_t op_size) override WARN_UNUSED_RESULT; | |
| 151 CheckBool EmitAbs32(Label* label) override WARN_UNUSED_RESULT; | |
| 152 CheckBool EmitAbs64(Label* label) override WARN_UNUSED_RESULT; | |
| 153 | |
| 154 private: | |
| 155 AssemblyProgram* program_; | |
| 156 | |
| 157 DISALLOW_COPY_AND_ASSIGN(InstructionStoreReceptor); | |
| 158 }; | |
| 61 | 159 |
| 62 // An AssemblyProgram is the result of disassembling an executable file. | 160 // An AssemblyProgram is the result of disassembling an executable file. |
| 63 // | 161 // |
| 64 // * The disassembler creates labels in the AssemblyProgram and emits | 162 // * The disassembler creates labels in the AssemblyProgram and emits |
| 65 // 'Instructions'. | 163 // 'Instructions'. |
| 66 // * The disassembler then calls DefaultAssignIndexes to assign | 164 // * The disassembler then calls DefaultAssignIndexes to assign |
| 67 // addresses to positions in the address tables. | 165 // addresses to positions in the address tables. |
| 68 // * [Optional step] | 166 // * [Optional step] |
| 69 // * At this point the AssemblyProgram can be converted into an | 167 // * At this point the AssemblyProgram can be converted into an |
| 70 // EncodedProgram and serialized to an output stream. | 168 // EncodedProgram and serialized to an output stream. |
| 71 // * Later, the EncodedProgram can be deserialized and assembled into | 169 // * Later, the EncodedProgram can be deserialized and assembled into |
| 72 // the original file. | 170 // the original file. |
| 73 // | 171 // |
| 74 // The optional step is to modify the AssemblyProgram. One form of modification | 172 // 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 | 173 // 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 | 174 // AssemblyProgram look more like the EncodedProgram for some other |
| 77 // AssemblyProgram. The modification process should call UnassignIndexes, do | 175 // AssemblyProgram. The modification process should call UnassignIndexes, do |
| 78 // its own assignment, and then call AssignRemainingIndexes to ensure all | 176 // its own assignment, and then call AssignRemainingIndexes to ensure all |
| 79 // indexes are assigned. | 177 // indexes are assigned. |
| 80 // | 178 |
| 81 class AssemblyProgram { | 179 class AssemblyProgram { |
| 82 public: | 180 public: |
| 83 using LabelHandler = base::Callback<void(Label*)>; | 181 using LabelHandler = base::Callback<void(Label*)>; |
| 84 using LabelHandlerMap = std::map<OP, LabelHandler>; | 182 using LabelHandlerMap = std::map<OP, LabelHandler>; |
| 85 | 183 |
| 86 explicit AssemblyProgram(ExecutableType kind); | 184 explicit AssemblyProgram(ExecutableType kind); |
| 87 ~AssemblyProgram(); | 185 ~AssemblyProgram(); |
| 88 | 186 |
| 89 ExecutableType kind() const { return kind_; } | 187 ExecutableType kind() const { return kind_; } |
| 90 | 188 |
| 91 void set_image_base(uint64_t image_base) { image_base_ = image_base; } | 189 void set_image_base(uint64_t image_base) { image_base_ = image_base; } |
| 92 | 190 |
| 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. | 191 // Traverses RVAs in |abs32_visitor| and |rel32_visitor| to precompute Labels. |
| 131 void PrecomputeLabels(RvaVisitor* abs32_visitor, RvaVisitor* rel32_visitor); | 192 void PrecomputeLabels(RvaVisitor* abs32_visitor, RvaVisitor* rel32_visitor); |
| 132 | 193 |
| 133 // Removes underused Labels. Thresholds used (0 = no trimming) is | 194 // Removes underused Labels. Thresholds used (0 = no trimming) is |
| 134 // architecture-dependent. | 195 // architecture-dependent. |
| 135 void TrimLabels(); | 196 void TrimLabels(); |
| 136 | 197 |
| 137 void UnassignIndexes(); | 198 void UnassignIndexes(); |
| 138 void DefaultAssignIndexes(); | 199 void DefaultAssignIndexes(); |
| 139 void AssignRemainingIndexes(); | 200 void AssignRemainingIndexes(); |
| 140 | 201 |
| 141 // Looks up abs32 label. Returns null if none found. | 202 // Looks up abs32 label. Returns null if none found. |
| 142 Label* FindAbs32Label(RVA rva); | 203 Label* FindAbs32Label(RVA rva); |
| 143 | 204 |
| 144 // Looks up rel32 label. Returns null if none found. | 205 // Looks up rel32 label. Returns null if none found. |
| 145 Label* FindRel32Label(RVA rva); | 206 Label* FindRel32Label(RVA rva); |
| 146 | 207 |
| 147 std::unique_ptr<EncodedProgram> Encode() const; | 208 std::unique_ptr<EncodedProgram> Encode() const; |
| 148 | 209 |
| 149 // For each |instruction| in |instructions_|, looks up its opcode from | 210 // 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 | 211 // |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., | 212 // |instruction|'s label. We assume that |handler_map| has correct keys, i.e., |
| 152 // opcodes for an instruction that have label. | 213 // opcodes for an instruction that have label. |
| 153 void HandleInstructionLabels(const LabelHandlerMap& handler_map) const; | 214 void HandleInstructionLabels(const LabelHandlerMap& handler_map) const; |
| 154 | 215 |
| 216 // Returns via |ret| the InstructionCountReceptor instance owned by |this|. | |
| 217 // Must only be called once. Returns true on success. | |
| 218 CheckBool CreateInstructionCountReceptor(InstructionCountReceptor** ret); | |
|
grt (UTC plus 2)
2016/11/07 09:36:17
consumers of these methods don't need to know the
huangs
2016/11/07 19:46:52
Move implementations entirely into .cc file.
| |
| 219 | |
| 220 // Returns via |ret| the InstructionStoreReceptor instance owned by |this|. | |
| 221 // Must only be called once, and only after CreateInstructionCountReceptor() | |
| 222 // has been called. Returns true on success. | |
| 223 CheckBool CreateInstructionStoreReceptor(InstructionStoreReceptor** ret); | |
| 224 | |
| 155 private: | 225 private: |
| 226 using InstructionVector = NoThrowBuffer<Instruction*>; | |
| 227 | |
| 156 using ScopedInstruction = | 228 using ScopedInstruction = |
| 157 std::unique_ptr<Instruction, UncheckedDeleter<Instruction>>; | 229 std::unique_ptr<Instruction, UncheckedDeleter<Instruction>>; |
| 158 | 230 |
| 231 friend InstructionStoreReceptor; | |
| 232 | |
| 233 // Instructions will be assembled in the order they are emitted. | |
| 234 | |
| 235 // TODO(huangs): Implement these in InstructionStoreReceptor. | |
| 236 | |
| 237 // Generates an entire base relocation table. | |
| 238 CheckBool EmitPeRelocs() WARN_UNUSED_RESULT; | |
| 239 | |
| 240 // Generates an ELF style relocation table for X86. | |
| 241 CheckBool EmitElfRelocation() WARN_UNUSED_RESULT; | |
| 242 | |
| 243 // Generates an ELF style relocation table for ARM. | |
| 244 CheckBool EmitElfARMRelocation() WARN_UNUSED_RESULT; | |
| 245 | |
| 246 // Following instruction will be assembled at address 'rva'. | |
| 247 CheckBool EmitOrigin(RVA rva) WARN_UNUSED_RESULT; | |
| 248 | |
| 249 // Generates a single byte of data or machine instruction. | |
| 250 CheckBool EmitSingleByte(uint8_t byte) WARN_UNUSED_RESULT; | |
| 251 | |
| 252 // Generates multiple bytes of data or machine instructions. | |
| 253 CheckBool EmitMultipleBytes(const uint8_t* bytes, | |
| 254 size_t len) WARN_UNUSED_RESULT; | |
| 255 | |
| 256 // Generates a 4-byte relative reference to address of 'label'. | |
| 257 CheckBool EmitRel32(Label* label) WARN_UNUSED_RESULT; | |
| 258 | |
| 259 // Generates a 4-byte relative reference to address of 'label' for ARM. | |
| 260 CheckBool EmitRel32ARM(uint16_t op, | |
| 261 Label* label, | |
| 262 const uint8_t* arm_op, | |
| 263 uint16_t op_size) WARN_UNUSED_RESULT; | |
| 264 | |
| 265 // Generates a 4-byte absolute reference to address of 'label'. | |
| 266 CheckBool EmitAbs32(Label* label) WARN_UNUSED_RESULT; | |
| 267 | |
| 268 // Generates an 8-byte absolute reference to address of 'label'. | |
| 269 CheckBool EmitAbs64(Label* label) WARN_UNUSED_RESULT; | |
| 270 | |
| 159 ExecutableType kind_; | 271 ExecutableType kind_; |
| 160 | 272 |
| 161 CheckBool Emit(ScopedInstruction instruction) WARN_UNUSED_RESULT; | 273 CheckBool Emit(ScopedInstruction instruction) WARN_UNUSED_RESULT; |
| 162 CheckBool EmitShared(Instruction* instruction) WARN_UNUSED_RESULT; | 274 CheckBool EmitShared(Instruction* instruction) WARN_UNUSED_RESULT; |
| 163 | 275 |
| 164 static const int kLabelLowerLimit; | 276 static const int kLabelLowerLimit; |
| 165 | 277 |
| 166 // Looks up a label or creates a new one. Might return NULL. | 278 // Looks up a label or creates a new one. Might return NULL. |
| 167 Label* FindLabel(RVA rva, RVAToLabel* labels); | 279 Label* FindLabel(RVA rva, RVAToLabel* labels); |
| 168 | 280 |
| 169 // Helper methods for the public versions. | 281 // Helper methods for the public versions. |
| 170 static void UnassignIndexes(RVAToLabel* labels); | 282 static void UnassignIndexes(RVAToLabel* labels); |
| 171 static void DefaultAssignIndexes(RVAToLabel* labels); | 283 static void DefaultAssignIndexes(RVAToLabel* labels); |
| 172 static void AssignRemainingIndexes(RVAToLabel* labels); | 284 static void AssignRemainingIndexes(RVAToLabel* labels); |
| 173 | 285 |
| 174 // Sharing instructions that emit a single byte saves a lot of space. | 286 // Sharing instructions that emit a single byte saves a lot of space. |
| 175 Instruction* GetByteInstruction(uint8_t byte); | 287 Instruction* GetByteInstruction(uint8_t byte); |
| 176 std::unique_ptr<Instruction* [], base::FreeDeleter> byte_instruction_cache_; | 288 std::unique_ptr<Instruction* [], base::FreeDeleter> byte_instruction_cache_; |
| 177 | 289 |
| 178 uint64_t image_base_; // Desired or mandated base address of image. | 290 uint64_t image_base_; // Desired or mandated base address of image. |
| 179 | 291 |
| 180 InstructionVector instructions_; // All the instructions in program. | 292 InstructionVector instructions_; // All the instructions in program. |
| 181 | 293 |
| 182 // Storage and lookup of Labels associated with target addresses. We use | 294 // Storage and lookup of Labels associated with target addresses. We use |
| 183 // separate abs32 and rel32 labels. | 295 // separate abs32 and rel32 labels. |
| 184 LabelManager abs32_label_manager_; | 296 LabelManager abs32_label_manager_; |
| 185 LabelManager rel32_label_manager_; | 297 LabelManager rel32_label_manager_; |
| 186 | 298 |
| 299 std::unique_ptr<InstructionCountReceptor> count_receptor_; | |
| 300 std::unique_ptr<InstructionStoreReceptor> store_receptor_; | |
| 301 | |
| 187 DISALLOW_COPY_AND_ASSIGN(AssemblyProgram); | 302 DISALLOW_COPY_AND_ASSIGN(AssemblyProgram); |
| 188 }; | 303 }; |
| 189 | 304 |
| 190 // Converts |program| into encoded form, returning it as |*output|. | 305 // Converts |program| into encoded form, returning it as |*output|. |
| 191 // Returns C_OK if succeeded, otherwise returns an error status and sets | 306 // Returns C_OK if succeeded, otherwise returns an error status and sets |
| 192 // |*output| to null. | 307 // |*output| to null. |
| 193 Status Encode(const AssemblyProgram& program, | 308 Status Encode(const AssemblyProgram& program, |
| 194 std::unique_ptr<EncodedProgram>* output); | 309 std::unique_ptr<EncodedProgram>* output); |
| 195 | 310 |
| 196 } // namespace courgette | 311 } // namespace courgette |
| 197 | 312 |
| 198 #endif // COURGETTE_ASSEMBLY_PROGRAM_H_ | 313 #endif // COURGETTE_ASSEMBLY_PROGRAM_H_ |
| OLD | NEW |