blob: 82ad44418d385824a1fb406280d8d43111a9da86 [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.dexgen.dex.file;
import com.android.dexgen.dex.code.DalvCode;
import com.android.dexgen.dex.code.DalvInsnList;
import com.android.dexgen.dex.code.LocalList;
import com.android.dexgen.dex.code.PositionList;
import com.android.dexgen.rop.cst.CstMethodRef;
import com.android.dexgen.rop.cst.CstType;
import com.android.dexgen.rop.cst.CstUtf8;
import com.android.dexgen.util.AnnotatedOutput;
import com.android.dexgen.util.ExceptionWithContext;
import java.io.PrintWriter;
public class DebugInfoItem extends OffsettedItem {
/** the required alignment for instances of this class */
private static final int ALIGNMENT = 1;
private static final boolean ENABLE_ENCODER_SELF_CHECK = false;
/** {@code non-null;} the code this item represents */
private final DalvCode code;
private byte[] encoded;
private final boolean isStatic;
private final CstMethodRef ref;
public DebugInfoItem(DalvCode code, boolean isStatic, CstMethodRef ref) {
// We don't know the write size yet.
super (ALIGNMENT, -1);
if (code == null) {
throw new NullPointerException("code == null");
}
this.code = code;
this.isStatic = isStatic;
this.ref = ref;
}
/** {@inheritDoc} */
@Override
public ItemType itemType() {
return ItemType.TYPE_DEBUG_INFO_ITEM;
}
/** {@inheritDoc} */
@Override
public void addContents(DexFile file) {
// No contents to add.
}
/** {@inheritDoc} */
@Override
protected void place0(Section addedTo, int offset) {
// Encode the data and note the size.
try {
encoded = encode(addedTo.getFile(), null, null, null, false);
setWriteSize(encoded.length);
} catch (RuntimeException ex) {
throw ExceptionWithContext.withContext(ex,
"...while placing debug info for " + ref.toHuman());
}
}
/** {@inheritDoc} */
@Override
public String toHuman() {
throw new RuntimeException("unsupported");
}
/**
* Writes annotations for the elements of this list, as
* zero-length. This is meant to be used for dumping this instance
* directly after a code dump (with the real local list actually
* existing elsewhere in the output).
*
* @param file {@code non-null;} the file to use for referencing other sections
* @param out {@code non-null;} where to annotate to
* @param prefix {@code null-ok;} prefix to attach to each line of output
*/
public void annotateTo(DexFile file, AnnotatedOutput out, String prefix) {
encode(file, prefix, null, out, false);
}
/**
* Does a human-friendly dump of this instance.
*
* @param out {@code non-null;} where to dump
* @param prefix {@code non-null;} prefix to attach to each line of output
*/
public void debugPrint(PrintWriter out, String prefix) {
encode(null, prefix, out, null, false);
}
/** {@inheritDoc} */
@Override
protected void writeTo0(DexFile file, AnnotatedOutput out) {
if (out.annotates()) {
/*
* Re-run the encoder to generate the annotations,
* but write the bits from the original encode
*/
out.annotate(offsetString() + " debug info");
encode(file, null, null, out, true);
}
out.write(encoded);
}
/**
* Performs debug info encoding.
*
* @param file {@code null-ok;} file to refer to during encoding
* @param prefix {@code null-ok;} prefix to attach to each line of output
* @param debugPrint {@code null-ok;} if specified, an alternate output for
* annotations
* @param out {@code null-ok;} if specified, where annotations should go
* @param consume whether to claim to have consumed output for
* {@code out}
* @return {@code non-null;} the encoded array
*/
private byte[] encode(DexFile file, String prefix, PrintWriter debugPrint,
AnnotatedOutput out, boolean consume) {
byte[] result = encode0(file, prefix, debugPrint, out, consume);
if (ENABLE_ENCODER_SELF_CHECK && (file != null)) {
try {
DebugInfoDecoder.validateEncode(result, file, ref, code,
isStatic);
} catch (RuntimeException ex) {
// Reconvert, annotating to System.err.
encode0(file, "", new PrintWriter(System.err, true), null,
false);
throw ex;
}
}
return result;
}
/**
* Helper for {@link #encode} to do most of the work.
*
* @param file {@code null-ok;} file to refer to during encoding
* @param prefix {@code null-ok;} prefix to attach to each line of output
* @param debugPrint {@code null-ok;} if specified, an alternate output for
* annotations
* @param out {@code null-ok;} if specified, where annotations should go
* @param consume whether to claim to have consumed output for
* {@code out}
* @return {@code non-null;} the encoded array
*/
private byte[] encode0(DexFile file, String prefix, PrintWriter debugPrint,
AnnotatedOutput out, boolean consume) {
PositionList positions = code.getPositions();
LocalList locals = code.getLocals();
DalvInsnList insns = code.getInsns();
int codeSize = insns.codeSize();
int regSize = insns.getRegistersSize();
DebugInfoEncoder encoder =
new DebugInfoEncoder(positions, locals,
file, codeSize, regSize, isStatic, ref);
byte[] result;
if ((debugPrint == null) && (out == null)) {
result = encoder.convert();
} else {
result = encoder.convertAndAnnotate(prefix, debugPrint, out,
consume);
}
return result;
}
}