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