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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « courgette/assembly_program.h ('k') | courgette/courgette.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 #include <memory> 11 #include <memory>
12 #include <utility> 12 #include <utility>
13 #include <vector> 13 #include <vector>
14 14
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/macros.h" 16 #include "base/macros.h"
17 #include "courgette/courgette.h" 17 #include "courgette/courgette.h"
18 #include "courgette/encoded_program.h" 18 #include "courgette/encoded_program.h"
19 19
20 namespace courgette { 20 namespace courgette {
21 21
22 namespace { 22 namespace {
23 23
24 // Sets the current address for the emitting instructions. 24 // AssemblyProgram stores a sequence of instructions. The main uses are:
25 class OriginInstruction : public Instruction { 25 // - Serialization (write): InstructionStoreReceptor::Emit*() produces and
26 // serializes instructions into AssemblyProgram::instruction_raw_data_.
27 // - Encode (read): AssemblyProgram::Encode() iterates over serialized
28 // instructions and sends them to EncodedProgram.
29 // - Label extraction (read): AssemblyProgram::HandleInstructionLabels()
30 // iterates over serialized instructions and process only instructions with
31 // Labels.
32
33 /******** Instruction ********/
34
35 // Each instruction type (AssemblyOp::OP) has a corresponding class, and these
36 // classes have a common base class (Instruction). To simplify serialization,
37 // we want to write entire objects into buffer using pointer casting. However,
38 // the naive approach has 2 problems:
39 // (1) C++ struct can add padding, which wastes space.
40 // (2) Virtual function usage adds bloat to object size.
41 // Problem (1) is solved using #pragma pack() directives. Problem 2 is solved
42 // by decoupling storage (Data* structs) from behavior (Instruction* classes).
43
44 // Instruction interfaces that don't use templates. Instead of directly storing
45 // data, Instruction provides a "view" into a provided buffer, and keeps a
46 // "cursor" pointer to access the data. The base interface is only used by
47 // "read" use cases (encode & label extraction).
48 class Instruction {
26 public: 49 public:
27 explicit OriginInstruction(RVA rva) : Instruction(ORIGIN, 0), rva_(rva) {} 50 Instruction() = default;
28 RVA origin_rva() const { return rva_; } 51 virtual ~Instruction() = default;
52
53 // All data payload for inherited classes of Instruction.
54 #pragma pack(push, 1)
55 // If we nest these classes then we won't be able to use initializer list.
56 struct Data {
57 AssemblyOp::OP op;
58 };
59
60 struct DataWithRVA {
61 AssemblyOp::OP op;
62 RVA rva;
63 };
64
65 struct DataWithExecutableType {
66 AssemblyOp::OP op;
67 ExecutableType exe_type;
68 };
69
70 struct DataWithByte {
71 AssemblyOp::OP op;
72 uint8_t byte;
73 };
74
75 struct DataWithBytesAndSize {
76 AssemblyOp::OP op;
77 const uint8_t* bytes;
78 serialized_size_t size;
79 };
80
81 struct DataWithLabel {
82 AssemblyOp::OP op;
83 Label* label;
84 };
85
86 struct DataWithLabelAndARMRel32 {
87 AssemblyOp::OP op;
88 Label* label;
89 uint16_t compressed_op;
90 const uint8_t* arm_op; // TODO(huangs): Looks unused? Remove.
91 uint16_t op_size; // TODO(huangs): Looks unused? Remove.
92 };
93 #pragma pack(pop)
94
95 // Getters for basic info.
96 virtual AssemblyOp::OP GetOp() const = 0;
97 virtual size_t GetSize() const = 0;
98
99 // If the instruction located at |it| has a Label, returns it. Otherwise
100 // returns null.
101 virtual Label* ReadLabel(AssemblyRawDataVector::const_iterator it) const {
102 return nullptr;
103 }
104
105 // Sends the instruction to |encoded|, possibly using config from |prog|.
106 virtual bool Encode(AssemblyRawDataVector::const_iterator it,
107 EncodedProgram* encoded) const = 0;
108
29 private: 109 private:
30 RVA rva_; 110 DISALLOW_COPY_AND_ASSIGN(Instruction);
31 }; 111 };
32 112
33 // Emits an entire PE base relocation table. 113 /******** InstructionImpl ********/
34 class PeRelocsInstruction : public Instruction { 114
115 // Intermediate Instruction class using templates.
116 template <int OP_USE, typename DATA_T>
117 class InstructionImpl : public Instruction {
35 public: 118 public:
36 PeRelocsInstruction() : Instruction(MAKEPERELOCS) {} 119 using This = InstructionImpl<OP_USE, DATA_T>;
37 }; 120
38 121 static constexpr AssemblyOp::OP kOpUse = static_cast<AssemblyOp::OP>(OP_USE);
39 // Emits an ELF relocation table. 122 static constexpr size_t kSize = sizeof(DATA_T);
40 class ElfRelocsInstruction : public Instruction { 123
41 public: 124 InstructionImpl() {}
42 ElfRelocsInstruction() : Instruction(MAKEELFRELOCS) {} 125 ~InstructionImpl() override = default;
43 }; 126
44 127 // Instruction:
45 // Emits an ELF ARM relocation table. 128 AssemblyOp::OP GetOp() const override { return kOpUse; }
46 class ElfARMRelocsInstruction : public Instruction { 129 size_t GetSize() const override { return kSize; }
47 public: 130 bool Encode(AssemblyRawDataVector::const_iterator it,
48 ElfARMRelocsInstruction() : Instruction(MAKEELFARMRELOCS) {} 131 EncodedProgram* encoded) const override = 0;
49 }; 132
50 133 // Allocates space at end of |raw_data|, and writes |data_in| there.
51 // Emits a single byte. 134 CheckBool Serialize(AssemblyRawDataVector* raw_data, DATA_T data_in) {
52 class ByteInstruction : public Instruction { 135 size_t pos = raw_data->size();
53 public: 136 if (!raw_data->resize(pos + kSize, 0))
54 explicit ByteInstruction(uint8_t value) : Instruction(DEFBYTE, value) {} 137 return false;
55 uint8_t byte_value() const { return info_; } 138 DCHECK(pos + sizeof(DATA_T) <= raw_data->size());
56 }; 139 *reinterpret_cast<DATA_T*>(&(*raw_data)[pos]) = data_in;
57 140 return true;
58 // Emits a single byte. 141 }
59 class BytesInstruction : public Instruction { 142
60 public:
61 BytesInstruction(const uint8_t* values, size_t len)
62 : Instruction(DEFBYTES, 0), values_(values), len_(len) {}
63 const uint8_t* byte_values() const { return values_; }
64 size_t len() const { return len_; }
65
66 private:
67 const uint8_t* values_;
68 size_t len_;
69 };
70
71 // A ABS32 to REL32 instruction emits a reference to a label's address.
72 class InstructionWithLabel : public Instruction {
73 public:
74 InstructionWithLabel(OP op, Label* label)
75 : Instruction(op, 0), label_(label) {
76 if (label == NULL) NOTREACHED();
77 }
78 Label* label() const { return label_; }
79 protected: 143 protected:
80 Label* label_; 144 const DATA_T* SeekRead(AssemblyRawDataVector::const_iterator it) const {
81 }; 145 return reinterpret_cast<const DATA_T*>(&(*it));
82 146 }
83 // An ARM REL32 instruction emits a reference to a label's address and 147 };
84 // a specially-compressed ARM op. 148
85 class InstructionWithLabelARM : public InstructionWithLabel { 149 /******** InstructionWithLabel ********/
86 public: 150
87 InstructionWithLabelARM(OP op, 151 // Common code for the "Label extraction" use case.
88 uint16_t compressed_op, 152 template <int OP_USE, typename DATA_T>
89 Label* label, 153 class InstructionWithLabel : public InstructionImpl<OP_USE, DATA_T> {
90 const uint8_t* arm_op, 154 // Instruction:
91 uint16_t op_size) 155 Label* ReadLabel(AssemblyRawDataVector::const_iterator it) const override {
92 : InstructionWithLabel(op, label), 156 return SeekRead(it)->label;
93 compressed_op_(compressed_op), 157 }
94 arm_op_(arm_op), 158 };
95 op_size_(op_size) { 159
96 if (label == NULL) NOTREACHED(); 160 /******** Instruction*, one for each AssemblyOp:OP value ********/
97 } 161
98 uint16_t compressed_op() const { return compressed_op_; } 162 struct InstructionMakePERelocs
99 const uint8_t* arm_op() const { return arm_op_; } 163 : public InstructionImpl<AssemblyOp::MAKEPERELOCS,
100 uint16_t op_size() const { return op_size_; } 164 Instruction::DataWithExecutableType> {
101 165 bool Encode(AssemblyRawDataVector::const_iterator it,
102 private: 166 EncodedProgram* encoded) const override {
103 uint16_t compressed_op_; 167 return encoded->AddPeMakeRelocs(SeekRead(it)->exe_type);
104 const uint8_t* arm_op_; 168 }
105 uint16_t op_size_; 169 static InstructionMakePERelocs instance;
106 }; 170 };
171 InstructionMakePERelocs InstructionMakePERelocs::instance;
172
173 struct InstructionMakeELFRelocs
174 : public InstructionImpl<AssemblyOp::MAKEELFRELOCS, Instruction::Data> {
175 bool Encode(AssemblyRawDataVector::const_iterator it,
176 EncodedProgram* encoded) const override {
177 return encoded->AddElfMakeRelocs();
178 }
179 static InstructionMakeELFRelocs instance;
180 };
181 InstructionMakeELFRelocs InstructionMakeELFRelocs::instance;
182
183 struct InstructionMakeELFARMRelocs
184 : public InstructionImpl<AssemblyOp::MAKEELFARMRELOCS, Instruction::Data> {
185 bool Encode(AssemblyRawDataVector::const_iterator it,
186 EncodedProgram* encoded) const override {
187 return encoded->AddElfARMMakeRelocs();
188 }
189 static InstructionMakeELFARMRelocs instance;
190 };
191 InstructionMakeELFARMRelocs InstructionMakeELFARMRelocs::instance;
192
193 struct InstructionOrigin
194 : public InstructionImpl<AssemblyOp::ORIGIN, Instruction::DataWithRVA> {
195 bool Encode(AssemblyRawDataVector::const_iterator it,
196 EncodedProgram* encoded) const override {
197 return encoded->AddOrigin(SeekRead(it)->rva);
198 }
199 static InstructionOrigin instance;
200 };
201 InstructionOrigin InstructionOrigin::instance;
202
203 struct InstructionSingleByte
204 : public InstructionImpl<AssemblyOp::SINGLEBYTE,
205 Instruction::DataWithByte> {
206 bool Encode(AssemblyRawDataVector::const_iterator it,
207 EncodedProgram* encoded) const override {
208 return encoded->AddCopy(1, &SeekRead(it)->byte);
209 }
210 static InstructionSingleByte instance;
211 };
212 InstructionSingleByte InstructionSingleByte::instance;
213
214 struct InstructionMultipleBytes
215 : public InstructionImpl<AssemblyOp::MULTIPLEBYTES,
216 Instruction::DataWithBytesAndSize> {
217 bool Encode(AssemblyRawDataVector::const_iterator it,
218 EncodedProgram* encoded) const override {
219 const auto* cursor = SeekRead(it);
220 return encoded->AddCopy(cursor->size, cursor->bytes);
221 }
222 static InstructionMultipleBytes instance;
223 };
224 InstructionMultipleBytes InstructionMultipleBytes::instance;
225
226 struct InstructionRel32
227 : public InstructionWithLabel<AssemblyOp::REL32,
228 Instruction::DataWithLabel> {
229 bool Encode(AssemblyRawDataVector::const_iterator it,
230 EncodedProgram* encoded) const override {
231 return encoded->AddRel32(SeekRead(it)->label->index_);
232 }
233 static InstructionRel32 instance;
234 };
235 InstructionRel32 InstructionRel32::instance;
236
237 struct InstructionRel32ARM
238 : public InstructionWithLabel<AssemblyOp::REL32ARM,
239 Instruction::DataWithLabelAndARMRel32> {
240 bool Encode(AssemblyRawDataVector::const_iterator it,
241 EncodedProgram* encoded) const override {
242 const auto* cursor = SeekRead(it);
243 return encoded->AddRel32ARM(cursor->compressed_op, cursor->label->index_);
244 }
245 static InstructionRel32ARM instance;
246 };
247 InstructionRel32ARM InstructionRel32ARM::instance;
248
249 struct InstructionAbs32
250 : public InstructionWithLabel<AssemblyOp::ABS32,
251 Instruction::DataWithLabel> {
252 bool Encode(AssemblyRawDataVector::const_iterator it,
253 EncodedProgram* encoded) const override {
254 return encoded->AddAbs32(SeekRead(it)->label->index_);
255 }
256 static InstructionAbs32 instance;
257 };
258 InstructionAbs32 InstructionAbs32::instance;
259
260 struct InstructionAbs64
261 : public InstructionWithLabel<AssemblyOp::ABS64,
262 Instruction::DataWithLabel> {
263 bool Encode(AssemblyRawDataVector::const_iterator it,
264 EncodedProgram* encoded) const override {
265 return encoded->AddAbs64(SeekRead(it)->label->index_);
266 }
267 static InstructionAbs64 instance;
268 };
269 InstructionAbs64 InstructionAbs64::instance;
270
271 /******** Utility Functions ********/
272
273 // A collection of reusable Instruction instances.
274 Instruction* FindInstruction(AssemblyOp::OP op) {
275 switch (op) {
276 case InstructionOrigin::kOpUse:
277 return &InstructionOrigin::instance;
278 case InstructionMakePERelocs::kOpUse:
279 return &InstructionMakePERelocs::instance;
280 case InstructionMakeELFRelocs::kOpUse:
281 return &InstructionMakeELFRelocs::instance;
282 case InstructionSingleByte::kOpUse:
283 return &InstructionSingleByte::instance;
284 case InstructionRel32::kOpUse:
285 return &InstructionRel32::instance;
286 case InstructionAbs32::kOpUse:
287 return &InstructionAbs32::instance;
288 case InstructionRel32ARM::kOpUse:
289 return &InstructionRel32ARM::instance;
290 case InstructionMakeELFARMRelocs::kOpUse:
291 return &InstructionMakeELFARMRelocs::instance;
292 case InstructionMultipleBytes::kOpUse:
293 return &InstructionMultipleBytes::instance;
294 case InstructionAbs64::kOpUse:
295 return &InstructionAbs64::instance;
296 }
297 NOTREACHED();
298 return nullptr;
299 }
107 300
108 /******** InstructionCountReceptor ********/ 301 /******** InstructionCountReceptor ********/
109 302
110 // An InstructionReceptor that counts space occupied by emitted instructions. 303 // An InstructionReceptor to count space occupied by emitted instructions.
111 class InstructionCountReceptor : public InstructionReceptor { 304 class InstructionCountReceptor : public InstructionReceptor {
112 public: 305 public:
113 InstructionCountReceptor() = default; 306 InstructionCountReceptor() = default;
114 307
115 size_t size() const { return size_; } 308 size_t size() const { return size_; }
116 309
117 // InstructionReceptor: 310 // InstructionReceptor:
118 // TODO(huangs): 2016/11: Populate these with size_ += ... 311 CheckBool EmitPeRelocs() { return Add<InstructionMakePERelocs>(); }
119 CheckBool EmitPeRelocs() override { return true; } 312 CheckBool EmitElfRelocation() { return Add<InstructionMakeELFRelocs>(); }
120 CheckBool EmitElfRelocation() override { return true; } 313 CheckBool EmitElfARMRelocation() {
121 CheckBool EmitElfARMRelocation() override { return true; } 314 return Add<InstructionMakeELFARMRelocs>();
122 CheckBool EmitOrigin(RVA rva) override { return true; } 315 }
123 CheckBool EmitSingleByte(uint8_t byte) override { return true; } 316 CheckBool EmitOrigin(RVA rva) { return Add<InstructionOrigin>(); }
124 CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) override { 317 CheckBool EmitSingleByte(uint8_t byte) {
318 return Add<InstructionSingleByte>();
319 }
320 CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) {
321 return Add<InstructionMultipleBytes>();
322 }
323 CheckBool EmitRel32(Label* label) { return Add<InstructionRel32>(); }
324 CheckBool EmitRel32ARM(uint16_t compressed_op,
325 Label* label,
326 const uint8_t* arm_op,
327 uint16_t op_size) {
328 return Add<InstructionRel32ARM>();
329 }
330 CheckBool EmitAbs32(Label* label) { return Add<InstructionAbs32>(); }
331 CheckBool EmitAbs64(Label* label) { return Add<InstructionAbs64>(); }
332
333 private:
334 template <typename T>
335 inline bool Add() {
336 size_ += T::kSize;
125 return true; 337 return true;
126 } 338 }
127 CheckBool EmitRel32(Label* label) override { return true; }
128 CheckBool EmitRel32ARM(uint16_t op,
129 Label* label,
130 const uint8_t* arm_op,
131 uint16_t op_size) override {
132 return true;
133 }
134 CheckBool EmitAbs32(Label* label) override { return true; }
135 CheckBool EmitAbs64(Label* label) override { return true; }
136 339
137 private:
138 size_t size_ = 0; 340 size_t size_ = 0;
139 341
140 DISALLOW_COPY_AND_ASSIGN(InstructionCountReceptor); 342 DISALLOW_COPY_AND_ASSIGN(InstructionCountReceptor);
141 }; 343 };
142 344
143 /******** InstructionStoreReceptor ********/ 345 /******** InstructionStoreReceptor ********/
144 346
145 // An InstructionReceptor that stores emitted instructions. 347 // An InstructionReceptor to store emitted instructions.
146 class InstructionStoreReceptor : public InstructionReceptor { 348 class InstructionStoreReceptor : public InstructionReceptor {
147 public: 349 public:
148 explicit InstructionStoreReceptor(AssemblyProgram* program) 350 InstructionStoreReceptor(ExecutableType exe_type,
149 : program_(program) { 351 AssemblyRawDataVector* raw_data)
150 CHECK(program_); 352 : exe_type_(exe_type), raw_data_(raw_data) {}
151 }
152
153 // TODO(huangs): 2016/11: Add Reserve().
154 353
155 // InstructionReceptor: 354 // InstructionReceptor:
156 // TODO(huangs): 2016/11: Replace stub with implementation. 355 CheckBool EmitPeRelocs() {
157 CheckBool EmitPeRelocs() override { return program_->EmitPeRelocs(); } 356 InstructionMakePERelocs instr;
158 CheckBool EmitElfRelocation() override { 357 return instr.Serialize(raw_data_, {instr.GetOp(), exe_type_});
159 return program_->EmitElfRelocation();
160 } 358 }
161 CheckBool EmitElfARMRelocation() override { 359 CheckBool EmitElfRelocation() {
162 return program_->EmitElfARMRelocation(); 360 InstructionMakeELFRelocs instr;
361 return instr.Serialize(raw_data_, {instr.GetOp()});
163 } 362 }
164 CheckBool EmitOrigin(RVA rva) override { return program_->EmitOrigin(rva); } 363 CheckBool EmitElfARMRelocation() {
165 CheckBool EmitSingleByte(uint8_t byte) override { 364 InstructionMakeELFARMRelocs instr;
166 return program_->EmitSingleByte(byte); 365 return instr.Serialize(raw_data_, {instr.GetOp()});
167 } 366 }
168 CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) override { 367 CheckBool EmitOrigin(RVA rva) {
169 return program_->EmitMultipleBytes(bytes, len); 368 InstructionOrigin instr;
369 return instr.Serialize(raw_data_, {instr.GetOp(), rva});
170 } 370 }
171 CheckBool EmitRel32(Label* label) override { 371 CheckBool EmitSingleByte(uint8_t byte) {
172 return program_->EmitRel32(label); 372 InstructionSingleByte instr;
373 return instr.Serialize(raw_data_, {instr.GetOp(), byte});
173 } 374 }
174 CheckBool EmitRel32ARM(uint16_t op, 375 CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) {
376 InstructionMultipleBytes instr;
377 return instr.Serialize(
378 raw_data_, {instr.GetOp(), bytes, static_cast<serialized_size_t>(len)});
379 }
380 CheckBool EmitRel32(Label* label) {
381 InstructionRel32 instr;
382 return instr.Serialize(raw_data_, {instr.GetOp(), label});
383 }
384 CheckBool EmitRel32ARM(uint16_t compressed_op,
175 Label* label, 385 Label* label,
176 const uint8_t* arm_op, 386 const uint8_t* arm_op,
177 uint16_t op_size) override { 387 uint16_t op_size) {
178 return program_->EmitRel32ARM(op, label, arm_op, op_size); 388 InstructionRel32ARM instr;
389 // Note that |label| is moved before |compressed_op|.
390 return instr.Serialize(
391 raw_data_, {instr.GetOp(), label, compressed_op, arm_op, op_size});
179 } 392 }
180 CheckBool EmitAbs32(Label* label) override { 393 CheckBool EmitAbs32(Label* label) {
181 return program_->EmitAbs32(label); 394 InstructionAbs32 instr;
395 return instr.Serialize(raw_data_, {instr.GetOp(), label});
182 } 396 }
183 CheckBool EmitAbs64(Label* label) override { 397 CheckBool EmitAbs64(Label* label) {
184 return program_->EmitAbs64(label); 398 InstructionAbs64 instr;
399 return instr.Serialize(raw_data_, {instr.GetOp(), label});
185 } 400 }
186 401
187 private: 402 private:
188 AssemblyProgram* program_; 403 // Executable type for PE relocation.
404 const ExecutableType exe_type_;
405
406 // Storage of raw instruction data, owned by this instance's owner.
407 AssemblyRawDataVector* raw_data_;
189 408
190 DISALLOW_COPY_AND_ASSIGN(InstructionStoreReceptor); 409 DISALLOW_COPY_AND_ASSIGN(InstructionStoreReceptor);
191 }; 410 };
192 411
193 } // namespace 412 } // namespace
194 413
195 /******** AssemblyProgram ********/ 414 /******** AssemblyProgram ********/
196 415
197 AssemblyProgram::AssemblyProgram(ExecutableType kind) 416 AssemblyProgram::AssemblyProgram(ExecutableType kind) : kind_(kind) {}
198 : kind_(kind), image_base_(0) {
199 }
200
201 AssemblyProgram::~AssemblyProgram() {
202 for (size_t i = 0; i < instructions_.size(); ++i) {
203 Instruction* instruction = instructions_[i];
204 if (instruction->op() != DEFBYTE) // Owned by byte_instruction_cache_.
205 UncheckedDelete(instruction);
206 }
207 if (byte_instruction_cache_.get()) {
208 for (size_t i = 0; i < 256; ++i)
209 UncheckedDelete(byte_instruction_cache_[i]);
210 }
211 }
212
213 CheckBool AssemblyProgram::EmitPeRelocs() {
214 return Emit(ScopedInstruction(UncheckedNew<PeRelocsInstruction>()));
215 }
216
217 CheckBool AssemblyProgram::EmitElfRelocation() {
218 return Emit(ScopedInstruction(UncheckedNew<ElfRelocsInstruction>()));
219 }
220
221 CheckBool AssemblyProgram::EmitElfARMRelocation() {
222 return Emit(ScopedInstruction(UncheckedNew<ElfARMRelocsInstruction>()));
223 }
224
225 CheckBool AssemblyProgram::EmitOrigin(RVA rva) {
226 return Emit(ScopedInstruction(UncheckedNew<OriginInstruction>(rva)));
227 }
228
229 CheckBool AssemblyProgram::EmitSingleByte(uint8_t byte) {
230 return EmitShared(GetByteInstruction(byte));
231 }
232
233 CheckBool AssemblyProgram::EmitMultipleBytes(const uint8_t* bytes, size_t len) {
234 return Emit(ScopedInstruction(UncheckedNew<BytesInstruction>(bytes, len)));
235 }
236
237 CheckBool AssemblyProgram::EmitRel32(Label* label) {
238 return Emit(
239 ScopedInstruction(UncheckedNew<InstructionWithLabel>(REL32, label)));
240 }
241
242 CheckBool AssemblyProgram::EmitRel32ARM(uint16_t op,
243 Label* label,
244 const uint8_t* arm_op,
245 uint16_t op_size) {
246 return Emit(ScopedInstruction(UncheckedNew<InstructionWithLabelARM>(
247 REL32ARM, op, label, arm_op, op_size)));
248 }
249
250 CheckBool AssemblyProgram::EmitAbs32(Label* label) {
251 return Emit(
252 ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS32, label)));
253 }
254
255 CheckBool AssemblyProgram::EmitAbs64(Label* label) {
256 return Emit(
257 ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS64, label)));
258 }
259 417
260 void AssemblyProgram::PrecomputeLabels(RvaVisitor* abs32_visitor, 418 void AssemblyProgram::PrecomputeLabels(RvaVisitor* abs32_visitor,
261 RvaVisitor* rel32_visitor) { 419 RvaVisitor* rel32_visitor) {
262 abs32_label_manager_.Read(abs32_visitor); 420 abs32_label_manager_.Read(abs32_visitor);
263 rel32_label_manager_.Read(rel32_visitor); 421 rel32_label_manager_.Read(rel32_visitor);
264 TrimLabels(); 422 TrimLabels();
265 } 423 }
266 424
267 // Chosen empirically to give the best reduction in payload size for 425 // Chosen empirically to give the best reduction in payload size for
268 // an update from daisy_3701.98.0 to daisy_4206.0.0. 426 // an update from daisy_3701.98.0 to daisy_4206.0.0.
(...skipping 29 matching lines...) Expand all
298 Label* AssemblyProgram::FindAbs32Label(RVA rva) { 456 Label* AssemblyProgram::FindAbs32Label(RVA rva) {
299 return abs32_label_manager_.Find(rva); 457 return abs32_label_manager_.Find(rva);
300 } 458 }
301 459
302 Label* AssemblyProgram::FindRel32Label(RVA rva) { 460 Label* AssemblyProgram::FindRel32Label(RVA rva) {
303 return rel32_label_manager_.Find(rva); 461 return rel32_label_manager_.Find(rva);
304 } 462 }
305 463
306 void AssemblyProgram::HandleInstructionLabels( 464 void AssemblyProgram::HandleInstructionLabels(
307 const AssemblyProgram::LabelHandlerMap& handler_map) const { 465 const AssemblyProgram::LabelHandlerMap& handler_map) const {
308 for (const Instruction* instruction : instructions_) { 466 auto it = instruction_raw_data_.begin();
309 LabelHandlerMap::const_iterator it = handler_map.find(instruction->op()); 467 auto end = instruction_raw_data_.end();
310 if (it != handler_map.end()) { 468 while (it < end) {
311 it->second.Run( 469 // Get the instruction from the operation.
312 static_cast<const InstructionWithLabel*>(instruction)->label()); 470 AssemblyOp::OP op = static_cast<AssemblyOp::OP>(*it);
471 Instruction* instr = FindInstruction(op);
472 DCHECK_LE(it + instr->GetSize(), end);
473
474 // If Label exists and is handled, then handle it.
475 Label* label = instr->ReadLabel(it);
476 if (label) {
477 LabelHandlerMap::const_iterator label_it = handler_map.find(op);
478 if (label_it != handler_map.end())
479 label_it->second.Run(label);
313 } 480 }
481 it += instr->GetSize();
314 } 482 }
315 } 483 }
316 484
317 CheckBool AssemblyProgram::GenerateInstructions( 485 CheckBool AssemblyProgram::GenerateInstructions(
318 const InstructionGenerator& gen) { 486 const InstructionGenerator& gen) {
487 CHECK(instruction_raw_data_.empty());
488
319 // Pass 1: Count the space needed to store instructions. 489 // Pass 1: Count the space needed to store instructions.
320 InstructionCountReceptor count_receptor; 490 InstructionCountReceptor count_receptor;
321 if (!gen.Run(this, &count_receptor)) 491 if (!gen.Run(this, &count_receptor))
322 return false; 492 return false;
323 493
494 // Reserve space for raw data, using count from Phase 1.
495 if (!instruction_raw_data_.reserve(count_receptor.size()))
496 return false;
497
324 // Pass 2: Emit all instructions to preallocated buffer (uses Phase 1 count). 498 // Pass 2: Emit all instructions to preallocated buffer (uses Phase 1 count).
325 InstructionStoreReceptor store_receptor(this); 499 InstructionStoreReceptor store_receptor(kind(), &instruction_raw_data_);
326 // TODO(huangs): 2016/11: Pass |count_receptor_->size()| to |store_receptor_| 500 if (!gen.Run(this, &store_receptor))
327 // to reserve space for raw data. 501 return false;
328 return gen.Run(this, &store_receptor);
329 }
330 502
331 CheckBool AssemblyProgram::Emit(ScopedInstruction instruction) { 503 CHECK_EQ(count_receptor.size(), instruction_raw_data_.size());
332 if (!instruction || !instructions_.push_back(instruction.get()))
333 return false;
334 // Ownership successfully passed to instructions_.
335 ignore_result(instruction.release());
336 return true; 504 return true;
337 } 505 }
338 506
339 CheckBool AssemblyProgram::EmitShared(Instruction* instruction) {
340 DCHECK(!instruction || instruction->op() == DEFBYTE);
341 return instruction && instructions_.push_back(instruction);
342 }
343
344 void AssemblyProgram::UnassignIndexes(RVAToLabel* labels) { 507 void AssemblyProgram::UnassignIndexes(RVAToLabel* labels) {
345 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) { 508 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) {
346 Label* current = p->second; 509 Label* current = p->second;
347 current->index_ = Label::kNoIndex; 510 current->index_ = Label::kNoIndex;
348 } 511 }
349 } 512 }
350 513
351 // DefaultAssignIndexes takes a set of labels and assigns indexes in increasing 514 // DefaultAssignIndexes takes a set of labels and assigns indexes in increasing
352 // address order. 515 // address order.
353 void AssemblyProgram::DefaultAssignIndexes(RVAToLabel* labels) { 516 void AssemblyProgram::DefaultAssignIndexes(RVAToLabel* labels) {
354 int index = 0; 517 int index = 0;
355 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) { 518 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) {
356 Label* current = p->second; 519 Label* current = p->second;
357 if (current->index_ != Label::kNoIndex) 520 if (current->index_ != Label::kNoIndex)
358 NOTREACHED(); 521 NOTREACHED();
359 current->index_ = index; 522 current->index_ = index;
360 ++index; 523 ++index;
361 } 524 }
362 } 525 }
363 526
364 // AssignRemainingIndexes assigns indexes to any addresses (labels) that are not 527 // AssignRemainingIndexes assigns indexes to any addresses (labels) that are not
365 // yet assigned an index. 528 // yet assigned an index.
366 void AssemblyProgram::AssignRemainingIndexes(RVAToLabel* labels) { 529 void AssemblyProgram::AssignRemainingIndexes(RVAToLabel* labels) {
367 // An address table compresses best when each index is associated with an 530 // An address table compresses best when each index is associated with an
368 // address that is slight larger than the previous index. 531 // address that is slight larger than the previous index.
369 532
370 // First see which indexes have not been used. The 'available' vector could 533 // First see which indexes have not been used. The 'available' vector could
371 // grow even bigger, but the number of addresses is a better starting size 534 // grow even bigger, but the number of addresses is a better starting size
372 // than empty. 535 // than empty.
373 std::vector<bool> available(labels->size(), true); 536 std::vector<bool> available(labels->size(), true);
374 int used = 0; 537 int used = 0;
375 538
376 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) { 539 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) {
377 int index = p->second->index_; 540 int index = p->second->index_;
378 if (index != Label::kNoIndex) { 541 if (index != Label::kNoIndex) {
379 while (static_cast<size_t>(index) >= available.size()) 542 while (static_cast<size_t>(index) >= available.size())
380 available.push_back(true); 543 available.push_back(true);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 } 614 }
452 615
453 std::unique_ptr<EncodedProgram> AssemblyProgram::Encode() const { 616 std::unique_ptr<EncodedProgram> AssemblyProgram::Encode() const {
454 std::unique_ptr<EncodedProgram> encoded(new EncodedProgram()); 617 std::unique_ptr<EncodedProgram> encoded(new EncodedProgram());
455 618
456 encoded->set_image_base(image_base_); 619 encoded->set_image_base(image_base_);
457 620
458 if (!encoded->ImportLabels(abs32_label_manager_, rel32_label_manager_)) 621 if (!encoded->ImportLabels(abs32_label_manager_, rel32_label_manager_))
459 return nullptr; 622 return nullptr;
460 623
461 for (size_t i = 0; i < instructions_.size(); ++i) { 624 auto it = instruction_raw_data_.begin();
462 Instruction* instruction = instructions_[i]; 625 auto end = instruction_raw_data_.end();
626 while (it < end) {
627 // Get the instruction from the operation.
628 AssemblyOp::OP op = static_cast<AssemblyOp::OP>(*it);
629 Instruction* instr = FindInstruction(op);
630 DCHECK_LE(it + instr->GetSize(), end);
463 631
464 switch (instruction->op()) { 632 instr->Encode(it, encoded.get());
465 case ORIGIN: { 633 it += instr->GetSize();
466 OriginInstruction* org = static_cast<OriginInstruction*>(instruction);
467 if (!encoded->AddOrigin(org->origin_rva()))
468 return nullptr;
469 break;
470 }
471 case DEFBYTE: {
472 uint8_t b = static_cast<ByteInstruction*>(instruction)->byte_value();
473 if (!encoded->AddCopy(1, &b))
474 return nullptr;
475 break;
476 }
477 case DEFBYTES: {
478 const uint8_t* byte_values =
479 static_cast<BytesInstruction*>(instruction)->byte_values();
480 size_t len = static_cast<BytesInstruction*>(instruction)->len();
481
482 if (!encoded->AddCopy(len, byte_values))
483 return nullptr;
484 break;
485 }
486 case REL32: {
487 Label* label = static_cast<InstructionWithLabel*>(instruction)->label();
488 if (!encoded->AddRel32(label->index_))
489 return nullptr;
490 break;
491 }
492 case REL32ARM: {
493 Label* label =
494 static_cast<InstructionWithLabelARM*>(instruction)->label();
495 uint16_t compressed_op =
496 static_cast<InstructionWithLabelARM*>(instruction)->compressed_op();
497 if (!encoded->AddRel32ARM(compressed_op, label->index_))
498 return nullptr;
499 break;
500 }
501 case ABS32: {
502 Label* label = static_cast<InstructionWithLabel*>(instruction)->label();
503 if (!encoded->AddAbs32(label->index_))
504 return nullptr;
505 break;
506 }
507 case ABS64: {
508 Label* label = static_cast<InstructionWithLabel*>(instruction)->label();
509 if (!encoded->AddAbs64(label->index_))
510 return nullptr;
511 break;
512 }
513 case MAKEPERELOCS: {
514 if (!encoded->AddPeMakeRelocs(kind_))
515 return nullptr;
516 break;
517 }
518 case MAKEELFRELOCS: {
519 if (!encoded->AddElfMakeRelocs())
520 return nullptr;
521 break;
522 }
523 case MAKEELFARMRELOCS: {
524 if (!encoded->AddElfARMMakeRelocs())
525 return nullptr;
526 break;
527 }
528 default: {
529 NOTREACHED() << "Unknown Insn OP kind";
530 }
531 }
532 } 634 }
533
534 return encoded; 635 return encoded;
535 } 636 }
536 637
537 Instruction* AssemblyProgram::GetByteInstruction(uint8_t byte) {
538 if (!byte_instruction_cache_) {
539 Instruction** ram = nullptr;
540 if (!base::UncheckedMalloc(sizeof(Instruction*) * 256,
541 reinterpret_cast<void**>(&ram))) {
542 return nullptr;
543 }
544 byte_instruction_cache_.reset(ram);
545
546 for (int i = 0; i < 256; ++i) {
547 byte_instruction_cache_[i] =
548 UncheckedNew<ByteInstruction>(static_cast<uint8_t>(i));
549 if (!byte_instruction_cache_[i]) {
550 for (int j = 0; j < i; ++j)
551 UncheckedDelete(byte_instruction_cache_[j]);
552 byte_instruction_cache_.reset();
553 return nullptr;
554 }
555 }
556 }
557
558 return byte_instruction_cache_[byte];
559 }
560
561 //////////////////////////////////////////////////////////////////////////////// 638 ////////////////////////////////////////////////////////////////////////////////
562 639
563 Status Encode(const AssemblyProgram& program, 640 Status Encode(const AssemblyProgram& program,
564 std::unique_ptr<EncodedProgram>* output) { 641 std::unique_ptr<EncodedProgram>* output) {
565 // Explicitly release any memory associated with the output before encoding. 642 // Explicitly release any memory associated with the output before encoding.
566 output->reset(); 643 output->reset();
567 644
568 *output = program.Encode(); 645 *output = program.Encode();
569 return (*output) ? C_OK : C_GENERAL_ERROR; 646 return (*output) ? C_OK : C_GENERAL_ERROR;
570 } 647 }
571 648
572 } // namespace courgette 649 } // namespace courgette
OLDNEW
« 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