16d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver/*
26d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * Copyright 2013, Google Inc.
36d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * All rights reserved.
46d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver *
56d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * Redistribution and use in source and binary forms, with or without
66d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * modification, are permitted provided that the following conditions are
76d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * met:
86d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver *
96d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver *     * Redistributions of source code must retain the above copyright
106d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * notice, this list of conditions and the following disclaimer.
116d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver *     * Redistributions in binary form must reproduce the above
126d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * copyright notice, this list of conditions and the following disclaimer
136d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * in the documentation and/or other materials provided with the
146d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * distribution.
156d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver *     * Neither the name of Google Inc. nor the names of its
166d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * contributors may be used to endorse or promote products derived from
176d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * this software without specific prior written permission.
186d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver *
196d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
206d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
216d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
226d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
236d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
246d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
256d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
266d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
276d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
286d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
296d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
306d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver */
316d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
326d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverpackage org.jf.dexlib2.dexbacked.raw;
336d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
346d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport com.google.common.base.Joiner;
356d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport com.google.common.collect.Lists;
36db7795ffaa2d8804d84623a79d406f8c8686c1b8Ben Gruverimport org.jf.dexlib2.VerificationError;
376d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport org.jf.dexlib2.dexbacked.DexReader;
386d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport org.jf.dexlib2.dexbacked.instruction.DexBackedInstruction;
398f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruverimport org.jf.dexlib2.dexbacked.raw.util.DexAnnotator;
406d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport org.jf.dexlib2.iface.instruction.*;
416d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport org.jf.dexlib2.iface.instruction.formats.*;
426d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport org.jf.dexlib2.util.AnnotatedBytes;
436d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport org.jf.dexlib2.util.ReferenceUtil;
44dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruverimport org.jf.util.ExceptionWithContext;
456d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport org.jf.util.NumberUtils;
466d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
476d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport javax.annotation.Nonnull;
486d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport javax.annotation.Nullable;
496d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport java.util.List;
506d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
516d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverpublic class CodeItem {
526d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver    public static final int REGISTERS_OFFSET = 0;
536d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver    public static final int INS_OFFSET = 2;
546d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver    public static final int OUTS_OFFSET = 4;
55e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver    public static final int TRIES_SIZE_OFFSET = 6;
566d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver    public static final int DEBUG_INFO_OFFSET = 8;
576d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver    public static final int INSTRUCTION_COUNT_OFFSET = 12;
58e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver    public static final int INSTRUCTION_START_OFFSET = 16;
59e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver
60e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver    public static class TryItem {
61e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver        public static final int ITEM_SIZE = 8;
62e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver
63e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver        public static final int START_ADDRESS_OFFSET = 0;
64e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver        public static final int CODE_UNIT_COUNT_OFFSET = 4;
65e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver        public static final int HANDLER_OFFSET = 6;
66e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver    }
676d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
688f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver    @Nonnull
698f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver    public static SectionAnnotator makeAnnotator(@Nonnull DexAnnotator annotator, @Nonnull MapItem mapItem) {
708f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver        return new SectionAnnotator(annotator, mapItem) {
71063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver            private SectionAnnotator debugInfoAnnotator = null;
72063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver
73063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver            @Override public void annotateSection(@Nonnull AnnotatedBytes out) {
74063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver                debugInfoAnnotator = annotator.getAnnotator(ItemType.DEBUG_INFO_ITEM);
75063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver                super.annotateSection(out);
76063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver            }
77063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver
788f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            @Nonnull @Override public String getItemName() {
798f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                return "code_item";
808f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            }
816d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
828f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            @Override public int getItemAlignment() {
838f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                return 4;
846d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver            }
856d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
868f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            @Override
878f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            public void annotateItem(@Nonnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity) {
88dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                try {
89dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    DexReader reader = dexFile.readerAt(out.getCursor());
908f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
91dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    int registers = reader.readUshort();
92dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    out.annotate(2, "registers_size = %d", registers);
938f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
94dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    int inSize = reader.readUshort();
95dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    out.annotate(2, "ins_size = %d", inSize);
968f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
97dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    int outSize = reader.readUshort();
98dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    out.annotate(2, "outs_size = %d", outSize);
998f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
100dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    int triesCount = reader.readUshort();
101dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    out.annotate(2, "tries_size = %d", triesCount);
1028f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
103dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    int debugInfoOffset = reader.readSmallUint();
104dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    out.annotate(4, "debug_info_off = 0x%x", debugInfoOffset);
1058f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
106dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    if (debugInfoOffset != 0) {
107dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        addDebugInfoIdentity(debugInfoOffset, itemIdentity);
1088f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    }
1096d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
110dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    int instructionSize = reader.readSmallUint();
111dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    out.annotate(4, "insns_size = 0x%x", instructionSize);
1128f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
113dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    out.annotate(0, "instructions:");
1146d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver                    out.indent();
1158f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
116dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    out.setLimit(out.getCursor(), out.getCursor() + instructionSize * 2);
117dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver
118dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    int end = reader.getOffset() + instructionSize*2;
119dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    try {
120dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        while (reader.getOffset() < end) {
121dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                            Instruction instruction = DexBackedInstruction.readFrom(reader);
122dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver
123dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                            // if we read past the end of the instruction list
124dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                            if (reader.getOffset() > end) {
125dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                out.annotateTo(end, "truncated instruction");
126dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                reader.setOffset(end);
127dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                            } else {
128dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                switch (instruction.getOpcode().format) {
129dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    case Format10x:
130dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        annotateInstruction10x(out, instruction);
131dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        break;
132dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    case Format35c:
133dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        annotateInstruction35c(out, (Instruction35c)instruction);
134dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        break;
135dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    case Format3rc:
136dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        annotateInstruction3rc(out, (Instruction3rc)instruction);
137dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        break;
138dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    case ArrayPayload:
139dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        annotateArrayPayload(out, (ArrayPayload)instruction);
140dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        break;
141dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    case PackedSwitchPayload:
142dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        annotatePackedSwitchPayload(out, (PackedSwitchPayload)instruction);
143dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        break;
144dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    case SparseSwitchPayload:
145dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        annotateSparseSwitchPayload(out, (SparseSwitchPayload)instruction);
146dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        break;
147dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    default:
148dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        annotateDefaultInstruction(out, instruction);
149dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        break;
150dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                }
151dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                            }
1526d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
153dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                            assert reader.getOffset() == out.getCursor();
154dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        }
155dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    } catch (ExceptionWithContext ex) {
156dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        ex.printStackTrace(System.err);
157dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        out.annotate(0, "annotation error: %s", ex.getMessage());
158dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        out.moveTo(end);
159dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        reader.setOffset(end);
160dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    } finally {
161dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        out.clearLimit();
1628f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        out.deindent();
1638f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    }
1648f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
165dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    if (triesCount > 0) {
166dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        if ((reader.getOffset() % 4) != 0) {
167dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                            reader.readUshort();
168dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                            out.annotate(2, "padding");
169dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        }
170dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver
171dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        out.annotate(0, "try_items:");
1728f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        out.indent();
173dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        try {
174dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                            for (int i=0; i<triesCount; i++) {
175dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                out.annotate(0, "try_item[%d]:", i);
1768f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                                out.indent();
177dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                try {
178dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    int startAddr = reader.readSmallUint();
179dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    out.annotate(4, "start_addr = 0x%x", startAddr);
180dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver
181dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    int instructionCount = reader.readUshort();
182dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    out.annotate(2, "insn_count = 0x%x", instructionCount);
183dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver
184dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    int handlerOffset = reader.readUshort();
185dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    out.annotate(2, "handler_off = 0x%x", handlerOffset);
186dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                } finally {
187dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    out.deindent();
188dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                }
1898f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                            }
190dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        } finally {
1916d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver                            out.deindent();
1926d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver                        }
193dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver
194dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        int handlerListCount = reader.readSmallUleb128();
195dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        out.annotate(0, "encoded_catch_handler_list:");
196dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        out.annotateTo(reader.getOffset(), "size = %d", handlerListCount);
197dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        out.indent();
198dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        try {
199dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                            for (int i=0; i<handlerListCount; i++) {
200dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                out.annotate(0, "encoded_catch_handler[%d]", i);
201dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                out.indent();
202dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                try {
203dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    int handlerCount = reader.readSleb128();
204dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    out.annotateTo(reader.getOffset(), "size = %d", handlerCount);
205dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    boolean hasCatchAll = handlerCount <= 0;
206dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    handlerCount = Math.abs(handlerCount);
207dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    if (handlerCount != 0) {
208dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        out.annotate(0, "handlers:");
209dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        out.indent();
210dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        try {
211dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                            for (int j=0; j<handlerCount; j++) {
212dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                                out.annotate(0, "encoded_type_addr_pair[%d]", i);
213dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                                out.indent();
214dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                                try {
215dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                                    int typeIndex = reader.readSmallUleb128();
216dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                                    out.annotateTo(reader.getOffset(), TypeIdItem.getReferenceAnnotation(dexFile, typeIndex));
217dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver
218dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                                    int handlerAddress = reader.readSmallUleb128();
219dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                                    out.annotateTo(reader.getOffset(), "addr = 0x%x", handlerAddress);
220dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                                } finally {
221dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                                    out.deindent();
222dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                                }
223dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                            }
224dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        } finally {
225dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                            out.deindent();
226dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        }
227dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    }
228dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    if (hasCatchAll) {
229dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        int catchAllAddress = reader.readSmallUleb128();
230dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                        out.annotateTo(reader.getOffset(), "catch_all_addr = 0x%x", catchAllAddress);
231dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    }
232dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                } finally {
233dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                    out.deindent();
234dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                                }
235dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                            }
236dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        } finally {
237dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                            out.deindent();
2388f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        }
2396d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver                    }
240dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                } catch (ExceptionWithContext ex) {
241dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    out.annotate(0, "annotation error: %s", ex.getMessage());
2426d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver                }
2436d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver            }
2446d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
2458f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            private String formatRegister(int registerNum) {
2468f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                return String.format("v%d", registerNum);
2478f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            }
2486d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
2498f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            private void annotateInstruction10x(@Nonnull AnnotatedBytes out, @Nonnull Instruction instruction) {
2508f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.annotate(2, instruction.getOpcode().name);
2516d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver            }
2526d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
2538f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            private void annotateInstruction35c(@Nonnull AnnotatedBytes out, @Nonnull Instruction35c instruction) {
2548f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                List<String> args = Lists.newArrayList();
2558f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
2568f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                int registerCount = instruction.getRegisterCount();
2578f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                if (registerCount == 1) {
2588f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterC()));
2598f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                } else if (registerCount == 2) {
2608f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterC()));
2618f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterD()));
2628f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                } else if (registerCount == 3) {
2638f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterC()));
2648f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterD()));
2658f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterE()));
2668f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                } else if (registerCount == 4) {
2678f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterC()));
2688f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterD()));
2698f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterE()));
2708f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterF()));
2718f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                } else if (registerCount == 5) {
2728f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterC()));
2738f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterD()));
2748f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterE()));
2758f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterF()));
2768f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(instruction.getRegisterG()));
2776d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver                }
2786d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
2798f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                String reference = ReferenceUtil.getReferenceString(instruction.getReference());
2808f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
2818f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.annotate(6, String.format("%s {%s}, %s",
2828f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        instruction.getOpcode().name, Joiner.on(", ").join(args), reference));
2836d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver            }
2846d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
2858f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            private void annotateInstruction3rc(@Nonnull AnnotatedBytes out, @Nonnull Instruction3rc instruction) {
2868f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                int startRegister = instruction.getStartRegister();
2878f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                int endRegister = startRegister + instruction.getRegisterCount() - 1;
2888f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                String reference = ReferenceUtil.getReferenceString(instruction.getReference());
2898f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.annotate(6, String.format("%s {%s .. %s}, %s",
2908f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        instruction.getOpcode().name, formatRegister(startRegister), formatRegister(endRegister),
2918f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        reference));
2926d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver            }
2936d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
2948f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            private void annotateDefaultInstruction(@Nonnull AnnotatedBytes out, @Nonnull Instruction instruction) {
2958f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                List<String> args = Lists.newArrayList();
2968f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
2978f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                if (instruction instanceof OneRegisterInstruction) {
2988f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    args.add(formatRegister(((OneRegisterInstruction)instruction).getRegisterA()));
2998f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    if (instruction instanceof TwoRegisterInstruction) {
3008f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        args.add(formatRegister(((TwoRegisterInstruction)instruction).getRegisterB()));
3018f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        if (instruction instanceof ThreeRegisterInstruction) {
3028f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                            args.add(formatRegister(((ThreeRegisterInstruction)instruction).getRegisterC()));
3038f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        }
3048f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    }
305db7795ffaa2d8804d84623a79d406f8c8686c1b8Ben Gruver                }  else if (instruction instanceof VerificationErrorInstruction) {
306dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    String verificationError = VerificationError.getVerificationErrorName(
307dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        ((VerificationErrorInstruction) instruction).getVerificationError());
308dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    if (verificationError != null) {
309dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        args.add(verificationError);
310dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    } else {
311dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                        args.add("invalid verification error type");
312dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    }
3138f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                }
3148f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
3158f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                if (instruction instanceof ReferenceInstruction) {
316dc802b06607cde3eadaaffeae888bfd6146000f1Ben Gruver                    args.add(ReferenceUtil.getReferenceString(((ReferenceInstruction)instruction).getReference()));
3178a151ae671f6d5c99d55779005580834b49187f0Ben Gruver                } else if (instruction instanceof OffsetInstruction) {
3188f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    int offset = ((OffsetInstruction)instruction).getCodeOffset();
3198f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    String sign = offset>=0?"+":"-";
32070c5b247e69463338f0b61fd6a9774f439b31bd7Ben Gruver                    args.add(String.format("%s0x%x", sign, Math.abs(offset)));
3218a151ae671f6d5c99d55779005580834b49187f0Ben Gruver                } else if (instruction instanceof NarrowLiteralInstruction) {
3228f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    int value = ((NarrowLiteralInstruction)instruction).getNarrowLiteral();
3238f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    if (NumberUtils.isLikelyFloat(value)) {
3248f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        args.add(String.format("%d # %f", value, Float.intBitsToFloat(value)));
3256d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver                    } else {
3268f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        args.add(String.format("%d", value));
3276d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver                    }
3288f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                } else if (instruction instanceof WideLiteralInstruction) {
3298f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    long value = ((WideLiteralInstruction)instruction).getWideLiteral();
3308f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    if (NumberUtils.isLikelyDouble(value)) {
3318f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        args.add(String.format("%d # %f", value, Double.longBitsToDouble(value)));
3326d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver                    } else {
3338f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        args.add(String.format("%d", value));
3346d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver                    }
3358a151ae671f6d5c99d55779005580834b49187f0Ben Gruver                } else if (instruction instanceof FieldOffsetInstruction) {
336e88723c666db87d414e126ac6d94d683d86ad28dBen Gruver                    int fieldOffset = ((FieldOffsetInstruction)instruction).getFieldOffset();
337e88723c666db87d414e126ac6d94d683d86ad28dBen Gruver                    args.add(String.format("field@0x%x", fieldOffset));
3388a151ae671f6d5c99d55779005580834b49187f0Ben Gruver                } else if (instruction instanceof VtableIndexInstruction) {
3398a151ae671f6d5c99d55779005580834b49187f0Ben Gruver                    int vtableIndex = ((VtableIndexInstruction)instruction).getVtableIndex();
3408a151ae671f6d5c99d55779005580834b49187f0Ben Gruver                    args.add(String.format("vtable@%d", vtableIndex));
3412a91d72a1534dd8171d8296ce8312de4bd603451Ben Gruver                } else if (instruction instanceof InlineIndexInstruction) {
3422a91d72a1534dd8171d8296ce8312de4bd603451Ben Gruver                    int inlineIndex = ((InlineIndexInstruction)instruction).getInlineIndex();
3432a91d72a1534dd8171d8296ce8312de4bd603451Ben Gruver                    args.add(String.format("inline@%d", inlineIndex));
344e88723c666db87d414e126ac6d94d683d86ad28dBen Gruver                }
345e88723c666db87d414e126ac6d94d683d86ad28dBen Gruver
3468f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.annotate(instruction.getCodeUnits()*2, "%s %s",
3478f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        instruction.getOpcode().name, Joiner.on(", ").join(args));
3486d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver            }
3496d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
3508f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            private void annotateArrayPayload(@Nonnull AnnotatedBytes out, @Nonnull ArrayPayload instruction) {
3518f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                List<Number> elements = instruction.getArrayElements();
3528f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                int elementWidth = instruction.getElementWidth();
3536d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver
3548f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.annotate(2, instruction.getOpcode().name);
3558f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.indent();
3568f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.annotate(2, "element_width = %d", elementWidth);
3578f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.annotate(4, "size = %d", elements.size());
3588f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.annotate(0, "elements:");
3598f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.indent();
3608f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                for (int i=0; i<elements.size(); i++) {
3618f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    if (elementWidth == 8) {
3628f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        long value = elements.get(i).longValue();
3638f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        if (NumberUtils.isLikelyDouble(value)) {
3648f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                            out.annotate(elementWidth, "element[%d] = %d # %f", i, value, Double.longBitsToDouble(value));
3658f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        } else {
3668f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                            out.annotate(elementWidth, "element[%d] = %d", i, value);
3678f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        }
3688f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    } else {
3698f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        int value = elements.get(i).intValue();
3708f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        if (NumberUtils.isLikelyFloat(value)) {
3718f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                            out.annotate(elementWidth, "element[%d] = %d # %f", i, value, Float.intBitsToFloat(value));
3728f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                        } else {
3738f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                            out.annotate(elementWidth, "element[%d] = %d", i, value);
3746d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver                        }
3756d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver                    }
3768f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                }
3778f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                if (out.getCursor() % 2 != 0) {
3788f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                    out.annotate(1, "padding");
3798f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                }
3808f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.deindent();
3818f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.deindent();
3828f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            }
3838f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
3848f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            private void annotatePackedSwitchPayload(@Nonnull AnnotatedBytes out,
3858f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                                                     @Nonnull PackedSwitchPayload instruction) {
3868f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                List<? extends SwitchElement> elements = instruction.getSwitchElements();
3878f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
3888f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.annotate(2, instruction.getOpcode().name);
3898f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.indent();
3908f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
3918f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.annotate(2, "size = %d", elements.size());
392c89097680ec8d7d2495b7314c848af3507cf515fBen Gruver                if (elements.size() == 0) {
393c89097680ec8d7d2495b7314c848af3507cf515fBen Gruver                    out.annotate(4, "first_key");
394c89097680ec8d7d2495b7314c848af3507cf515fBen Gruver                } else {
395c89097680ec8d7d2495b7314c848af3507cf515fBen Gruver                    out.annotate(4, "first_key = %d", elements.get(0).getKey());
396c89097680ec8d7d2495b7314c848af3507cf515fBen Gruver                    out.annotate(0, "targets:");
397c89097680ec8d7d2495b7314c848af3507cf515fBen Gruver                    out.indent();
398c89097680ec8d7d2495b7314c848af3507cf515fBen Gruver                    for (int i=0; i<elements.size(); i++) {
399c89097680ec8d7d2495b7314c848af3507cf515fBen Gruver                        out.annotate(4, "target[%d] = %d", i, elements.get(i).getOffset());
400c89097680ec8d7d2495b7314c848af3507cf515fBen Gruver                    }
401c89097680ec8d7d2495b7314c848af3507cf515fBen Gruver                    out.deindent();
4028f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                }
4038f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.deindent();
4048f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            }
4058f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
4068f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver            private void annotateSparseSwitchPayload(@Nonnull AnnotatedBytes out,
4078f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                                                     @Nonnull SparseSwitchPayload instruction) {
4088f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                List<? extends SwitchElement> elements = instruction.getSwitchElements();
4098f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver
4108f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.annotate(2, instruction.getOpcode().name);
4118f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.indent();
4128f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.annotate(2, "size = %d", elements.size());
4132fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                if (elements.size() > 0) {
4142fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                    out.annotate(0, "keys:");
4152fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                    out.indent();
4162fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                    for (int i=0; i<elements.size(); i++) {
4172fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                        out.annotate(4, "key[%d] = %d", i, elements.get(i).getKey());
4182fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                    }
4192fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                    out.deindent();
4202fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                    out.annotate(0, "targets:");
4212fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                    out.indent();
4222fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                    for (int i=0; i<elements.size(); i++) {
4232fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                        out.annotate(4, "target[%d] = %d", i, elements.get(i).getOffset());
4242fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                    }
4252fe6041fa9e2e2eab534a7da086006835c8f59f6Ben Gruver                    out.deindent();
4268f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                }
4278f8b67f65ec3390e92cce7d710e5b1eaabd4e248Ben Gruver                out.deindent();
4286d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver            }
429063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver
430063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver            private void addDebugInfoIdentity(int debugInfoOffset, String methodString) {
431063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver                if (debugInfoAnnotator != null) {
432063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver                    debugInfoAnnotator.setItemIdentity(debugInfoOffset, methodString);
433063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver                }
434063ec54b929a38f6b56cb667f8d08e23f92b62f7Ben Gruver            }
4356d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver        };
4366d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver    }
4376d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver}
438