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 EncodedProgram; | 26 class EncodedProgram; |
27 | 27 |
| 28 using serialized_size_t = uint32_t; |
| 29 |
| 30 // Raw data array for AssemblyData seralization. |
| 31 using AssemblyRawDataVector = NoThrowBuffer<uint8_t>; |
| 32 |
28 // Opcodes of simple assembly language | 33 // Opcodes of simple assembly language |
29 enum OP { | 34 class AssemblyOp { |
30 ORIGIN, // ORIGIN <rva> - set current address for assembly. | |
31 MAKEPERELOCS, // Generates a base relocation table. | |
32 MAKEELFRELOCS, // Generates a base relocation table. | |
33 DEFBYTE, // DEFBYTE <value> - emit a byte literal. | |
34 REL32, // REL32 <label> - emit a rel32 encoded reference to 'label'. | |
35 ABS32, // ABS32 <label> - emit an abs32 encoded reference to 'label'. | |
36 REL32ARM, // REL32ARM <c_op> <label> - arm-specific rel32 reference | |
37 MAKEELFARMRELOCS, // Generates a base relocation table. | |
38 DEFBYTES, // Emits any number of byte literals | |
39 ABS64, // ABS64 <label> - emit an abs64 encoded reference to 'label'. | |
40 LAST_OP | |
41 }; | |
42 | |
43 // Base class for instructions. Because we have so many instructions we want to | |
44 // keep them as small as possible. For this reason we avoid virtual functions. | |
45 class Instruction { | |
46 public: | 35 public: |
47 OP op() const { return static_cast<OP>(op_); } | 36 // Any change in this Update |kOpSize| |
48 | 37 enum OP : uint8_t { |
49 protected: | 38 ORIGIN, // ORIGIN <rva>: Sets current address for assembly. |
50 explicit Instruction(OP op) : op_(op), info_(0) {} | 39 MAKEPERELOCS, // Generates a base relocation table. |
51 Instruction(OP op, unsigned int info) : op_(op), info_(info) {} | 40 MAKEELFRELOCS, // Generates a base relocation table. |
52 | 41 SINGLEBYTE, // SINGLEBYTE <value>: Emits a byte literal. |
53 uint32_t op_ : 4; // A few bits to store the OP code. | 42 REL32, // REL32 <label>: Emits a rel32 encoded reference to Label. |
54 uint32_t info_ : 28; // Remaining bits in first word available to subclass. | 43 ABS32, // ABS32 <label>: Emits an abs32 encoded reference to Label. |
55 | 44 REL32ARM, // REL32ARM <c_op> <label>: ARM-specific rel32 reference. |
56 private: | 45 MAKEELFARMRELOCS, // Generates a base relocation table. |
57 DISALLOW_COPY_AND_ASSIGN(Instruction); | 46 MULTIPLEBYTES, // Emits any number of byte literals. |
| 47 ABS64, // ABS64 <label>: Emits an abs64 encoded reference to Label. |
| 48 NUM_OP |
| 49 }; |
58 }; | 50 }; |
59 | 51 |
60 // An interface to receive emitted instructions parsed from an executable. | 52 // An interface to receive emitted instructions parsed from an executable. |
61 class InstructionReceptor { | 53 class InstructionReceptor { |
62 public: | 54 public: |
63 InstructionReceptor() = default; | 55 InstructionReceptor() = default; |
64 virtual ~InstructionReceptor() = default; | 56 virtual ~InstructionReceptor() = default; |
65 | 57 |
66 // Generates an entire base relocation table. | 58 // Generates an entire base relocation table. |
67 virtual CheckBool EmitPeRelocs() = 0; | 59 virtual CheckBool EmitPeRelocs() = 0; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 // The optional step is to modify the AssemblyProgram. One form of modification | 107 // The optional step is to modify the AssemblyProgram. One form of modification |
116 // is to assign indexes in such a way as to make the EncodedProgram for this | 108 // is to assign indexes in such a way as to make the EncodedProgram for this |
117 // AssemblyProgram look more like the EncodedProgram for some other | 109 // AssemblyProgram look more like the EncodedProgram for some other |
118 // AssemblyProgram. The modification process should call UnassignIndexes, do | 110 // AssemblyProgram. The modification process should call UnassignIndexes, do |
119 // its own assignment, and then call AssignRemainingIndexes to ensure all | 111 // its own assignment, and then call AssignRemainingIndexes to ensure all |
120 // indexes are assigned. | 112 // indexes are assigned. |
121 | 113 |
122 class AssemblyProgram { | 114 class AssemblyProgram { |
123 public: | 115 public: |
124 using LabelHandler = base::Callback<void(Label*)>; | 116 using LabelHandler = base::Callback<void(Label*)>; |
125 using LabelHandlerMap = std::map<OP, LabelHandler>; | 117 using LabelHandlerMap = std::map<AssemblyOp::OP, LabelHandler>; |
126 | 118 |
127 // A callback for GenerateInstructions() to emit instructions. The first | 119 // A callback for GenerateInstructions() to emit instructions. The first |
128 // argument (AssemblyProgram*) is provided for Label-related feature access. | 120 // argument (AssemblyProgram*) is provided for Label-related feature access. |
129 // The second argument (InstructionReceptor*) is a receptor for instructions. | 121 // The second argument (InstructionReceptor*) is a receptor for instructions. |
130 // The callback (which gets called in 2 passes) should return true on success, | 122 // The callback (which gets called in 2 passes) should return true on success, |
131 // and false otherwise. | 123 // and false otherwise. |
132 using InstructionGenerator = | 124 using InstructionGenerator = |
133 base::Callback<CheckBool(AssemblyProgram*, InstructionReceptor*)>; | 125 base::Callback<CheckBool(AssemblyProgram*, InstructionReceptor*)>; |
134 | 126 |
135 explicit AssemblyProgram(ExecutableType kind); | 127 explicit AssemblyProgram(ExecutableType kind); |
136 ~AssemblyProgram(); | 128 ~AssemblyProgram() = default; |
137 | 129 |
138 ExecutableType kind() const { return kind_; } | 130 ExecutableType kind() const { return kind_; } |
139 | 131 |
140 void set_image_base(uint64_t image_base) { image_base_ = image_base; } | 132 void set_image_base(uint64_t image_base) { image_base_ = image_base; } |
141 | 133 |
142 // Traverses RVAs in |abs32_visitor| and |rel32_visitor| to precompute Labels. | 134 // Traverses RVAs in |abs32_visitor| and |rel32_visitor| to precompute Labels. |
143 void PrecomputeLabels(RvaVisitor* abs32_visitor, RvaVisitor* rel32_visitor); | 135 void PrecomputeLabels(RvaVisitor* abs32_visitor, RvaVisitor* rel32_visitor); |
144 | 136 |
145 // Removes underused Labels. Thresholds used (0 = no trimming) is | 137 // Removes underused Labels. Thresholds used (0 = no trimming) is |
146 // architecture-dependent. | 138 // architecture-dependent. |
147 void TrimLabels(); | 139 void TrimLabels(); |
148 | 140 |
149 void UnassignIndexes(); | 141 void UnassignIndexes(); |
150 void DefaultAssignIndexes(); | 142 void DefaultAssignIndexes(); |
151 void AssignRemainingIndexes(); | 143 void AssignRemainingIndexes(); |
152 | 144 |
153 // Looks up abs32 label. Returns null if none found. | 145 // Looks up abs32 label. Returns null if none found. |
154 Label* FindAbs32Label(RVA rva); | 146 Label* FindAbs32Label(RVA rva); |
155 | 147 |
156 // Looks up rel32 label. Returns null if none found. | 148 // Looks up rel32 label. Returns null if none found. |
157 Label* FindRel32Label(RVA rva); | 149 Label* FindRel32Label(RVA rva); |
158 | 150 |
159 std::unique_ptr<EncodedProgram> Encode() const; | 151 std::unique_ptr<EncodedProgram> Encode() const; |
160 | 152 |
161 // For each |instruction| in |instructions_|, looks up its opcode from | 153 // For each instruction in |raw_data_|, looks up its opcode from |handler_map| |
162 // |handler_map| for a handler. If a handler exists, invoke it by passing the | 154 // for a handler. If a handler exists, invoke it by passing the instruction's |
163 // |instruction|'s label. We assume that |handler_map| has correct keys, i.e., | 155 // label. We assume that |handler_map| has correct keys, i.e., opcodes for an |
164 // opcodes for an instruction that have label. | 156 // instruction that have label. |
165 void HandleInstructionLabels(const LabelHandlerMap& handler_map) const; | 157 void HandleInstructionLabels(const LabelHandlerMap& handler_map) const; |
166 | 158 |
167 // Calls |gen| in 2 passes to emit instructions. In pass 1 we provide a | 159 // 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 | 160 // receptor to count space requirement. In pass 2 we provide a receptor to |
169 // store instructions. | 161 // store instructions. This function can only be called once per instance. |
170 CheckBool GenerateInstructions(const InstructionGenerator& gen); | 162 CheckBool GenerateInstructions(const InstructionGenerator& gen); |
171 | 163 |
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 | |
209 private: | 164 private: |
210 using InstructionVector = NoThrowBuffer<Instruction*>; | |
211 | |
212 using ScopedInstruction = | |
213 std::unique_ptr<Instruction, UncheckedDeleter<Instruction>>; | |
214 | |
215 ExecutableType kind_; | 165 ExecutableType kind_; |
216 | 166 |
217 CheckBool Emit(ScopedInstruction instruction) WARN_UNUSED_RESULT; | |
218 CheckBool EmitShared(Instruction* instruction) WARN_UNUSED_RESULT; | |
219 | |
220 static const int kLabelLowerLimit; | 167 static const int kLabelLowerLimit; |
221 | 168 |
222 // Looks up a label or creates a new one. Might return NULL. | 169 // Looks up a label or creates a new one. Might return NULL. |
223 Label* FindLabel(RVA rva, RVAToLabel* labels); | 170 Label* FindLabel(RVA rva, RVAToLabel* labels); |
224 | 171 |
225 // Helper methods for the public versions. | 172 // Helper methods for the public versions. |
226 static void UnassignIndexes(RVAToLabel* labels); | 173 static void UnassignIndexes(RVAToLabel* labels); |
227 static void DefaultAssignIndexes(RVAToLabel* labels); | 174 static void DefaultAssignIndexes(RVAToLabel* labels); |
228 static void AssignRemainingIndexes(RVAToLabel* labels); | 175 static void AssignRemainingIndexes(RVAToLabel* labels); |
229 | 176 |
230 // Sharing instructions that emit a single byte saves a lot of space. | 177 uint64_t image_base_ = 0; // Desired or mandated base address of image. |
231 Instruction* GetByteInstruction(uint8_t byte); | |
232 std::unique_ptr<Instruction* [], base::FreeDeleter> byte_instruction_cache_; | |
233 | |
234 uint64_t image_base_; // Desired or mandated base address of image. | |
235 | |
236 InstructionVector instructions_; // All the instructions in program. | |
237 | 178 |
238 // Storage and lookup of Labels associated with target addresses. We use | 179 // Storage and lookup of Labels associated with target addresses. We use |
239 // separate abs32 and rel32 labels. | 180 // separate abs32 and rel32 labels. |
240 LabelManager abs32_label_manager_; | 181 LabelManager abs32_label_manager_; |
241 LabelManager rel32_label_manager_; | 182 LabelManager rel32_label_manager_; |
242 | 183 |
| 184 // Container of serialized instruction data. |
| 185 AssemblyRawDataVector instruction_raw_data_; |
| 186 |
243 DISALLOW_COPY_AND_ASSIGN(AssemblyProgram); | 187 DISALLOW_COPY_AND_ASSIGN(AssemblyProgram); |
244 }; | 188 }; |
245 | 189 |
246 // Converts |program| into encoded form, returning it as |*output|. | 190 // Converts |program| into encoded form, returning it as |*output|. |
247 // Returns C_OK if succeeded, otherwise returns an error status and sets | 191 // Returns C_OK if succeeded, otherwise returns an error status and sets |
248 // |*output| to null. | 192 // |*output| to null. |
249 Status Encode(const AssemblyProgram& program, | 193 Status Encode(const AssemblyProgram& program, |
250 std::unique_ptr<EncodedProgram>* output); | 194 std::unique_ptr<EncodedProgram>* output); |
251 | 195 |
252 } // namespace courgette | 196 } // namespace courgette |
253 | 197 |
254 #endif // COURGETTE_ASSEMBLY_PROGRAM_H_ | 198 #endif // COURGETTE_ASSEMBLY_PROGRAM_H_ |
OLD | NEW |