1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "slicer/bytecode_encoder.h"
18 #include "slicer/common.h"
19 #include "slicer/chronometer.h"
20
21 #include <assert.h>
22
23 namespace lir {
24
25 // Pack a 16bit word: 00AA
Pack_Z_8(dex::u4 a)26 static dex::u2 Pack_Z_8(dex::u4 a) {
27 dex::u2 fa = (a & 0xff);
28 SLICER_CHECK(fa == a);
29 return fa;
30 }
31
32 // Pack a 16bit word: AABB
Pack_8_8(dex::u4 a,dex::u4 b)33 static dex::u2 Pack_8_8(dex::u4 a, dex::u4 b) {
34 dex::u2 fa = (a & 0xff);
35 SLICER_CHECK(fa == a);
36 dex::u2 fb = (b & 0xff);
37 SLICER_CHECK(fb == b);
38 return (fa << 8) | fb;
39 }
40
41 // Pack a 16bit word: ABCC
Pack_4_4_8(dex::u4 a,dex::u4 b,dex::u4 c)42 static dex::u2 Pack_4_4_8(dex::u4 a, dex::u4 b, dex::u4 c) {
43 dex::u2 fa = (a & 0xf);
44 SLICER_CHECK(fa == a);
45 dex::u2 fb = (b & 0xf);
46 SLICER_CHECK(fb == b);
47 dex::u2 fc = (c & 0xff);
48 SLICER_CHECK(fc == c);
49 return (fa << 12) | (fb << 8) | fc;
50 }
51
52 // Pack a 16bit word: ABCD
Pack_4_4_4_4(dex::u4 a,dex::u4 b,dex::u4 c,dex::u4 d)53 static dex::u2 Pack_4_4_4_4(dex::u4 a, dex::u4 b, dex::u4 c, dex::u4 d) {
54 dex::u2 fa = (a & 0xf);
55 SLICER_CHECK(fa == a);
56 dex::u2 fb = (b & 0xf);
57 SLICER_CHECK(fb == b);
58 dex::u2 fc = (c & 0xf);
59 SLICER_CHECK(fc == c);
60 dex::u2 fd = (d & 0xf);
61 SLICER_CHECK(fd == d);
62 return (fa << 12) | (fb << 8) | (fc << 4) | fd;
63 }
64
65 // Pack a 16bit word: AAAA
Pack_16(dex::u4 a)66 static dex::u2 Pack_16(dex::u4 a) {
67 dex::u2 fa = (a & 0xffff);
68 SLICER_CHECK(fa == a);
69 return fa;
70 }
71
72 // Trim a 4bit signed integer, making sure we're not discarding significant bits
Trim_S0(dex::u4 value)73 static dex::u4 Trim_S0(dex::u4 value) {
74 dex::u4 trim = value & 0xf;
75 SLICER_CHECK(dex::u4(dex::s4(trim << 28) >> 28) == value);
76 return trim;
77 }
78
79 // Trim a 8bit signed integer, making sure we're not discarding significant bits
Trim_S1(dex::u4 value)80 static dex::u4 Trim_S1(dex::u4 value) {
81 dex::u4 trim = value & 0xff;
82 SLICER_CHECK(dex::u4(dex::s4(trim << 24) >> 24) == value);
83 return trim;
84 }
85
86 // Trim a 16bit signed integer, making sure we're not discarding significant bits
Trim_S2(dex::u4 value)87 static dex::u4 Trim_S2(dex::u4 value) {
88 dex::u4 trim = value & 0xffff;
89 SLICER_CHECK(dex::u4(dex::s4(trim << 16) >> 16) == value);
90 return trim;
91 }
92
93 // Returns a register operand, checking the match between format and type
94 // (register fields can encode either a single 32bit vreg or a wide 64bit vreg pair)
GetRegA(const Bytecode * bytecode,int index)95 static dex::u4 GetRegA(const Bytecode* bytecode, int index) {
96 auto verify_flags = dex::GetVerifyFlagsFromOpcode(bytecode->opcode);
97 return (verify_flags & dex::kVerifyRegAWide) != 0
98 ? bytecode->CastOperand<VRegPair>(index)->base_reg
99 : bytecode->CastOperand<VReg>(index)->reg;
100 }
101
102 // Returns a register operand, checking the match between format and type
103 // (register fields can encode either a single 32bit vreg or a wide 64bit vreg pair)
GetRegB(const Bytecode * bytecode,int index)104 static dex::u4 GetRegB(const Bytecode* bytecode, int index) {
105 auto verify_flags = dex::GetVerifyFlagsFromOpcode(bytecode->opcode);
106 return (verify_flags & dex::kVerifyRegBWide) != 0
107 ? bytecode->CastOperand<VRegPair>(index)->base_reg
108 : bytecode->CastOperand<VReg>(index)->reg;
109 }
110
111 // Returns a register operand, checking the match between format and type
112 // (register fields can encode either a single 32bit vreg or a wide 64bit vreg pair)
GetRegC(const Bytecode * bytecode,int index)113 static dex::u4 GetRegC(const Bytecode* bytecode, int index) {
114 auto verify_flags = dex::GetVerifyFlagsFromOpcode(bytecode->opcode);
115 return (verify_flags & dex::kVerifyRegCWide) != 0
116 ? bytecode->CastOperand<VRegPair>(index)->base_reg
117 : bytecode->CastOperand<VReg>(index)->reg;
118 }
119
120 // Encode one instruction into a .dex bytecode
121 //
122 // NOTE: the formats and the operand notation is documented here:
123 // https://source.android.com/devices/tech/dalvik/instruction-formats.html
124 //
Visit(Bytecode * bytecode)125 bool BytecodeEncoder::Visit(Bytecode* bytecode) {
126 bytecode->offset = offset_;
127 dex::Opcode opcode = bytecode->opcode;
128
129 // Unconditionally replace short (8bit) branches with
130 // medium-range (16bit) branches. This should cover 99.999% of
131 // the cases and it avoids a more complex branch length handling.
132 if (opcode == dex::OP_GOTO) {
133 opcode = dex::OP_GOTO_16;
134 }
135
136 auto buff_offset = bytecode_.size();
137 auto format = dex::GetFormatFromOpcode(opcode);
138
139 switch (format) {
140 case dex::k10x: // op
141 {
142 SLICER_CHECK(bytecode->operands.size() == 0);
143 bytecode_.Push<dex::u2>(Pack_Z_8(opcode));
144 } break;
145
146 case dex::k12x: // op vA, vB
147 {
148 SLICER_CHECK(bytecode->operands.size() == 2);
149 dex::u4 vA = GetRegA(bytecode, 0);
150 dex::u4 vB = GetRegB(bytecode, 1);
151 bytecode_.Push<dex::u2>(Pack_4_4_8(vB, vA, opcode));
152 } break;
153
154 case dex::k22x: // op vAA, vBBBB
155 {
156 SLICER_CHECK(bytecode->operands.size() == 2);
157 dex::u4 vA = GetRegA(bytecode, 0);
158 dex::u4 vB = GetRegB(bytecode, 1);
159 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
160 bytecode_.Push<dex::u2>(Pack_16(vB));
161 } break;
162
163 case dex::k32x: // op vAAAA, vBBBB
164 {
165 SLICER_CHECK(bytecode->operands.size() == 2);
166 dex::u4 vA = GetRegA(bytecode, 0);
167 dex::u4 vB = GetRegB(bytecode, 1);
168 bytecode_.Push<dex::u2>(Pack_Z_8(opcode));
169 bytecode_.Push<dex::u2>(Pack_16(vA));
170 bytecode_.Push<dex::u2>(Pack_16(vB));
171 } break;
172
173 case dex::k11n: // op vA, #+B
174 {
175 SLICER_CHECK(bytecode->operands.size() == 2);
176 dex::u4 vA = GetRegA(bytecode, 0);
177 dex::u4 B = Trim_S0(bytecode->CastOperand<Const32>(1)->u.u4_value);
178 bytecode_.Push<dex::u2>(Pack_4_4_8(B, vA, opcode));
179 } break;
180
181 case dex::k21s: // op vAA, #+BBBB
182 {
183 SLICER_CHECK(bytecode->operands.size() == 2);
184 dex::u4 vA = GetRegA(bytecode, 0);
185 dex::u4 B = Trim_S2(bytecode->CastOperand<Const32>(1)->u.u4_value);
186 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
187 bytecode_.Push<dex::u2>(Pack_16(B));
188 } break;
189
190 case dex::k11x: // op vAA
191 {
192 SLICER_CHECK(bytecode->operands.size() == 1);
193 dex::u4 vA = GetRegA(bytecode, 0);
194 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
195 } break;
196
197 case dex::k31i: // op vAA, #+BBBBBBBB
198 {
199 SLICER_CHECK(bytecode->operands.size() == 2);
200 dex::u4 vA = GetRegA(bytecode, 0);
201 dex::u4 B = bytecode->CastOperand<Const32>(1)->u.u4_value;
202 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
203 bytecode_.Push<dex::u2>(Pack_16(B & 0xffff));
204 bytecode_.Push<dex::u2>(Pack_16(B >> 16));
205 } break;
206
207 case dex::k20t: // op +AAAA
208 {
209 SLICER_CHECK(bytecode->operands.size() == 1);
210 auto label = bytecode->CastOperand<CodeLocation>(0)->label;
211 dex::u4 A = 0;
212 if (label->offset != kInvalidOffset) {
213 assert(label->offset <= offset_);
214 A = label->offset - offset_;
215 SLICER_CHECK(A != 0);
216 SLICER_CHECK((A >> 16) == 0xffff); // TODO: out of range!
217 } else {
218 fixups_.push_back(LabelFixup(offset_, label, true));
219 }
220 bytecode_.Push<dex::u2>(Pack_Z_8(opcode));
221 bytecode_.Push<dex::u2>(Pack_16(A & 0xffff));
222 } break;
223
224 case dex::k30t: // op +AAAAAAAA
225 {
226 SLICER_CHECK(bytecode->operands.size() == 1);
227 auto label = bytecode->CastOperand<CodeLocation>(0)->label;
228 dex::u4 A = 0;
229 if (label->offset != kInvalidOffset) {
230 // NOTE: goto/32 can branch to itself
231 assert(label->offset <= offset_);
232 A = label->offset - offset_;
233 } else {
234 fixups_.push_back(LabelFixup(offset_, label, false));
235 }
236 bytecode_.Push<dex::u2>(Pack_Z_8(opcode));
237 bytecode_.Push<dex::u2>(Pack_16(A & 0xffff));
238 bytecode_.Push<dex::u2>(Pack_16(A >> 16));
239 } break;
240
241 case dex::k21t: // op vAA, +BBBB
242 {
243 SLICER_CHECK(bytecode->operands.size() == 2);
244 dex::u4 vA = GetRegA(bytecode, 0);
245 auto label = bytecode->CastOperand<CodeLocation>(1)->label;
246 dex::u4 B = 0;
247 if (label->offset != kInvalidOffset) {
248 assert(label->offset <= offset_);
249 B = label->offset - offset_;
250 SLICER_CHECK(B != 0);
251 SLICER_CHECK((B >> 16) == 0xffff); // TODO: out of range!
252 } else {
253 fixups_.push_back(LabelFixup(offset_, label, true));
254 }
255 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
256 bytecode_.Push<dex::u2>(Pack_16(B & 0xffff));
257 } break;
258
259 case dex::k22t: // op vA, vB, +CCCC
260 {
261 SLICER_CHECK(bytecode->operands.size() == 3);
262 dex::u4 vA = GetRegA(bytecode, 0);
263 dex::u4 vB = GetRegB(bytecode, 1);
264 auto label = bytecode->CastOperand<CodeLocation>(2)->label;
265 dex::u4 C = 0;
266 if (label->offset != kInvalidOffset) {
267 assert(label->offset <= offset_);
268 C = label->offset - offset_;
269 SLICER_CHECK(C != 0);
270 SLICER_CHECK((C >> 16) == 0xffff); // TODO: out of range!
271 } else {
272 fixups_.push_back(LabelFixup(offset_, label, true));
273 }
274 bytecode_.Push<dex::u2>(Pack_4_4_8(vB, vA, opcode));
275 bytecode_.Push<dex::u2>(Pack_16(C & 0xffff));
276 } break;
277
278 case dex::k31t: // op vAA, +BBBBBBBB
279 {
280 SLICER_CHECK(bytecode->operands.size() == 2);
281 dex::u4 vA = GetRegA(bytecode, 0);
282 auto label = bytecode->CastOperand<CodeLocation>(1)->label;
283 dex::u4 B = 0;
284 if (label->offset != kInvalidOffset) {
285 assert(label->offset <= offset_);
286 B = label->offset - offset_;
287 SLICER_CHECK(B != 0);
288 } else {
289 fixups_.push_back(LabelFixup(offset_, label, false));
290 }
291 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
292 bytecode_.Push<dex::u2>(Pack_16(B & 0xffff));
293 bytecode_.Push<dex::u2>(Pack_16(B >> 16));
294 } break;
295
296 case dex::k23x: // op vAA, vBB, vCC
297 {
298 SLICER_CHECK(bytecode->operands.size() == 3);
299 dex::u4 vA = GetRegA(bytecode, 0);
300 dex::u4 vB = GetRegB(bytecode, 1);
301 dex::u4 vC = GetRegC(bytecode, 2);
302 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
303 bytecode_.Push<dex::u2>(Pack_8_8(vC, vB));
304 } break;
305
306 case dex::k22b: // op vAA, vBB, #+CC
307 {
308 SLICER_CHECK(bytecode->operands.size() == 3);
309 dex::u4 vA = GetRegA(bytecode, 0);
310 dex::u4 vB = GetRegB(bytecode, 1);
311 dex::u4 C = Trim_S1(bytecode->CastOperand<Const32>(2)->u.u4_value);
312 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
313 bytecode_.Push<dex::u2>(Pack_8_8(C, vB));
314 } break;
315
316 case dex::k22s: // op vA, vB, #+CCCC
317 {
318 SLICER_CHECK(bytecode->operands.size() == 3);
319 dex::u4 vA = GetRegA(bytecode, 0);
320 dex::u4 vB = GetRegB(bytecode, 1);
321 dex::u4 C = Trim_S2(bytecode->CastOperand<Const32>(2)->u.u4_value);
322 bytecode_.Push<dex::u2>(Pack_4_4_8(vB, vA, opcode));
323 bytecode_.Push<dex::u2>(Pack_16(C));
324 } break;
325
326 case dex::k22c: // op vA, vB, thing@CCCC
327 {
328 SLICER_CHECK(bytecode->operands.size() == 3);
329 dex::u4 vA = GetRegA(bytecode, 0);
330 dex::u4 vB = GetRegB(bytecode, 1);
331 dex::u4 C = bytecode->CastOperand<IndexedOperand>(2)->index;
332 bytecode_.Push<dex::u2>(Pack_4_4_8(vB, vA, opcode));
333 bytecode_.Push<dex::u2>(Pack_16(C));
334 } break;
335
336 case dex::k21c: // op vAA, thing@BBBB
337 {
338 SLICER_CHECK(bytecode->operands.size() == 2);
339 dex::u4 vA = GetRegA(bytecode, 0);
340 dex::u4 B = bytecode->CastOperand<IndexedOperand>(1)->index;
341 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
342 bytecode_.Push<dex::u2>(Pack_16(B));
343 } break;
344
345 case dex::k31c: // op vAA, string@BBBBBBBB
346 {
347 SLICER_CHECK(bytecode->operands.size() == 2);
348 dex::u4 vA = GetRegA(bytecode, 0);
349 dex::u4 B = bytecode->CastOperand<IndexedOperand>(1)->index;
350 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
351 bytecode_.Push<dex::u2>(Pack_16(B & 0xffff));
352 bytecode_.Push<dex::u2>(Pack_16(B >> 16));
353 } break;
354
355 case dex::k35c: // op {vC,vD,vE,vF,vG}, thing@BBBB
356 {
357 SLICER_CHECK(bytecode->operands.size() == 2);
358 const auto& regs = bytecode->CastOperand<VRegList>(0)->registers;
359 dex::u4 B = bytecode->CastOperand<IndexedOperand>(1)->index;
360 dex::u4 A = regs.size();
361 dex::u4 C = (A > 0) ? regs[0] : 0;
362 dex::u4 D = (A > 1) ? regs[1] : 0;
363 dex::u4 E = (A > 2) ? regs[2] : 0;
364 dex::u4 F = (A > 3) ? regs[3] : 0;
365 dex::u4 G = (A > 4) ? regs[4] : 0;
366 bytecode_.Push<dex::u2>(Pack_4_4_8(A, G, opcode));
367 bytecode_.Push<dex::u2>(Pack_16(B));
368 bytecode_.Push<dex::u2>(Pack_4_4_4_4(F, E, D, C));
369
370 // keep track of the outs_count
371 if ((dex::GetFlagsFromOpcode(opcode) & dex::kInvoke) != 0) {
372 outs_count_ = std::max(outs_count_, A);
373 }
374 } break;
375
376 case dex::k3rc: // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
377 {
378 SLICER_CHECK(bytecode->operands.size() == 2);
379 auto vreg_range = bytecode->CastOperand<VRegRange>(0);
380 dex::u4 A = vreg_range->count;
381 dex::u4 B = bytecode->CastOperand<IndexedOperand>(1)->index;
382 dex::u4 C = vreg_range->base_reg;
383 bytecode_.Push<dex::u2>(Pack_8_8(A, opcode));
384 bytecode_.Push<dex::u2>(Pack_16(B));
385 bytecode_.Push<dex::u2>(Pack_16(C));
386
387 // keep track of the outs_count
388 if ((dex::GetFlagsFromOpcode(opcode) & dex::kInvoke) != 0) {
389 outs_count_ = std::max(outs_count_, A);
390 }
391 } break;
392
393 case dex::k51l: // op vAA, #+BBBBBBBBBBBBBBBB
394 {
395 SLICER_CHECK(bytecode->operands.size() == 2);
396 dex::u4 vA = GetRegA(bytecode, 0);
397 dex::u8 B = bytecode->CastOperand<Const64>(1)->u.u8_value;
398 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
399 bytecode_.Push<dex::u2>(Pack_16((B >> 0) & 0xffff));
400 bytecode_.Push<dex::u2>(Pack_16((B >> 16) & 0xffff));
401 bytecode_.Push<dex::u2>(Pack_16((B >> 32) & 0xffff));
402 bytecode_.Push<dex::u2>(Pack_16((B >> 48) & 0xffff));
403 } break;
404
405 case dex::k21h: // op vAA, #+BBBB0000[00000000]
406 SLICER_CHECK(bytecode->operands.size() == 2);
407 switch (opcode) {
408 case dex::OP_CONST_HIGH16: {
409 dex::u4 vA = GetRegA(bytecode, 0);
410 dex::u4 B = bytecode->CastOperand<Const32>(1)->u.u4_value >> 16;
411 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
412 bytecode_.Push<dex::u2>(Pack_16(B));
413 } break;
414
415 case dex::OP_CONST_WIDE_HIGH16: {
416 dex::u4 vA = GetRegA(bytecode, 0);
417 dex::u4 B = bytecode->CastOperand<Const64>(1)->u.u8_value >> 48;
418 bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
419 bytecode_.Push<dex::u2>(Pack_16(B));
420 } break;
421
422 default:
423 SLICER_FATAL("Unexpected fmt21h opcode: 0x%02x", opcode);
424 }
425 break;
426
427 default:
428 SLICER_FATAL("Unexpected format: 0x%02x", format);
429 }
430
431 SLICER_CHECK(bytecode_.size() - buff_offset == 2 * GetWidthFromFormat(format));
432 offset_ += GetWidthFromFormat(format);
433 return true;
434 }
435
Visit(PackedSwitchPayload * packed_switch)436 bool BytecodeEncoder::Visit(PackedSwitchPayload* packed_switch) {
437 SLICER_CHECK(offset_ % 2 == 0);
438
439 // keep track of the switches
440 packed_switch->offset = offset_;
441 auto& instr = packed_switches_[offset_];
442 SLICER_CHECK(instr == nullptr);
443 instr = packed_switch;
444
445 // we're going to fix up the offsets in a later pass
446 auto orig_size = bytecode_.size();
447 bytecode_.Push<dex::u2>(dex::kPackedSwitchSignature);
448 bytecode_.Push<dex::u2>(Pack_16(packed_switch->targets.size()));
449 bytecode_.Push<dex::s4>(packed_switch->first_key);
450 for (size_t i = 0; i < packed_switch->targets.size(); ++i) {
451 bytecode_.Push<dex::u4>(0);
452 }
453
454 // offset is in 16bit units, not bytes
455 offset_ += (bytecode_.size() - orig_size) / 2;
456
457 return true;
458 }
459
Visit(SparseSwitchPayload * sparse_switch)460 bool BytecodeEncoder::Visit(SparseSwitchPayload* sparse_switch) {
461 SLICER_CHECK(offset_ % 2 == 0);
462
463 // keep track of the switches
464 sparse_switch->offset = offset_;
465 auto& instr = sparse_switches_[offset_];
466 SLICER_CHECK(instr == nullptr);
467 instr = sparse_switch;
468
469 // we're going to fix up the offsets in a later pass
470 auto orig_size = bytecode_.size();
471 bytecode_.Push<dex::u2>(dex::kSparseSwitchSignature);
472 bytecode_.Push<dex::u2>(Pack_16(sparse_switch->switch_cases.size()));
473 for (const auto& switch_case : sparse_switch->switch_cases) {
474 bytecode_.Push<dex::s4>(switch_case.key);
475 }
476 for (size_t i = 0; i < sparse_switch->switch_cases.size(); ++i) {
477 bytecode_.Push<dex::u4>(0);
478 }
479 offset_ += (bytecode_.size() - orig_size) / 2;
480
481 return true;
482 }
483
Visit(ArrayData * array_data)484 bool BytecodeEncoder::Visit(ArrayData* array_data) {
485 SLICER_CHECK(offset_ % 2 == 0);
486
487 array_data->offset = offset_;
488 auto orig_size = bytecode_.size();
489 // kArrayDataSignature is already included by array_data->data
490 // (no need to emit here)
491 bytecode_.Push(array_data->data);
492 offset_ += (bytecode_.size() - orig_size) / 2;
493 return true;
494 }
495
Visit(Label * label)496 bool BytecodeEncoder::Visit(Label* label) {
497 // aligned label?
498 if (label->aligned && offset_ % 2 == 1) {
499 bytecode_.Push<dex::u2>(dex::OP_NOP);
500 ++offset_;
501 }
502
503 label->offset = offset_;
504 return true;
505 }
506
Visit(DbgInfoHeader * dbg_header)507 bool BytecodeEncoder::Visit(DbgInfoHeader* dbg_header) {
508 dbg_header->offset = offset_;
509 return true;
510 }
511
Visit(DbgInfoAnnotation * dbg_annotation)512 bool BytecodeEncoder::Visit(DbgInfoAnnotation* dbg_annotation) {
513 dbg_annotation->offset = offset_;
514 return true;
515 }
516
Visit(TryBlockBegin * try_begin)517 bool BytecodeEncoder::Visit(TryBlockBegin* try_begin) {
518 try_begin->offset = offset_;
519 return true;
520 }
521
Visit(TryBlockEnd * try_end)522 bool BytecodeEncoder::Visit(TryBlockEnd* try_end) {
523 try_end->offset = offset_;
524 return true;
525 }
526
FixupSwitchOffsets()527 void BytecodeEncoder::FixupSwitchOffsets() {
528 dex::u2* const begin = bytecode_.ptr<dex::u2>(0);
529 dex::u2* const end = begin + bytecode_.size() / 2;
530 dex::u2* ptr = begin;
531 while (ptr < end) {
532 const auto opcode = dex::OpcodeFromBytecode(*ptr);
533 const auto offset = ptr - begin;
534 if (opcode == dex::OP_PACKED_SWITCH) {
535 auto dex_instr = dex::DecodeInstruction(ptr);
536 FixupPackedSwitch(offset, offset + dex::s4(dex_instr.vB));
537 } else if (opcode == dex::OP_SPARSE_SWITCH) {
538 auto dex_instr = dex::DecodeInstruction(ptr);
539 FixupSparseSwitch(offset, offset + dex::s4(dex_instr.vB));
540 }
541 auto isize = dex::GetWidthFromBytecode(ptr);
542 SLICER_CHECK(isize > 0);
543 ptr += isize;
544 }
545 SLICER_CHECK(ptr == end);
546 }
547
FixupPackedSwitch(dex::u4 base_offset,dex::u4 payload_offset)548 void BytecodeEncoder::FixupPackedSwitch(dex::u4 base_offset,
549 dex::u4 payload_offset) {
550 auto instr = packed_switches_[payload_offset];
551 SLICER_CHECK(instr != nullptr);
552
553 auto payload = bytecode_.ptr<dex::PackedSwitchPayload>(payload_offset * 2);
554 SLICER_CHECK(payload->ident == dex::kPackedSwitchSignature);
555 SLICER_CHECK(reinterpret_cast<dex::u1*>(payload->targets + payload->size) <=
556 bytecode_.data() + bytecode_.size());
557
558 for (int i = 0; i < payload->size; ++i) {
559 auto label = instr->targets[i];
560 assert(label->offset != kInvalidOffset);
561 payload->targets[i] = label->offset - base_offset;
562 }
563 }
564
FixupSparseSwitch(dex::u4 base_offset,dex::u4 payload_offset)565 void BytecodeEncoder::FixupSparseSwitch(dex::u4 base_offset,
566 dex::u4 payload_offset) {
567 auto instr = sparse_switches_[payload_offset];
568 SLICER_CHECK(instr != nullptr);
569
570 auto payload = bytecode_.ptr<dex::SparseSwitchPayload>(payload_offset * 2);
571 SLICER_CHECK(payload->ident == dex::kSparseSwitchSignature);
572
573 dex::s4* const targets = payload->data + payload->size;
574 SLICER_CHECK(reinterpret_cast<dex::u1*>(targets + payload->size) <=
575 bytecode_.data() + bytecode_.size());
576
577 for (int i = 0; i < payload->size; ++i) {
578 auto label = instr->switch_cases[i].target;
579 assert(label->offset != kInvalidOffset);
580 targets[i] = label->offset - base_offset;
581 }
582 }
583
FixupLabels()584 void BytecodeEncoder::FixupLabels() {
585 for (const LabelFixup& fixup : fixups_) {
586 dex::u4 label_offset = fixup.label->offset;
587 assert(label_offset != kInvalidOffset);
588 assert(label_offset > fixup.offset);
589 dex::u4 rel_offset = label_offset - fixup.offset;
590 SLICER_CHECK(rel_offset != 0);
591 dex::u2* instr = bytecode_.ptr<dex::u2>(fixup.offset * 2);
592 if (fixup.short_fixup) {
593 // TODO: explicit out-of-range check
594 assert(instr[1] == 0);
595 instr[1] = Pack_16(rel_offset);
596 } else {
597 assert(instr[1] == 0);
598 assert(instr[2] == 0);
599 instr[1] = Pack_16(rel_offset & 0xffff);
600 instr[2] = Pack_16(rel_offset >> 16);
601 }
602 }
603 }
604
Encode(ir::Code * ir_code,std::shared_ptr<ir::DexFile> dex_ir)605 void BytecodeEncoder::Encode(ir::Code* ir_code, std::shared_ptr<ir::DexFile> dex_ir) {
606 SLICER_CHECK(bytecode_.empty());
607 SLICER_CHECK(offset_ == 0);
608 SLICER_CHECK(outs_count_ == 0);
609
610 packed_switches_.clear();
611 sparse_switches_.clear();
612
613 // reset all instruction offsets
614 for (auto instr : instructions_) {
615 instr->offset = kInvalidOffset;
616 }
617
618 // generate the .dex bytecodes
619 for (auto instr : instructions_) {
620 instr->Accept(this);
621 }
622
623 // no more appending (read & write is ok)
624 bytecode_.Seal(2);
625
626 FixupLabels();
627 FixupSwitchOffsets();
628
629 // update ir::Code
630 ir_code->instructions = slicer::ArrayView<const dex::u2>(
631 bytecode_.ptr<dex::u2>(0), bytecode_.size() / 2);
632 ir_code->outs_count = outs_count_;
633
634 // attach the new bytecode
635 dex_ir->AttachBuffer(std::move(bytecode_));
636 }
637
638 } // namespace lir
639