| /* |
| * [The "BSD licence"] |
| * Copyright (c) 2010 Ben Gruver (JesusFreke) |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| package org.jf.dexlib; |
| |
| import org.jf.dexlib.Debug.DebugInstructionIterator; |
| import org.jf.dexlib.Debug.DebugOpcode; |
| import org.jf.dexlib.Util.AnnotatedOutput; |
| import org.jf.dexlib.Util.ByteArrayInput; |
| import org.jf.dexlib.Util.Input; |
| import org.jf.dexlib.Util.Leb128Utils; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| public class DebugInfoItem extends Item<DebugInfoItem> { |
| private int lineStart; |
| private StringIdItem[] parameterNames; |
| private byte[] encodedDebugInfo; |
| private Item[] referencedItems; |
| |
| private CodeItem parent = null; |
| |
| /** |
| * Creates a new uninitialized <code>DebugInfoInfo</code> |
| * @param dexFile The <code>DexFile</code> that this item belongs to |
| */ |
| public DebugInfoItem(DexFile dexFile) { |
| super(dexFile); |
| } |
| |
| /** |
| * Creates a new <code>DebugInfoItem</code> with the given values |
| * @param dexFile The <code>DexFile</code> that this item belongs to |
| * @param lineStart the initial value for the line number register for the debug info machine |
| * @param parameterNames an array of the names of the associated method's parameters. The entire parameter |
| * can be null if no parameter info is available, or any element can be null to indicate no info for that parameter |
| * @param encodedDebugInfo the debug info, encoded as a byte array |
| * @param referencedItems an array of the items referenced by instructions, in order of occurance in the encoded |
| * debug info |
| */ |
| private DebugInfoItem(DexFile dexFile, |
| int lineStart, |
| StringIdItem[] parameterNames, |
| byte[] encodedDebugInfo, |
| Item[] referencedItems) { |
| super(dexFile); |
| this.lineStart = lineStart; |
| this.parameterNames = parameterNames; |
| this.encodedDebugInfo = encodedDebugInfo; |
| this.referencedItems = referencedItems; |
| } |
| |
| /** |
| * Returns a new <code>DebugInfoItem</code> with the given values |
| * @param dexFile The <code>DexFile</code> that this item belongs to |
| * @param lineStart the initial value for the line number register for the debug info machine |
| * @param parameterNames an array of the names of the associated method's parameters. The entire parameter |
| * can be null if no parameter info is available, or any element can be null to indicate no info for that parameter |
| * @param encodedDebugInfo the debug info, encoded as a byte array |
| * @param referencedItems an array of the items referenced by instructions, in order of occurance in the encoded |
| * debug info |
| * @return a new <code>DebugInfoItem</code> with the given values |
| */ |
| public static DebugInfoItem internDebugInfoItem(DexFile dexFile, |
| int lineStart, |
| StringIdItem[] parameterNames, |
| byte[] encodedDebugInfo, |
| Item[] referencedItems) { |
| DebugInfoItem debugInfoItem = new DebugInfoItem(dexFile, lineStart, parameterNames, encodedDebugInfo, |
| referencedItems); |
| return dexFile.DebugInfoItemsSection.intern(debugInfoItem); |
| } |
| |
| /** {@inheritDoc} */ |
| protected void readItem(Input in, ReadContext readContext) { |
| lineStart = in.readUnsignedLeb128(); |
| parameterNames = new StringIdItem[in.readUnsignedLeb128()]; |
| IndexedSection<StringIdItem> stringIdSection = dexFile.StringIdsSection; |
| for (int i=0; i<parameterNames.length; i++) { |
| parameterNames[i] = stringIdSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1); |
| } |
| |
| int start = in.getCursor(); |
| final List<Item> referencedItemsList = new ArrayList<Item>(50); |
| DebugInstructionIterator.IterateInstructions(in, |
| new DebugInstructionIterator.ProcessRawDebugInstructionDelegate() { |
| @Override |
| public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex, |
| int typeIndex, boolean registerIsSigned) { |
| if (nameIndex != -1) { |
| referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex)); |
| } |
| if (typeIndex != -1) { |
| referencedItemsList.add(dexFile.TypeIdsSection.getItemByIndex(typeIndex)); |
| } |
| } |
| |
| @Override |
| public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNume, |
| int nameIndex, int typeIndex, int signatureIndex, |
| boolean registerIsSigned) { |
| if (nameIndex != -1) { |
| referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex)); |
| } |
| if (typeIndex != -1) { |
| referencedItemsList.add(dexFile.TypeIdsSection.getItemByIndex(typeIndex)); |
| } |
| if (signatureIndex != -1) { |
| referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(signatureIndex)); |
| } |
| } |
| |
| @Override |
| public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) { |
| if (nameIndex != -1) { |
| referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex)); |
| } |
| } |
| }); |
| |
| referencedItems = new Item[referencedItemsList.size()]; |
| referencedItemsList.toArray(referencedItems); |
| |
| int length = in.getCursor() - start; |
| in.setCursor(start); |
| encodedDebugInfo = in.readBytes(length); |
| } |
| |
| |
| |
| /** {@inheritDoc} */ |
| protected int placeItem(int offset) { |
| offset += Leb128Utils.unsignedLeb128Size(lineStart); |
| offset += Leb128Utils.unsignedLeb128Size(parameterNames.length); |
| for (StringIdItem parameterName: parameterNames) { |
| int indexp1; |
| if (parameterName == null) { |
| indexp1 = 0; |
| } else { |
| indexp1 = parameterName.getIndex() + 1; |
| } |
| offset += Leb128Utils.unsignedLeb128Size(indexp1); |
| } |
| |
| //make a subclass so we can keep track of and access the computed length |
| class ProcessDebugInstructionDelegateWithLength extends |
| DebugInstructionIterator.ProcessRawDebugInstructionDelegate { |
| public int length = 0; |
| } |
| ProcessDebugInstructionDelegateWithLength pdidwl; |
| |
| //final referencedItems = this.referencedItems; |
| |
| DebugInstructionIterator.IterateInstructions(new ByteArrayInput(encodedDebugInfo), |
| pdidwl = new ProcessDebugInstructionDelegateWithLength() { |
| private int referencedItemsPosition = 0; |
| |
| @Override |
| public void ProcessStaticOpcode(DebugOpcode opcode, int startDebugOffset, int length) { |
| this.length+=length; |
| } |
| |
| @Override |
| public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex, |
| int typeIndex, boolean registerIsSigned) { |
| this.length++; |
| if (dexFile.getPreserveSignedRegisters() && registerIsSigned) { |
| this.length += Leb128Utils.signedLeb128Size(registerNum); |
| } else { |
| this.length+=Leb128Utils.unsignedLeb128Size(registerNum); |
| } |
| if (nameIndex != -1) { |
| this.length+= |
| Leb128Utils.unsignedLeb128Size(referencedItems[referencedItemsPosition++].getIndex()+1); |
| } else { |
| this.length++; |
| } |
| if (typeIndex != -1) { |
| this.length+= |
| Leb128Utils.unsignedLeb128Size(referencedItems[referencedItemsPosition++].getIndex()+1); |
| } else { |
| this.length++; |
| } |
| |
| } |
| |
| @Override |
| public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNum, int nameIndex, |
| int typeIndex, int signatureIndex, |
| boolean registerIsSigned) { |
| this.length++; |
| if (dexFile.getPreserveSignedRegisters() && registerIsSigned) { |
| this.length += Leb128Utils.signedLeb128Size(registerNum); |
| } else { |
| this.length+=Leb128Utils.unsignedLeb128Size(registerNum); |
| } |
| if (nameIndex != -1) { |
| this.length+= |
| Leb128Utils.unsignedLeb128Size(referencedItems[referencedItemsPosition++].getIndex()+1); |
| } else { |
| this.length++; |
| } |
| if (typeIndex != -1) { |
| this.length+= |
| Leb128Utils.unsignedLeb128Size(referencedItems[referencedItemsPosition++].getIndex()+1); |
| } else { |
| this.length++; |
| } |
| if (signatureIndex != -1) { |
| this.length+= |
| Leb128Utils.unsignedLeb128Size(referencedItems[referencedItemsPosition++].getIndex()+1); |
| } else { |
| this.length++; |
| } |
| } |
| |
| @Override |
| public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) { |
| this.length++; |
| if (nameIndex != -1) { |
| this.length+= |
| Leb128Utils.unsignedLeb128Size(referencedItems[referencedItemsPosition++].getIndex()+1); |
| } else { |
| this.length++; |
| } |
| } |
| }); |
| return offset + pdidwl.length; |
| } |
| |
| /** {@inheritDoc} */ |
| protected void writeItem(final AnnotatedOutput out) { |
| if (out.annotates()) { |
| writeItemWithAnnotations(out); |
| } else { |
| writeItemWithNoAnnotations(out); |
| } |
| } |
| |
| /** |
| * Replaces the encoded debug info for this DebugInfoItem. It is expected that the new debug info is compatible |
| * with the existing information, i.e. lineStart, referencedItems, parameterNames |
| * @param encodedDebugInfo the new encoded debug info |
| */ |
| protected void setEncodedDebugInfo(byte[] encodedDebugInfo) { |
| //TODO: I would rather replace this method with some way of saying "The (code) instruction at address changed from A bytes to B bytes. Fixup the debug info accordingly" |
| |
| this.encodedDebugInfo = encodedDebugInfo; |
| } |
| |
| /** |
| * Helper method that writes the item, without writing annotations |
| * @param out the AnnotatedOutput object |
| */ |
| private void writeItemWithNoAnnotations(final AnnotatedOutput out) { |
| out.writeUnsignedLeb128(lineStart); |
| out.writeUnsignedLeb128(parameterNames.length); |
| for (StringIdItem parameterName: parameterNames) { |
| int indexp1; |
| if (parameterName == null) { |
| indexp1 = 0; |
| } else { |
| indexp1 = parameterName.getIndex() + 1; |
| } |
| out.writeUnsignedLeb128(indexp1); |
| } |
| |
| DebugInstructionIterator.IterateInstructions(new ByteArrayInput(encodedDebugInfo), |
| new DebugInstructionIterator.ProcessRawDebugInstructionDelegate() { |
| private int referencedItemsPosition = 0; |
| |
| @Override |
| public void ProcessStaticOpcode(DebugOpcode opcode, int startDebugOffset, int length) { |
| out.write(encodedDebugInfo, startDebugOffset, length); |
| } |
| |
| @Override |
| public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex, |
| int typeIndex, boolean registerIsSigned) { |
| out.writeByte(DebugOpcode.DBG_START_LOCAL.value); |
| if (dexFile.getPreserveSignedRegisters() && registerIsSigned) { |
| out.writeSignedLeb128(registerNum); |
| } else { |
| out.writeUnsignedLeb128(registerNum); |
| } |
| if (nameIndex != -1) { |
| out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1); |
| } else { |
| out.writeByte(0); |
| } |
| if (typeIndex != -1) { |
| out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1); |
| } else { |
| out.writeByte(0); |
| } |
| } |
| |
| @Override |
| public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNum, int nameIndex, |
| int typeIndex, int signatureIndex, |
| boolean registerIsSigned) { |
| out.writeByte(DebugOpcode.DBG_START_LOCAL_EXTENDED.value); |
| if (dexFile.getPreserveSignedRegisters() && registerIsSigned) { |
| out.writeSignedLeb128(registerNum); |
| } else { |
| out.writeUnsignedLeb128(registerNum); |
| } |
| if (nameIndex != -1) { |
| out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1); |
| } else { |
| out.writeByte(0); |
| } |
| if (typeIndex != -1) { |
| out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1); |
| } else { |
| out.writeByte(0); |
| } |
| if (signatureIndex != -1) { |
| out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1); |
| } else { |
| out.writeByte(0); |
| } |
| } |
| |
| @Override |
| public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) { |
| out.writeByte(DebugOpcode.DBG_SET_FILE.value); |
| if (nameIndex != -1) { |
| out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1); |
| } else { |
| out.writeByte(0); |
| } |
| } |
| }); |
| } |
| |
| /** |
| * Helper method that writes and annotates the item |
| * @param out the AnnotatedOutput object |
| */ |
| private void writeItemWithAnnotations(final AnnotatedOutput out) { |
| out.annotate(0, parent.getParent().method.getMethodString()); |
| out.annotate("line_start: 0x" + Integer.toHexString(lineStart) + " (" + lineStart + ")"); |
| out.writeUnsignedLeb128(lineStart); |
| out.annotate("parameters_size: 0x" + Integer.toHexString(parameterNames.length) + " (" + parameterNames.length |
| + ")"); |
| out.writeUnsignedLeb128(parameterNames.length); |
| int index = 0; |
| for (StringIdItem parameterName: parameterNames) { |
| int indexp1; |
| if (parameterName == null) { |
| out.annotate("[" + index++ +"] parameterName: "); |
| indexp1 = 0; |
| } else { |
| out.annotate("[" + index++ +"] parameterName: " + parameterName.getStringValue()); |
| indexp1 = parameterName.getIndex() + 1; |
| } |
| out.writeUnsignedLeb128(indexp1); |
| } |
| |
| DebugInstructionIterator.IterateInstructions(new ByteArrayInput(encodedDebugInfo), |
| new DebugInstructionIterator.ProcessRawDebugInstructionDelegate() { |
| private int referencedItemsPosition = 0; |
| |
| @Override |
| public void ProcessEndSequence(int startDebugOffset) { |
| out.annotate("DBG_END_SEQUENCE"); |
| out.writeByte(DebugOpcode.DBG_END_SEQUENCE.value); |
| } |
| |
| @Override |
| public void ProcessAdvancePC(int startDebugOffset, int length, int addressDiff) { |
| out.annotate("DBG_ADVANCE_PC"); |
| out.writeByte(DebugOpcode.DBG_ADVANCE_PC.value); |
| out.indent(); |
| out.annotate("addr_diff: 0x" + Integer.toHexString(addressDiff) + " (" + addressDiff + ")"); |
| out.writeUnsignedLeb128(addressDiff); |
| out.deindent(); |
| } |
| |
| @Override |
| public void ProcessAdvanceLine(int startDebugOffset, int length, int lineDiff) { |
| out.annotate("DBG_ADVANCE_LINE"); |
| out.writeByte(DebugOpcode.DBG_ADVANCE_LINE.value); |
| out.indent(); |
| out.annotate("line_diff: 0x" + Integer.toHexString(lineDiff) + " (" + lineDiff + ")"); |
| out.writeSignedLeb128(lineDiff); |
| out.deindent(); |
| } |
| |
| @Override |
| public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex, |
| int typeIndex, boolean registerIsSigned) { |
| out.annotate("DBG_START_LOCAL"); |
| out.writeByte(DebugOpcode.DBG_START_LOCAL.value); |
| out.indent(); |
| out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")"); |
| if (dexFile.getPreserveSignedRegisters() && registerIsSigned) { |
| out.writeSignedLeb128(registerNum); |
| } else { |
| out.writeUnsignedLeb128(registerNum); |
| } |
| if (nameIndex != -1) { |
| Item nameItem = referencedItems[referencedItemsPosition++]; |
| assert nameItem instanceof StringIdItem; |
| out.annotate("name: " + ((StringIdItem)nameItem).getStringValue()); |
| out.writeUnsignedLeb128(nameItem.getIndex() + 1); |
| } else { |
| out.annotate("name: "); |
| out.writeByte(0); |
| } |
| if (typeIndex != -1) { |
| Item typeItem = referencedItems[referencedItemsPosition++]; |
| assert typeItem instanceof TypeIdItem; |
| out.annotate("type: " + ((TypeIdItem)typeItem).getTypeDescriptor()); |
| out.writeUnsignedLeb128(typeItem.getIndex() + 1); |
| } else { |
| out.annotate("type: "); |
| out.writeByte(0); |
| } |
| out.deindent(); |
| } |
| |
| @Override |
| public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNum, |
| int nameIndex, int typeIndex, int signatureIndex, |
| boolean registerIsSigned) { |
| out.annotate("DBG_START_LOCAL_EXTENDED"); |
| out.writeByte(DebugOpcode.DBG_START_LOCAL_EXTENDED.value); |
| out.indent(); |
| out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")"); |
| if (dexFile.getPreserveSignedRegisters() && registerIsSigned) { |
| out.writeSignedLeb128(registerNum); |
| } else { |
| out.writeUnsignedLeb128(registerNum); |
| } |
| if (nameIndex != -1) { |
| Item nameItem = referencedItems[referencedItemsPosition++]; |
| assert nameItem instanceof StringIdItem; |
| out.annotate("name: " + ((StringIdItem)nameItem).getStringValue()); |
| out.writeUnsignedLeb128(nameItem.getIndex() + 1); |
| } else { |
| out.annotate("name: "); |
| out.writeByte(0); |
| } |
| if (typeIndex != -1) { |
| Item typeItem = referencedItems[referencedItemsPosition++]; |
| assert typeItem instanceof TypeIdItem; |
| out.annotate("type: " + ((TypeIdItem)typeItem).getTypeDescriptor()); |
| out.writeUnsignedLeb128(typeItem.getIndex() + 1); |
| } else { |
| out.annotate("type: "); |
| out.writeByte(0); |
| } |
| if (signatureIndex != -1) { |
| Item signatureItem = referencedItems[referencedItemsPosition++]; |
| assert signatureItem instanceof StringIdItem; |
| out.annotate("signature: " + ((StringIdItem)signatureItem).getStringValue()); |
| out.writeUnsignedLeb128(signatureItem.getIndex() + 1); |
| } else { |
| out.annotate("signature: "); |
| out.writeByte(0); |
| } |
| out.deindent(); |
| } |
| |
| @Override |
| public void ProcessEndLocal(int startDebugOffset, int length, int registerNum, |
| boolean registerIsSigned) { |
| out.annotate("DBG_END_LOCAL"); |
| out.writeByte(DebugOpcode.DBG_END_LOCAL.value); |
| out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")"); |
| if (registerIsSigned) { |
| out.writeSignedLeb128(registerNum); |
| } else { |
| out.writeUnsignedLeb128(registerNum); |
| } |
| } |
| |
| @Override |
| public void ProcessRestartLocal(int startDebugOffset, int length, int registerNum, |
| boolean registerIsSigned) { |
| out.annotate("DBG_RESTART_LOCAL"); |
| out.writeByte(DebugOpcode.DBG_RESTART_LOCAL.value); |
| out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")"); |
| if (registerIsSigned) { |
| out.writeSignedLeb128(registerNum); |
| } else { |
| out.writeUnsignedLeb128(registerNum); |
| } |
| } |
| |
| @Override |
| public void ProcessSetPrologueEnd(int startDebugOffset) { |
| out.annotate("DBG_SET_PROLOGUE_END"); |
| out.writeByte(DebugOpcode.DBG_SET_PROLOGUE_END.value); |
| } |
| |
| @Override |
| public void ProcessSetEpilogueBegin(int startDebugOffset) { |
| out.annotate("DBG_SET_EPILOGUE_BEGIN"); |
| out.writeByte(DebugOpcode.DBG_SET_EPILOGUE_BEGIN.value); |
| } |
| |
| @Override |
| public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) { |
| out.annotate("DBG_SET_FILE"); |
| out.writeByte(DebugOpcode.DBG_SET_FILE.value); |
| if (nameIndex != -1) { |
| Item sourceItem = referencedItems[referencedItemsPosition++]; |
| assert sourceItem instanceof StringIdItem; |
| out.annotate("source_file: \"" + ((StringIdItem)sourceItem).getStringValue() + "\""); |
| out.writeUnsignedLeb128(sourceItem.getIndex() + 1); |
| } else { |
| out.annotate("source_file: "); |
| out.writeByte(0); |
| } |
| } |
| |
| @Override |
| public void ProcessSpecialOpcode(int startDebugOffset, int debugOpcode, int lineDiff, |
| int addressDiff) { |
| out.annotate("DBG_SPECIAL_OPCODE: line_diff=0x" + Integer.toHexString(lineDiff) + "(" + |
| lineDiff +"),addressDiff=0x" + Integer.toHexString(addressDiff) + "(" + addressDiff + |
| ")"); |
| out.writeByte(debugOpcode); |
| } |
| }); |
| } |
| |
| |
| |
| |
| /** {@inheritDoc} */ |
| public ItemType getItemType() { |
| return ItemType.TYPE_DEBUG_INFO_ITEM; |
| } |
| |
| /** {@inheritDoc} */ |
| public String getConciseIdentity() { |
| return "debug_info_item @0x" + Integer.toHexString(getOffset()); |
| } |
| |
| /** {@inheritDoc} */ |
| public int compareTo(DebugInfoItem other) { |
| if (parent == null) { |
| if (other.parent == null) { |
| return 0; |
| } |
| return -1; |
| } |
| if (other.parent == null) { |
| return 1; |
| } |
| return parent.compareTo(other.parent); |
| } |
| |
| /** |
| * Set the <code>CodeItem</code> that this <code>DebugInfoItem</code> is associated with |
| * @param codeItem the <code>CodeItem</code> that this <code>DebugInfoItem</code> is associated with |
| */ |
| protected void setParent(CodeItem codeItem) { |
| this.parent = codeItem; |
| } |
| |
| /** |
| * @return the initial value for the line number register for the debug info machine |
| */ |
| public int getLineStart() { |
| return lineStart; |
| } |
| |
| /** |
| * @return the debug info, encoded as a byte array |
| */ |
| public byte[] getEncodedDebugInfo() { |
| return encodedDebugInfo; |
| } |
| |
| /** |
| * @return an array of the items referenced by instructions, in order of occurance in the encoded debug info |
| */ |
| public Item[] getReferencedItems() { |
| return referencedItems; |
| } |
| |
| /** |
| * @return an array of the names of the associated method's parameters. The array can be null if no parameter info |
| * is available, or any element can be null to indicate no info for that parameter |
| */ |
| public StringIdItem[] getParameterNames() { |
| return parameterNames; |
| } |
| } |