• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013, Google Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 package org.jf.dexlib2.writer;
33 
34 import com.google.common.collect.Ordering;
35 import com.google.common.primitives.Ints;
36 import org.jf.dexlib2.Opcode;
37 import org.jf.dexlib2.Opcodes;
38 import org.jf.dexlib2.ReferenceType;
39 import org.jf.dexlib2.iface.instruction.DualReferenceInstruction;
40 import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
41 import org.jf.dexlib2.iface.instruction.SwitchElement;
42 import org.jf.dexlib2.iface.instruction.formats.*;
43 import org.jf.dexlib2.iface.reference.*;
44 import org.jf.util.ExceptionWithContext;
45 
46 import javax.annotation.Nonnull;
47 import java.io.IOException;
48 import java.util.Comparator;
49 import java.util.List;
50 
51 public class InstructionWriter<StringRef extends StringReference, TypeRef extends TypeReference,
52         FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
53         ProtoRefKey extends MethodProtoReference, MethodHandleKey extends MethodHandleReference,
54         CallSiteKey extends CallSiteReference> {
55     @Nonnull private final Opcodes opcodes;
56     @Nonnull private final DexDataWriter writer;
57     @Nonnull private final StringSection<?, StringRef> stringSection;
58     @Nonnull private final TypeSection<?, ?, TypeRef> typeSection;
59     @Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection;
60     @Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection;
61     @Nonnull private final ProtoSection<?, ?, ProtoRefKey, ?> protoSection;
62     @Nonnull private final MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection;
63     @Nonnull private final CallSiteSection<CallSiteKey, ?> callSiteSection;
64 
65     @Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference,
66             FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
67             ProtoRefKey extends MethodProtoReference, MethodHandleKey extends MethodHandleReference,
68             CallSiteKey extends CallSiteReference>
69             InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey, MethodHandleKey, CallSiteKey>
makeInstructionWriter( @onnull Opcodes opcodes, @Nonnull DexDataWriter writer, @Nonnull StringSection<?, StringRef> stringSection, @Nonnull TypeSection<?, ?, TypeRef> typeSection, @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection, @Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection, @Nonnull MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection, @Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection)70             makeInstructionWriter(
71                 @Nonnull Opcodes opcodes,
72                 @Nonnull DexDataWriter writer,
73                 @Nonnull StringSection<?, StringRef> stringSection,
74                 @Nonnull TypeSection<?, ?, TypeRef> typeSection,
75                 @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
76                 @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
77                 @Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection,
78                 @Nonnull MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection,
79                 @Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection) {
80         return new InstructionWriter<
81                 StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey, MethodHandleKey,CallSiteKey>(
82                         opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection,
83                         methodHandleSection, callSiteSection);
84     }
85 
InstructionWriter(@onnull Opcodes opcodes, @Nonnull DexDataWriter writer, @Nonnull StringSection<?, StringRef> stringSection, @Nonnull TypeSection<?, ?, TypeRef> typeSection, @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection, @Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection, @Nonnull MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection, @Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection)86     InstructionWriter(@Nonnull Opcodes opcodes,
87                       @Nonnull DexDataWriter writer,
88                       @Nonnull StringSection<?, StringRef> stringSection,
89                       @Nonnull TypeSection<?, ?, TypeRef> typeSection,
90                       @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
91                       @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
92                       @Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection,
93                       @Nonnull MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection,
94                       @Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection) {
95         this.opcodes = opcodes;
96         this.writer = writer;
97         this.stringSection = stringSection;
98         this.typeSection = typeSection;
99         this.fieldSection = fieldSection;
100         this.methodSection = methodSection;
101         this.protoSection = protoSection;
102         this.methodHandleSection = methodHandleSection;
103         this.callSiteSection = callSiteSection;
104     }
105 
getOpcodeValue(Opcode opcode)106     private short getOpcodeValue(Opcode opcode) {
107         Short value = opcodes.getOpcodeValue(opcode);
108         if (value == null) {
109             throw new ExceptionWithContext("Instruction %s is invalid for api %d", opcode.name, opcodes.api);
110         }
111         return value;
112     }
113 
write(@onnull Instruction10t instruction)114     public void write(@Nonnull Instruction10t instruction) {
115         try {
116             writer.write(getOpcodeValue(instruction.getOpcode()));
117             writer.write(instruction.getCodeOffset());
118         } catch (IOException ex) {
119             throw new RuntimeException(ex);
120         }
121     }
122 
write(@onnull Instruction10x instruction)123     public void write(@Nonnull Instruction10x instruction) {
124         try {
125             writer.write(getOpcodeValue(instruction.getOpcode()));
126             writer.write(0);
127         } catch (IOException ex) {
128             throw new RuntimeException(ex);
129         }
130     }
131 
write(@onnull Instruction11n instruction)132     public void write(@Nonnull Instruction11n instruction) {
133         try {
134             writer.write(getOpcodeValue(instruction.getOpcode()));
135             writer.write(packNibbles(instruction.getRegisterA(), instruction.getNarrowLiteral()));
136         } catch (IOException ex) {
137             throw new RuntimeException(ex);
138         }
139     }
140 
write(@onnull Instruction11x instruction)141     public void write(@Nonnull Instruction11x instruction) {
142         try {
143             writer.write(getOpcodeValue(instruction.getOpcode()));
144             writer.write(instruction.getRegisterA());
145         } catch (IOException ex) {
146             throw new RuntimeException(ex);
147         }
148     }
149 
write(@onnull Instruction12x instruction)150     public void write(@Nonnull Instruction12x instruction) {
151         try {
152             writer.write(getOpcodeValue(instruction.getOpcode()));
153             writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB()));
154         } catch (IOException ex) {
155             throw new RuntimeException(ex);
156         }
157     }
158 
write(@onnull Instruction20bc instruction)159     public void write(@Nonnull Instruction20bc instruction) {
160         try {
161             writer.write(getOpcodeValue(instruction.getOpcode()));
162             writer.write(instruction.getVerificationError());
163             writer.writeUshort(getReferenceIndex(instruction));
164         } catch (IOException ex) {
165             throw new RuntimeException(ex);
166         }
167     }
168 
write(@onnull Instruction20t instruction)169     public void write(@Nonnull Instruction20t instruction) {
170         try {
171             writer.write(getOpcodeValue(instruction.getOpcode()));
172             writer.write(0);
173             writer.writeShort(instruction.getCodeOffset());
174         } catch (IOException ex) {
175             throw new RuntimeException(ex);
176         }
177     }
178 
write(@onnull Instruction21c instruction)179     public void write(@Nonnull Instruction21c instruction) {
180         try {
181             writer.write(getOpcodeValue(instruction.getOpcode()));
182             writer.write(instruction.getRegisterA());
183             writer.writeUshort(getReferenceIndex(instruction));
184         } catch (IOException ex) {
185             throw new RuntimeException(ex);
186         }
187     }
188 
write(@onnull Instruction21ih instruction)189     public void write(@Nonnull Instruction21ih instruction) {
190         try {
191             writer.write(getOpcodeValue(instruction.getOpcode()));
192             writer.write(instruction.getRegisterA());
193             writer.writeShort(instruction.getHatLiteral());
194         } catch (IOException ex) {
195             throw new RuntimeException(ex);
196         }
197     }
198 
write(@onnull Instruction21lh instruction)199     public void write(@Nonnull Instruction21lh instruction) {
200         try {
201             writer.write(getOpcodeValue(instruction.getOpcode()));
202             writer.write(instruction.getRegisterA());
203             writer.writeShort(instruction.getHatLiteral());
204         } catch (IOException ex) {
205             throw new RuntimeException(ex);
206         }
207     }
208 
write(@onnull Instruction21s instruction)209     public void write(@Nonnull Instruction21s instruction) {
210         try {
211             writer.write(getOpcodeValue(instruction.getOpcode()));
212             writer.write(instruction.getRegisterA());
213             writer.writeShort(instruction.getNarrowLiteral());
214         } catch (IOException ex) {
215             throw new RuntimeException(ex);
216         }
217     }
218 
write(@onnull Instruction21t instruction)219     public void write(@Nonnull Instruction21t instruction) {
220         try {
221             writer.write(getOpcodeValue(instruction.getOpcode()));
222             writer.write(instruction.getRegisterA());
223             writer.writeShort(instruction.getCodeOffset());
224         } catch (IOException ex) {
225             throw new RuntimeException(ex);
226         }
227     }
228 
write(@onnull Instruction22b instruction)229     public void write(@Nonnull Instruction22b instruction) {
230         try {
231             writer.write(getOpcodeValue(instruction.getOpcode()));
232             writer.write(instruction.getRegisterA());
233             writer.write(instruction.getRegisterB());
234             writer.write(instruction.getNarrowLiteral());
235         } catch (IOException ex) {
236             throw new RuntimeException(ex);
237         }
238     }
239 
write(@onnull Instruction22c instruction)240     public void write(@Nonnull Instruction22c instruction) {
241         try {
242             writer.write(getOpcodeValue(instruction.getOpcode()));
243             writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB()));
244             writer.writeUshort(getReferenceIndex(instruction));
245         } catch (IOException ex) {
246             throw new RuntimeException(ex);
247         }
248     }
249 
write(@onnull Instruction22cs instruction)250     public void write(@Nonnull Instruction22cs instruction) {
251         try {
252             writer.write(getOpcodeValue(instruction.getOpcode()));
253             writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB()));
254             writer.writeUshort(instruction.getFieldOffset());
255         } catch (IOException ex) {
256             throw new RuntimeException(ex);
257         }
258     }
259 
write(@onnull Instruction22s instruction)260     public void write(@Nonnull Instruction22s instruction) {
261         try {
262             writer.write(getOpcodeValue(instruction.getOpcode()));
263             writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB()));
264             writer.writeShort(instruction.getNarrowLiteral());
265         } catch (IOException ex) {
266             throw new RuntimeException(ex);
267         }
268     }
269 
write(@onnull Instruction22t instruction)270     public void write(@Nonnull Instruction22t instruction) {
271         try {
272             writer.write(getOpcodeValue(instruction.getOpcode()));
273             writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB()));
274             writer.writeShort(instruction.getCodeOffset());
275         } catch (IOException ex) {
276             throw new RuntimeException(ex);
277         }
278     }
279 
write(@onnull Instruction22x instruction)280     public void write(@Nonnull Instruction22x instruction) {
281         try {
282             writer.write(getOpcodeValue(instruction.getOpcode()));
283             writer.write(instruction.getRegisterA());
284             writer.writeUshort(instruction.getRegisterB());
285         } catch (IOException ex) {
286             throw new RuntimeException(ex);
287         }
288     }
289 
write(@onnull Instruction23x instruction)290     public void write(@Nonnull Instruction23x instruction) {
291         try {
292             writer.write(getOpcodeValue(instruction.getOpcode()));
293             writer.write(instruction.getRegisterA());
294             writer.write(instruction.getRegisterB());
295             writer.write(instruction.getRegisterC());
296         } catch (IOException ex) {
297             throw new RuntimeException(ex);
298         }
299     }
300 
write(@onnull Instruction30t instruction)301     public void write(@Nonnull Instruction30t instruction) {
302         try {
303             writer.write(getOpcodeValue(instruction.getOpcode()));
304             writer.write(0);
305             writer.writeInt(instruction.getCodeOffset());
306         } catch (IOException ex) {
307             throw new RuntimeException(ex);
308         }
309     }
310 
write(@onnull Instruction31c instruction)311     public void write(@Nonnull Instruction31c instruction) {
312         try {
313             writer.write(getOpcodeValue(instruction.getOpcode()));
314             writer.write(instruction.getRegisterA());
315             writer.writeInt(getReferenceIndex(instruction));
316         } catch (IOException ex) {
317             throw new RuntimeException(ex);
318         }
319     }
320 
write(@onnull Instruction31i instruction)321     public void write(@Nonnull Instruction31i instruction) {
322         try {
323             writer.write(getOpcodeValue(instruction.getOpcode()));
324             writer.write(instruction.getRegisterA());
325             writer.writeInt(instruction.getNarrowLiteral());
326         } catch (IOException ex) {
327             throw new RuntimeException(ex);
328         }
329     }
330 
write(@onnull Instruction31t instruction)331     public void write(@Nonnull Instruction31t instruction) {
332         try {
333             writer.write(getOpcodeValue(instruction.getOpcode()));
334             writer.write(instruction.getRegisterA());
335             writer.writeInt(instruction.getCodeOffset());
336         } catch (IOException ex) {
337             throw new RuntimeException(ex);
338         }
339     }
340 
write(@onnull Instruction32x instruction)341     public void write(@Nonnull Instruction32x instruction) {
342         try {
343             writer.write(getOpcodeValue(instruction.getOpcode()));
344             writer.write(0);
345             writer.writeUshort(instruction.getRegisterA());
346             writer.writeUshort(instruction.getRegisterB());
347         } catch (IOException ex) {
348             throw new RuntimeException(ex);
349         }
350     }
351 
write(@onnull Instruction35c instruction)352     public void write(@Nonnull Instruction35c instruction) {
353         try {
354             writer.write(getOpcodeValue(instruction.getOpcode()));
355             writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount()));
356             writer.writeUshort(getReferenceIndex(instruction));
357             writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD()));
358             writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF()));
359         } catch (IOException ex) {
360             throw new RuntimeException(ex);
361         }
362     }
363 
write(@onnull Instruction35mi instruction)364     public void write(@Nonnull Instruction35mi instruction) {
365         try {
366             writer.write(getOpcodeValue(instruction.getOpcode()));
367             writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount()));
368             writer.writeUshort(instruction.getInlineIndex());
369             writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD()));
370             writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF()));
371         } catch (IOException ex) {
372             throw new RuntimeException(ex);
373         }
374     }
375 
write(@onnull Instruction35ms instruction)376     public void write(@Nonnull Instruction35ms instruction) {
377         try {
378             writer.write(getOpcodeValue(instruction.getOpcode()));
379             writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount()));
380             writer.writeUshort(instruction.getVtableIndex());
381             writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD()));
382             writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF()));
383         } catch (IOException ex) {
384             throw new RuntimeException(ex);
385         }
386     }
387 
write(@onnull Instruction3rc instruction)388     public void write(@Nonnull Instruction3rc instruction) {
389         try {
390             writer.write(getOpcodeValue(instruction.getOpcode()));
391             writer.write(instruction.getRegisterCount());
392             writer.writeUshort(getReferenceIndex(instruction));
393             writer.writeUshort(instruction.getStartRegister());
394         } catch (IOException ex) {
395             throw new RuntimeException(ex);
396         }
397     }
398 
write(@onnull Instruction3rmi instruction)399     public void write(@Nonnull Instruction3rmi instruction) {
400         try {
401             writer.write(getOpcodeValue(instruction.getOpcode()));
402             writer.write(instruction.getRegisterCount());
403             writer.writeUshort(instruction.getInlineIndex());
404             writer.writeUshort(instruction.getStartRegister());
405         } catch (IOException ex) {
406             throw new RuntimeException(ex);
407         }
408     }
409 
410 
write(@onnull Instruction3rms instruction)411     public void write(@Nonnull Instruction3rms instruction) {
412         try {
413             writer.write(getOpcodeValue(instruction.getOpcode()));
414             writer.write(instruction.getRegisterCount());
415             writer.writeUshort(instruction.getVtableIndex());
416             writer.writeUshort(instruction.getStartRegister());
417         } catch (IOException ex) {
418             throw new RuntimeException(ex);
419         }
420     }
421 
write(@onnull Instruction45cc instruction)422     public void write(@Nonnull Instruction45cc instruction) {
423         try {
424             writer.write(getOpcodeValue(instruction.getOpcode()));
425             writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount()));
426             writer.writeUshort(getReferenceIndex(instruction));
427             writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD()));
428             writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF()));
429             writer.writeUshort(getReference2Index(instruction));
430         } catch (IOException ex) {
431             throw new RuntimeException(ex);
432         }
433     }
434 
write(@onnull Instruction4rcc instruction)435     public void write(@Nonnull Instruction4rcc instruction) {
436         try {
437             writer.write(getOpcodeValue(instruction.getOpcode()));
438             writer.write(instruction.getRegisterCount());
439             writer.writeUshort(getReferenceIndex(instruction));
440             writer.writeUshort(instruction.getStartRegister());
441             writer.writeUshort(getReference2Index(instruction));
442         } catch (IOException ex) {
443             throw new RuntimeException(ex);
444         }
445     }
446 
write(@onnull Instruction51l instruction)447     public void write(@Nonnull Instruction51l instruction) {
448         try {
449             writer.write(getOpcodeValue(instruction.getOpcode()));
450             writer.write(instruction.getRegisterA());
451             writer.writeLong(instruction.getWideLiteral());
452         } catch (IOException ex) {
453             throw new RuntimeException(ex);
454         }
455     }
456 
write(@onnull ArrayPayload instruction)457     public void write(@Nonnull ArrayPayload instruction) {
458         try {
459             writer.writeUshort(getOpcodeValue(instruction.getOpcode()));
460             writer.writeUshort(instruction.getElementWidth());
461             List<Number> elements = instruction.getArrayElements();
462             writer.writeInt(elements.size());
463             switch (instruction.getElementWidth()) {
464                 case 1:
465                     for (Number element: elements) {
466                         writer.write(element.byteValue());
467                     }
468                     break;
469                 case 2:
470                     for (Number element: elements) {
471                         writer.writeShort(element.shortValue());
472                     }
473                     break;
474                 case 4:
475                     for (Number element: elements) {
476                         writer.writeInt(element.intValue());
477                     }
478                     break;
479                 case 8:
480                     for (Number element: elements) {
481                         writer.writeLong(element.longValue());
482                     }
483                     break;
484             }
485             if ((writer.getPosition() & 1) != 0) {
486                 writer.write(0);
487             }
488         } catch (IOException ex) {
489             throw new RuntimeException(ex);
490         }
491     }
492 
write(@onnull SparseSwitchPayload instruction)493     public void write(@Nonnull SparseSwitchPayload instruction) {
494         try {
495             writer.writeUbyte(0);
496             writer.writeUbyte(getOpcodeValue(instruction.getOpcode()) >> 8);
497             List<? extends SwitchElement> elements = Ordering.from(switchElementComparator).immutableSortedCopy(
498                     instruction.getSwitchElements());
499             writer.writeUshort(elements.size());
500             for (SwitchElement element: elements) {
501                 writer.writeInt(element.getKey());
502             }
503             for (SwitchElement element: elements) {
504                 writer.writeInt(element.getOffset());
505             }
506         } catch (IOException ex) {
507             throw new RuntimeException(ex);
508         }
509     }
510 
511     private final Comparator<SwitchElement> switchElementComparator = new Comparator<SwitchElement>() {
512         @Override public int compare(SwitchElement element1, SwitchElement element2) {
513             return Ints.compare(element1.getKey(), element2.getKey());
514         }
515     };
516 
write(@onnull PackedSwitchPayload instruction)517     public void write(@Nonnull PackedSwitchPayload instruction) {
518         try {
519             writer.writeUbyte(0);
520             writer.writeUbyte(getOpcodeValue(instruction.getOpcode()) >> 8);
521             List<? extends SwitchElement> elements = instruction.getSwitchElements();
522             writer.writeUshort(elements.size());
523             if (elements.size() == 0) {
524                 writer.writeInt(0);
525             } else {
526                 writer.writeInt(elements.get(0).getKey());
527                 for (SwitchElement element: elements) {
528                     writer.writeInt(element.getOffset());
529                 }
530             }
531         } catch (IOException ex) {
532             throw new RuntimeException(ex);
533         }
534     }
535 
packNibbles(int a, int b)536     private static int packNibbles(int a, int b) {
537         return (b << 4) | a;
538     }
539 
getReferenceIndex(ReferenceInstruction referenceInstruction)540     private int getReferenceIndex(ReferenceInstruction referenceInstruction) {
541         return getReferenceIndex(referenceInstruction.getReferenceType(),
542                 referenceInstruction.getReference());
543     }
544 
getReference2Index(DualReferenceInstruction referenceInstruction)545     private int getReference2Index(DualReferenceInstruction referenceInstruction) {
546         return getReferenceIndex(referenceInstruction.getReferenceType2(),
547                 referenceInstruction.getReference2());
548     }
549 
getReferenceIndex(int referenceType, Reference reference)550     private int getReferenceIndex(int referenceType, Reference reference) {
551         switch (referenceType) {
552             case ReferenceType.FIELD:
553                 return fieldSection.getItemIndex((FieldRefKey) reference);
554             case ReferenceType.METHOD:
555                 return methodSection.getItemIndex((MethodRefKey) reference);
556             case ReferenceType.STRING:
557                 return stringSection.getItemIndex((StringRef) reference);
558             case ReferenceType.TYPE:
559                 return typeSection.getItemIndex((TypeRef) reference);
560             case ReferenceType.METHOD_PROTO:
561                 return protoSection.getItemIndex((ProtoRefKey) reference);
562             case ReferenceType.METHOD_HANDLE:
563                 return methodHandleSection.getItemIndex((MethodHandleKey) reference);
564             case ReferenceType.CALL_SITE:
565                 return callSiteSection.getItemIndex((CallSiteKey) reference);
566             default:
567                 throw new ExceptionWithContext("Unknown reference type: %d",  referenceType);
568         }
569     }
570 }
571