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/common.h"
18 #include "slicer/code_ir.h"
19 #include "slicer/dex_bytecode.h"
20 #include "slicer/dex_format.h"
21 #include "slicer/dex_ir.h"
22 #include "slicer/dex_leb128.h"
23 #include "slicer/bytecode_encoder.h"
24 #include "slicer/debuginfo_encoder.h"
25 #include "slicer/tryblocks_encoder.h"
26 
27 #include <assert.h>
28 #include <string.h>
29 #include <algorithm>
30 #include <cstdlib>
31 #include <type_traits>
32 #include <vector>
33 
34 namespace lir {
35 
Assemble()36 void CodeIr::Assemble() {
37   auto ir_code = ir_method->code;
38   SLICER_CHECK(ir_code != nullptr);
39 
40   // new .dex bytecode
41   //
42   // NOTE: this must be done before the debug information and
43   //   try/catch blocks since here is where we update the final offsets
44   //
45   BytecodeEncoder bytecode_encoder(instructions);
46   bytecode_encoder.Encode(ir_code, dex_ir);
47 
48   // debug information
49   if (ir_code->debug_info != nullptr) {
50     DebugInfoEncoder dbginfo_encoder(instructions);
51     dbginfo_encoder.Encode(ir_method, dex_ir);
52   }
53 
54   // try/catch blocks
55   TryBlocksEncoder try_blocks_encoder(instructions);
56   try_blocks_encoder.Encode(ir_code, dex_ir);
57 }
58 
DissasembleTryBlocks(const ir::Code * ir_code)59 void CodeIr::DissasembleTryBlocks(const ir::Code* ir_code) {
60   int nextTryBlockId = 1;
61   for (const auto& tryBlock : ir_code->try_blocks) {
62     auto try_block_begin = Alloc<TryBlockBegin>();
63     try_block_begin->id = nextTryBlockId++;
64     try_block_begin->offset = tryBlock.start_addr;
65 
66     auto try_block_end = Alloc<TryBlockEnd>();
67     try_block_end->try_begin = try_block_begin;
68     try_block_end->offset = tryBlock.start_addr + tryBlock.insn_count;
69 
70     // parse the catch handlers
71     const dex::u1* ptr =
72         ir_code->catch_handlers.ptr<dex::u1>() + tryBlock.handler_off;
73     int catchCount = dex::ReadSLeb128(&ptr);
74 
75     for (int catchIndex = 0; catchIndex < std::abs(catchCount); ++catchIndex) {
76       CatchHandler handler = {};
77 
78       // type
79       dex::u4 type_index = dex::ReadULeb128(&ptr);
80       handler.ir_type = dex_ir->types_map[type_index];
81       SLICER_CHECK(handler.ir_type != nullptr);
82 
83       // address
84       dex::u4 address = dex::ReadULeb128(&ptr);
85       handler.label = GetLabel(address);
86 
87       try_block_end->handlers.push_back(handler);
88     }
89 
90     // catch_all handler?
91     //
92     // NOTE: this is used to generate code for the "finally" blocks
93     //  (see Java Virtual Machine Specification - 3.13 "Compiling finally")
94     //
95     if (catchCount < 1) {
96       dex::u4 address = dex::ReadULeb128(&ptr);
97       try_block_end->catch_all = GetLabel(address);
98     }
99 
100     // we should have at least one handler
101     SLICER_CHECK(!try_block_end->handlers.empty() ||
102           try_block_end->catch_all != nullptr);
103 
104     try_begins_.push_back(try_block_begin);
105     try_ends_.push_back(try_block_end);
106   }
107 }
108 
DissasembleDebugInfo(const ir::DebugInfo * ir_debug_info)109 void CodeIr::DissasembleDebugInfo(const ir::DebugInfo* ir_debug_info) {
110   if (ir_debug_info == nullptr) {
111     return;
112   }
113 
114   // debug info state machine registers
115   dex::u4 address = 0;
116   int line = ir_debug_info->line_start;
117   ir::String* source_file = ir_method->decl->parent->class_def->source_file;
118 
119   // header
120   if (!ir_debug_info->param_names.empty()) {
121     auto dbg_header = Alloc<DbgInfoHeader>();
122     dbg_header->param_names = ir_debug_info->param_names;
123     dbg_header->offset = 0;
124     dbg_annotations_.push_back(dbg_header);
125   }
126 
127   // initial source file
128   {
129     auto annotation = Alloc<DbgInfoAnnotation>(dex::DBG_SET_FILE);
130     annotation->offset = 0;
131     annotation->operands.push_back(Alloc<String>(
132         source_file, source_file ? source_file->orig_index : dex::kNoIndex));
133     dbg_annotations_.push_back(annotation);
134   }
135 
136   // initial line number - redundant?
137   {
138     auto annotation = Alloc<DbgInfoAnnotation>(dex::DBG_ADVANCE_LINE);
139     annotation->offset = 0;
140     annotation->operands.push_back(Alloc<LineNumber>(line));
141     dbg_annotations_.push_back(annotation);
142   }
143 
144   // debug info annotations
145   const dex::u1* ptr = ir_debug_info->data.ptr<dex::u1>();
146   dex::u1 opcode = 0;
147   while ((opcode = *ptr++) != dex::DBG_END_SEQUENCE) {
148     DbgInfoAnnotation* annotation = nullptr;
149 
150     switch (opcode) {
151       case dex::DBG_ADVANCE_PC:
152         // addr_diff
153         address += dex::ReadULeb128(&ptr);
154         break;
155 
156       case dex::DBG_ADVANCE_LINE:
157         // line_diff
158         line += dex::ReadSLeb128(&ptr);
159         SLICER_WEAK_CHECK(line > 0);
160         break;
161 
162       case dex::DBG_START_LOCAL: {
163         annotation = Alloc<DbgInfoAnnotation>(opcode);
164 
165         // register_num
166         annotation->operands.push_back(Alloc<VReg>(dex::ReadULeb128(&ptr)));
167 
168         // name
169         dex::u4 name_index = dex::ReadULeb128(&ptr) - 1;
170         annotation->operands.push_back(GetString(name_index));
171 
172         // type
173         dex::u4 type_index = dex::ReadULeb128(&ptr) - 1;
174         annotation->operands.push_back(GetType(type_index));
175       } break;
176 
177       case dex::DBG_START_LOCAL_EXTENDED: {
178         annotation = Alloc<DbgInfoAnnotation>(opcode);
179 
180         // register_num
181         annotation->operands.push_back(Alloc<VReg>(dex::ReadULeb128(&ptr)));
182 
183         // name
184         dex::u4 name_index = dex::ReadULeb128(&ptr) - 1;
185         annotation->operands.push_back(GetString(name_index));
186 
187         // type
188         dex::u4 type_index = dex::ReadULeb128(&ptr) - 1;
189         annotation->operands.push_back(GetType(type_index));
190 
191         // signature
192         dex::u4 sig_index = dex::ReadULeb128(&ptr) - 1;
193         annotation->operands.push_back(GetString(sig_index));
194       } break;
195 
196       case dex::DBG_END_LOCAL:
197       case dex::DBG_RESTART_LOCAL:
198         annotation = Alloc<DbgInfoAnnotation>(opcode);
199         // register_num
200         annotation->operands.push_back(Alloc<VReg>(dex::ReadULeb128(&ptr)));
201         break;
202 
203       case dex::DBG_SET_PROLOGUE_END:
204         annotation = Alloc<DbgInfoAnnotation>(opcode);
205         break;
206 
207       case dex::DBG_SET_EPILOGUE_BEGIN:
208         annotation = Alloc<DbgInfoAnnotation>(opcode);
209         break;
210 
211       case dex::DBG_SET_FILE: {
212         annotation = Alloc<DbgInfoAnnotation>(opcode);
213 
214         // source file name
215         dex::u4 name_index = dex::ReadULeb128(&ptr) - 1;
216         source_file = (name_index == dex::kNoIndex)
217                           ? nullptr
218                           : dex_ir->strings_map[name_index];
219         annotation->operands.push_back(Alloc<String>(source_file, name_index));
220       } break;
221 
222       default: {
223         int adjusted_opcode = opcode - dex::DBG_FIRST_SPECIAL;
224         line += dex::DBG_LINE_BASE + (adjusted_opcode % dex::DBG_LINE_RANGE);
225         address += (adjusted_opcode / dex::DBG_LINE_RANGE);
226         SLICER_WEAK_CHECK(line > 0);
227         annotation = Alloc<DbgInfoAnnotation>(dex::DBG_ADVANCE_LINE);
228         annotation->operands.push_back(Alloc<LineNumber>(line));
229       } break;
230     }
231 
232     if (annotation != nullptr) {
233       annotation->offset = address;
234       dbg_annotations_.push_back(annotation);
235     }
236   }
237 }
238 
DissasembleBytecode(const ir::Code * ir_code)239 void CodeIr::DissasembleBytecode(const ir::Code* ir_code) {
240   const dex::u2* begin = ir_code->instructions.begin();
241   const dex::u2* end = ir_code->instructions.end();
242   const dex::u2* ptr = begin;
243 
244   while (ptr < end) {
245     auto isize = dex::GetWidthFromBytecode(ptr);
246     SLICER_CHECK(isize > 0);
247 
248     dex::u4 offset = ptr - begin;
249 
250     Instruction* instr = nullptr;
251     switch (*ptr) {
252       case dex::kPackedSwitchSignature:
253         instr = DecodePackedSwitch(ptr, offset);
254         break;
255 
256       case dex::kSparseSwitchSignature:
257         instr = DecodeSparseSwitch(ptr, offset);
258         break;
259 
260       case dex::kArrayDataSignature:
261         instr = DecodeArrayData(ptr, offset);
262         break;
263 
264       default:
265         instr = DecodeBytecode(ptr, offset);
266         break;
267     }
268 
269     instr->offset = offset;
270     instructions.push_back(instr);
271     ptr += isize;
272   }
273   SLICER_CHECK(ptr == end);
274 }
275 
FixupSwitches()276 void CodeIr::FixupSwitches() {
277   const dex::u2* begin = ir_method->code->instructions.begin();
278 
279   // packed switches
280   for (auto& fixup : packed_switches_) {
281     FixupPackedSwitch(fixup.second.instr, fixup.second.base_offset,
282                       begin + fixup.first);
283   }
284 
285   // sparse switches
286   for (auto& fixup : sparse_switches_) {
287     FixupSparseSwitch(fixup.second.instr, fixup.second.base_offset,
288                       begin + fixup.first);
289   }
290 }
291 
292 // merge a set of extra instructions into the instruction list
293 template <class I_LIST, class E_LIST>
MergeInstructions(I_LIST & instructions,const E_LIST & extra)294 static void MergeInstructions(I_LIST& instructions, const E_LIST& extra) {
295 
296   // the extra instructins must be sorted by offset
297   SLICER_CHECK(std::is_sorted(extra.begin(), extra.end(),
298                         [](const Instruction* a, const Instruction* b) {
299                           return a->offset < b->offset;
300                         }));
301 
302   auto instrIt = instructions.begin();
303   auto extraIt = extra.begin();
304 
305   while (extraIt != extra.end()) {
306     if (instrIt == instructions.end() ||
307         (*extraIt)->offset == (*instrIt)->offset) {
308       instructions.insert(instrIt, *extraIt);
309       ++extraIt;
310     } else {
311       ++instrIt;
312     }
313   }
314 }
315 
Dissasemble()316 void CodeIr::Dissasemble() {
317   nodes_.clear();
318   labels_.clear();
319 
320   try_begins_.clear();
321   try_ends_.clear();
322   dbg_annotations_.clear();
323   packed_switches_.clear();
324   sparse_switches_.clear();
325 
326   auto ir_code = ir_method->code;
327   if (ir_code == nullptr) {
328     return;
329   }
330 
331   // decode the .dex bytecodes
332   DissasembleBytecode(ir_code);
333 
334   // try/catch blocks
335   DissasembleTryBlocks(ir_code);
336 
337   // debug information
338   DissasembleDebugInfo(ir_code->debug_info);
339 
340   // fixup switches
341   FixupSwitches();
342 
343   // assign label ids
344   std::vector<Label*> tmp_labels;
345   int nextLabelId = 1;
346   for (auto& label : labels_) {
347     label.second->id = nextLabelId++;
348     tmp_labels.push_back(label.second);
349   }
350 
351   // merge the labels into the instructions stream
352   MergeInstructions(instructions, dbg_annotations_);
353   MergeInstructions(instructions, try_begins_);
354   MergeInstructions(instructions, tmp_labels);
355   MergeInstructions(instructions, try_ends_);
356 }
357 
DecodePackedSwitch(const dex::u2 *,dex::u4 offset)358 PackedSwitchPayload* CodeIr::DecodePackedSwitch(const dex::u2* /*ptr*/,
359                                          dex::u4 offset) {
360   // actual decoding is delayed to FixupPackedSwitch()
361   // (since the label offsets are relative to the referring
362   //  instruction, not the switch data)
363   SLICER_CHECK(offset % 2 == 0);
364   auto& instr = packed_switches_[offset].instr;
365   SLICER_CHECK(instr == nullptr);
366   instr = Alloc<PackedSwitchPayload>();
367   return instr;
368 }
369 
FixupPackedSwitch(PackedSwitchPayload * instr,dex::u4 base_offset,const dex::u2 * ptr)370 void CodeIr::FixupPackedSwitch(PackedSwitchPayload* instr, dex::u4 base_offset,
371                                const dex::u2* ptr) {
372   SLICER_CHECK(instr->targets.empty());
373 
374   auto dex_packed_switch = reinterpret_cast<const dex::PackedSwitchPayload*>(ptr);
375   SLICER_CHECK(dex_packed_switch->ident == dex::kPackedSwitchSignature);
376 
377   instr->first_key = dex_packed_switch->first_key;
378   for (dex::u2 i = 0; i < dex_packed_switch->size; ++i) {
379     instr->targets.push_back(
380         GetLabel(base_offset + dex_packed_switch->targets[i]));
381   }
382 }
383 
DecodeSparseSwitch(const dex::u2 *,dex::u4 offset)384 SparseSwitchPayload* CodeIr::DecodeSparseSwitch(const dex::u2* /*ptr*/,
385                                          dex::u4 offset) {
386   // actual decoding is delayed to FixupSparseSwitch()
387   // (since the label offsets are relative to the referring
388   //  instruction, not the switch data)
389   SLICER_CHECK(offset % 2 == 0);
390   auto& instr = sparse_switches_[offset].instr;
391   SLICER_CHECK(instr == nullptr);
392   instr = Alloc<SparseSwitchPayload>();
393   return instr;
394 }
395 
FixupSparseSwitch(SparseSwitchPayload * instr,dex::u4 base_offset,const dex::u2 * ptr)396 void CodeIr::FixupSparseSwitch(SparseSwitchPayload* instr, dex::u4 base_offset,
397                                const dex::u2* ptr) {
398   SLICER_CHECK(instr->switch_cases.empty());
399 
400   auto dex_sparse_switch = reinterpret_cast<const dex::SparseSwitchPayload*>(ptr);
401   SLICER_CHECK(dex_sparse_switch->ident == dex::kSparseSwitchSignature);
402 
403   auto& data = dex_sparse_switch->data;
404   auto& size = dex_sparse_switch->size;
405 
406   for (dex::u2 i = 0; i < size; ++i) {
407     SparseSwitchPayload::SwitchCase switch_case = {};
408     switch_case.key = data[i];
409     switch_case.target = GetLabel(base_offset + data[i + size]);
410     instr->switch_cases.push_back(switch_case);
411   }
412 }
413 
DecodeArrayData(const dex::u2 * ptr,dex::u4 offset)414 ArrayData* CodeIr::DecodeArrayData(const dex::u2* ptr, dex::u4 offset) {
415   auto dex_array_data = reinterpret_cast<const dex::ArrayData*>(ptr);
416   SLICER_CHECK(dex_array_data->ident == dex::kArrayDataSignature);
417   SLICER_CHECK(offset % 2 == 0);
418 
419   auto instr = Alloc<ArrayData>();
420   instr->data = slicer::MemView(ptr, dex::GetWidthFromBytecode(ptr) * 2);
421   return instr;
422 }
423 
GetRegA(const dex::Instruction & dex_instr)424 Operand* CodeIr::GetRegA(const dex::Instruction& dex_instr) {
425   auto flags = dex::GetFlagsFromOpcode(dex_instr.opcode);
426   if ((flags & dex::kInstrWideRegA) != 0) {
427     return Alloc<VRegPair>(dex_instr.vA);
428   } else {
429     return Alloc<VReg>(dex_instr.vA);
430   }
431 }
432 
GetRegB(const dex::Instruction & dex_instr)433 Operand* CodeIr::GetRegB(const dex::Instruction& dex_instr) {
434   auto flags = dex::GetFlagsFromOpcode(dex_instr.opcode);
435   if ((flags & dex::kInstrWideRegB) != 0) {
436     return Alloc<VRegPair>(dex_instr.vB);
437   } else {
438     return Alloc<VReg>(dex_instr.vB);
439   }
440 }
441 
GetRegC(const dex::Instruction & dex_instr)442 Operand* CodeIr::GetRegC(const dex::Instruction& dex_instr) {
443   auto flags = dex::GetFlagsFromOpcode(dex_instr.opcode);
444   if ((flags & dex::kInstrWideRegC) != 0) {
445     return Alloc<VRegPair>(dex_instr.vC);
446   } else {
447     return Alloc<VReg>(dex_instr.vC);
448   }
449 }
450 
DecodeBytecode(const dex::u2 * ptr,dex::u4 offset)451 Bytecode* CodeIr::DecodeBytecode(const dex::u2* ptr, dex::u4 offset) {
452   auto dex_instr = dex::DecodeInstruction(ptr);
453 
454   auto instr = Alloc<Bytecode>();
455   instr->opcode = dex_instr.opcode;
456 
457   auto index_type = dex::GetIndexTypeFromOpcode(dex_instr.opcode);
458 
459   switch (dex::GetFormatFromOpcode(dex_instr.opcode)) {
460     case dex::kFmt10x:  // op
461       break;
462 
463     case dex::kFmt12x:  // op vA, vB
464     case dex::kFmt22x:  // op vAA, vBBBB
465     case dex::kFmt32x:  // op vAAAA, vBBBB
466       instr->operands.push_back(GetRegA(dex_instr));
467       instr->operands.push_back(GetRegB(dex_instr));
468       break;
469 
470     case dex::kFmt11n:  // op vA, #+B
471     case dex::kFmt21s:  // op vAA, #+BBBB
472     case dex::kFmt31i:  // op vAA, #+BBBBBBBB
473       instr->operands.push_back(GetRegA(dex_instr));
474       instr->operands.push_back(Alloc<Const32>(dex_instr.vB));
475       break;
476 
477     case dex::kFmt11x:  // op vAA
478       instr->operands.push_back(GetRegA(dex_instr));
479       break;
480 
481     case dex::kFmt10t:  // op +AA
482     case dex::kFmt20t:  // op +AAAA
483     case dex::kFmt30t:  // op +AAAAAAAA
484     {
485       auto label = GetLabel(offset + dex::s4(dex_instr.vA));
486       instr->operands.push_back(Alloc<CodeLocation>(label));
487     } break;
488 
489     case dex::kFmt21t:  // op vAA, +BBBB
490     case dex::kFmt31t:  // op vAA, +BBBBBBBB
491     {
492       dex::u4 targetOffset = offset + dex::s4(dex_instr.vB);
493       instr->operands.push_back(GetRegA(dex_instr));
494       auto label = GetLabel(targetOffset);
495       instr->operands.push_back(Alloc<CodeLocation>(label));
496 
497       if (dex_instr.opcode == dex::OP_PACKED_SWITCH) {
498         label->aligned = true;
499         dex::u4& base_offset = packed_switches_[targetOffset].base_offset;
500         SLICER_CHECK(base_offset == kInvalidOffset);
501         base_offset = offset;
502       } else if (dex_instr.opcode == dex::OP_SPARSE_SWITCH) {
503         label->aligned = true;
504         dex::u4& base_offset = sparse_switches_[targetOffset].base_offset;
505         SLICER_CHECK(base_offset == kInvalidOffset);
506         base_offset = offset;
507       } else if (dex_instr.opcode == dex::OP_FILL_ARRAY_DATA) {
508         label->aligned = true;
509       }
510     } break;
511 
512     case dex::kFmt23x:  // op vAA, vBB, vCC
513       instr->operands.push_back(GetRegA(dex_instr));
514       instr->operands.push_back(GetRegB(dex_instr));
515       instr->operands.push_back(GetRegC(dex_instr));
516       break;
517 
518     case dex::kFmt22t:  // op vA, vB, +CCCC
519     {
520       instr->operands.push_back(GetRegA(dex_instr));
521       instr->operands.push_back(GetRegB(dex_instr));
522       auto label = GetLabel(offset + dex::s4(dex_instr.vC));
523       instr->operands.push_back(Alloc<CodeLocation>(label));
524     } break;
525 
526     case dex::kFmt22b:  // op vAA, vBB, #+CC
527     case dex::kFmt22s:  // op vA, vB, #+CCCC
528       instr->operands.push_back(GetRegA(dex_instr));
529       instr->operands.push_back(GetRegB(dex_instr));
530       instr->operands.push_back(Alloc<Const32>(dex_instr.vC));
531       break;
532 
533     case dex::kFmt22c:  // op vA, vB, thing@CCCC
534       instr->operands.push_back(GetRegA(dex_instr));
535       instr->operands.push_back(GetRegB(dex_instr));
536       instr->operands.push_back(GetIndexedOperand(index_type, dex_instr.vC));
537       break;
538 
539     case dex::kFmt21c:  // op vAA, thing@BBBB
540     case dex::kFmt31c:  // op vAA, string@BBBBBBBB
541       instr->operands.push_back(GetRegA(dex_instr));
542       instr->operands.push_back(GetIndexedOperand(index_type, dex_instr.vB));
543       break;
544 
545     case dex::kFmt35c:  // op {vC,vD,vE,vF,vG}, thing@BBBB
546     {
547       SLICER_CHECK(dex_instr.vA <= 5);
548       auto vreg_list = Alloc<VRegList>();
549       for (dex::u4 i = 0; i < dex_instr.vA; ++i) {
550         vreg_list->registers.push_back(dex_instr.arg[i]);
551       }
552       instr->operands.push_back(vreg_list);
553       instr->operands.push_back(GetIndexedOperand(index_type, dex_instr.vB));
554     } break;
555 
556     case dex::kFmt3rc:  // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
557     {
558       auto vreg_range = Alloc<VRegRange>(dex_instr.vC, dex_instr.vA);
559       instr->operands.push_back(vreg_range);
560       instr->operands.push_back(GetIndexedOperand(index_type, dex_instr.vB));
561     } break;
562 
563     case dex::kFmt21h:  // op vAA, #+BBBB0000[00000000]
564       switch (dex_instr.opcode) {
565         case dex::OP_CONST_HIGH16:
566           instr->operands.push_back(GetRegA(dex_instr));
567           instr->operands.push_back(Alloc<Const32>(dex_instr.vB << 16));
568           break;
569 
570         case dex::OP_CONST_WIDE_HIGH16:
571           instr->operands.push_back(GetRegA(dex_instr));
572           instr->operands.push_back(Alloc<Const64>(dex::u8(dex_instr.vB) << 48));
573           break;
574 
575         default:
576           SLICER_FATAL("Unexpected opcode 0x%02x", dex_instr.opcode);
577       }
578       break;
579 
580     case dex::kFmt51l:  // op vAA, #+BBBBBBBBBBBBBBBB
581       instr->operands.push_back(GetRegA(dex_instr));
582       instr->operands.push_back(Alloc<Const64>(dex_instr.vB_wide));
583       break;
584 
585     default:
586       SLICER_FATAL("Unexpected bytecode format (opcode 0x%02x)", dex_instr.opcode);
587   }
588 
589   return instr;
590 }
591 
592 // Get a indexed object (string, field, ...)
593 // (index must be valid != kNoIndex)
GetIndexedOperand(dex::InstructionIndexType index_type,dex::u4 index)594 IndexedOperand* CodeIr::GetIndexedOperand(dex::InstructionIndexType index_type,
595                                           dex::u4 index) {
596   SLICER_CHECK(index != dex::kNoIndex);
597   switch (index_type) {
598     case dex::kIndexStringRef:
599       return Alloc<String>(dex_ir->strings_map[index], index);
600 
601     case dex::kIndexTypeRef:
602       return Alloc<Type>(dex_ir->types_map[index], index);
603 
604     case dex::kIndexFieldRef:
605       return Alloc<Field>(dex_ir->fields_map[index], index);
606 
607     case dex::kIndexMethodRef:
608       return Alloc<Method>(dex_ir->methods_map[index], index);
609 
610     default:
611       SLICER_FATAL("Unexpected index type 0x%02x", index_type);
612   }
613 }
614 
615 // Get a type based on its index (potentially kNoIndex)
GetType(dex::u4 index)616 Type* CodeIr::GetType(dex::u4 index) {
617   auto ir_type = (index == dex::kNoIndex) ? nullptr : dex_ir->types_map[index];
618   return Alloc<Type>(ir_type, index);
619 }
620 
621 // Get a string based on its index (potentially kNoIndex)
GetString(dex::u4 index)622 String* CodeIr::GetString(dex::u4 index) {
623   auto ir_string = (index == dex::kNoIndex) ? nullptr : dex_ir->strings_map[index];
624   return Alloc<String>(ir_string, index);
625 }
626 
627 // Get en existing, or new label for a particular offset
GetLabel(dex::u4 offset)628 Label* CodeIr::GetLabel(dex::u4 offset) {
629   auto& p = labels_[offset];
630   if (p == nullptr) {
631     p = Alloc<Label>(offset);
632   }
633   ++p->refCount;
634   return p;
635 }
636 
637 }  // namespace lir
638