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 #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 Loading... |
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 Loading... |
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 |
OLD | NEW |