read enhanced bytecode postions from class attributes

This commit is contained in:
Juergen Graf 2011-03-29 15:56:48 +02:00
parent d7ebb57ee6
commit 47711fd310
8 changed files with 351 additions and 10 deletions

View File

@ -19,6 +19,7 @@ import com.ibm.wala.cfg.AbstractCFG;
import com.ibm.wala.cfg.ControlFlowGraph;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.shrikeCT.InvalidClassFileException;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.Descriptor;
import com.ibm.wala.types.MethodReference;
@ -249,6 +250,15 @@ public abstract class AstMethod implements IMethod {
public int getNumberOfParameters() {
return symtab.getParameterValueNumbers().length;
}
/** BEGIN Custom change: precise bytecode positions */
/*
* @see com.ibm.wala.classLoader.IMethod#getParameterSourcePosition(int)
*/
public SourcePosition getParameterSourcePosition(int paramNum) throws InvalidClassFileException {
return null;
}
/** END Custom change: precise bytecode positions */
public int getLineNumber(int instructionIndex) {
Position pos = debugInfo.getInstructionPosition(instructionIndex);

View File

@ -15,6 +15,8 @@ import java.io.InputStream;
import java.net.URL;
import java.util.Iterator;
import com.ibm.wala.classLoader.IMethod.SourcePosition;
/**
* The assumption is that a typical CAst is derived from some kind of
* textual source file, for which it makes sense to record source
@ -35,13 +37,7 @@ public interface CAstSourcePositionMap {
*
* @author Julian Dolby (dolby@us.ibm.com)
*/
public interface Position extends Comparable {
int getFirstLine();
int getLastLine();
int getFirstCol();
int getLastCol();
int getFirstOffset();
int getLastOffset();
public interface Position extends SourcePosition {
URL getURL();
InputStream getInputStream() throws IOException;
}

View File

@ -122,7 +122,22 @@ public interface IMethod extends IMember, ContextItem {
* @return the source line number corresponding to a particular bytecode index, or -1 if the information is not available.
*/
int getLineNumber(int bcIndex);
/** BEGIN Custom change: precise positions */
public interface SourcePosition extends Comparable {
int getFirstLine();
int getLastLine();
int getFirstCol();
int getLastCol();
int getFirstOffset();
int getLastOffset();
}
SourcePosition getSourcePosition(int instructionIndex) throws InvalidClassFileException;
SourcePosition getParameterSourcePosition(int paramNum) throws InvalidClassFileException;
/** END Custom change: precise positions */
/**
* @return the (source code) name of the local variable of a given number at the specified program counter, or null if the
* information is not available.

View File

@ -96,7 +96,21 @@ public abstract class ShrikeBTMethod implements IMethod, BytecodeConstants {
* Mapping from instruction index to program counter.
*/
private int[] pcMap;
/** BEGIN Custom change: precise positions */
/**
* Cached map representing position information for bytecode instruction
* at given index
*/
protected SourcePosition[] positionMap;
/**
* Sourcecode positions for method parameters
*/
protected SourcePosition[] paramPositionMap;
/** END Custom change: precise positions */
/**
* Cached map representing line number information in ShrikeCT format TODO: do more careful caching than just soft references
*/
@ -740,6 +754,22 @@ public abstract class ShrikeBTMethod implements IMethod, BytecodeConstants {
return null;
}
}
/** BEGIN Custom change: precise bytecode positions */
/*
* @see com.ibm.wala.classLoader.IMethod#getSourcePosition(int)
*/
public SourcePosition getSourcePosition(int bcIndex) throws InvalidClassFileException {
return (getBCInfo().positionMap == null) ? null : getBCInfo().positionMap[bcIndex];
}
/*
* @see com.ibm.wala.classLoader.IMethod#getParameterSourcePosition(int)
*/
public SourcePosition getParameterSourcePosition(int paramNum) throws InvalidClassFileException {
return (getBCInfo().paramPositionMap == null) ? null : getBCInfo().paramPositionMap[paramNum];
}
/** END Custom change: precise bytecode positions */
/*
* @see com.ibm.wala.classLoader.IMethod#getLineNumber(int)

View File

@ -10,6 +10,7 @@
*******************************************************************************/
package com.ibm.wala.classLoader;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -19,7 +20,9 @@ import com.ibm.wala.shrikeBT.Decoder;
import com.ibm.wala.shrikeBT.IndirectionData;
import com.ibm.wala.shrikeBT.shrikeCT.CTDecoder;
import com.ibm.wala.shrikeCT.AnnotationsReader;
import com.ibm.wala.shrikeCT.AnnotationsReader.UnimplementedException;
import com.ibm.wala.shrikeCT.ClassReader;
import com.ibm.wala.shrikeCT.ClassReader.AttrIterator;
import com.ibm.wala.shrikeCT.CodeReader;
import com.ibm.wala.shrikeCT.ExceptionsReader;
import com.ibm.wala.shrikeCT.InvalidClassFileException;
@ -28,8 +31,8 @@ import com.ibm.wala.shrikeCT.LocalVariableTableReader;
import com.ibm.wala.shrikeCT.RuntimeInvisibleAnnotationsReader;
import com.ibm.wala.shrikeCT.RuntimeVisibleAnnotationsReader;
import com.ibm.wala.shrikeCT.SignatureReader;
import com.ibm.wala.shrikeCT.AnnotationsReader.UnimplementedException;
import com.ibm.wala.shrikeCT.ClassReader.AttrIterator;
import com.ibm.wala.shrikeCT.SourcePositionTableReader;
import com.ibm.wala.shrikeCT.SourcePositionTableReader.Position;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.types.annotations.Annotation;
import com.ibm.wala.types.generics.MethodTypeSignature;
@ -146,12 +149,115 @@ public final class ShrikeCTMethod extends ShrikeBTMethod implements IBytecodeMet
return reader.getClasses();
}
}
/** BEGIN Custom change: precise positions */
private static final class SPos implements SourcePosition {
final int firstLine;
final int lastLine;
final int firstCol;
final int lastCol;
private SPos(int firstLine, int lastLine, int firstCol, int lastCol) {
this.firstLine = firstLine;
this.lastLine = lastLine;
this.firstCol = firstCol;
this.lastCol = lastCol;
}
public int getFirstCol() {
return firstCol;
}
public int getFirstLine() {
return firstLine;
}
public int getFirstOffset() {
return 0;
}
public int getLastCol() {
return lastCol;
}
public int getLastLine() {
return lastLine;
}
public int getLastOffset() {
return 0;
}
public int compareTo(Object o) {
if (o instanceof SourcePosition) {
SourcePosition p = (SourcePosition) o;
if (firstLine != p.getFirstLine()) {
return firstLine - p.getFirstLine();
} else if (firstCol != p.getFirstCol()) {
return firstCol - p.getFirstCol();
} else if (lastLine != p.getLastLine()) {
return lastLine - p.getLastLine();
} else if (lastCol != p.getLastCol()) {
return lastCol - p.getLastCol();
} else {
return 0;
}
} else {
return -1;
}
}
@Override
public String toString() {
return "(" + firstLine + "," + firstCol + "-" + lastLine + "," + lastCol + ")";
}
}
/** END Custom change: precise positions */
@Override
protected void processDebugInfo(BytecodeInfo bcInfo) throws InvalidClassFileException {
CodeReader cr = getCodeReader();
bcInfo.lineNumberMap = LineNumberTableReader.makeBytecodeToSourceMap(cr);
bcInfo.localVariableMap = LocalVariableTableReader.makeVarMap(cr);
/** BEGIN Custom change: precise bytecode positions */
Position param = null;
try {
param = SourcePositionTableReader.findParameterPosition(shrikeMethodIndex, cr);
} catch (IOException e) {
e.printStackTrace();
}
bcInfo.paramPositionMap = new SPos[getNumberOfParameters()];
if (param != null) {
SPos paramPos = new SPos(param.firstLine, param.lastLine, param.firstCol, param.lastCol);
for (int i = 0; i < getNumberOfParameters(); i++) {
bcInfo.paramPositionMap[i] = paramPos;
}
}
Position pos[] = null;
try {
pos = SourcePositionTableReader.makeBytecodeToPositionMap(cr);
} catch (IOException e) {
e.printStackTrace();
}
if (pos == null && bcInfo.lineNumberMap != null) {
pos = SourcePositionTableReader.makeLineNumberToPositionMap(bcInfo.lineNumberMap);
}
if (pos != null) {
bcInfo.positionMap = new SPos[pos.length];
for (int i = 0; i < pos.length; i++) {
Position p = pos[i];
bcInfo.positionMap[i] = new SPos(p.firstLine, p.lastLine, p.firstCol, p.lastCol);
}
}
/** END Custom change: : precise bytecode positions */
}
@Override

View File

@ -308,6 +308,22 @@ public class SyntheticMethod implements IMethod {
public Descriptor getDescriptor() {
return method.getSelector().getDescriptor();
}
/** BEGIN Custom change: : precise bytecode positions */
/*
* @see com.ibm.wala.classLoader.IMethod#getSourcePosition(int)
*/
public SourcePosition getSourcePosition(int bcIndex) throws InvalidClassFileException {
return null;
}
/*
* @see com.ibm.wala.classLoader.IMethod#getParameterSourcePosition(int)
*/
public SourcePosition getParameterSourcePosition(int paramNum) throws InvalidClassFileException {
return null;
}
/** END Custom change: precise bytecode positions */
/*
* @see com.ibm.wala.classLoader.IMethod#getLineNumber(int)

View File

@ -16,3 +16,4 @@ Export-Package: com.ibm.wala.shrike.bench,
com.ibm.wala.shrikeBT.tools,
com.ibm.wala.shrikeCT
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Require-Bundle: joana.jSDG.SourceInfo;bundle-version="0.0.2"

View File

@ -0,0 +1,167 @@
package com.ibm.wala.shrikeCT;
import java.io.IOException;
import joana.sourceinfo.CRTable;
import joana.sourceinfo.MethodPositions;
import joana.sourceinfo.Range;
import com.ibm.wala.shrikeCT.ClassReader.AttrIterator;
public final class SourcePositionTableReader extends AttributeReader {
protected SourcePositionTableReader(AttrIterator attr) throws InvalidClassFileException {
super(attr, CRTable.ATTRIBUTE_NAME);
}
public static final class Position implements Comparable<Object> {
public final int firstLine;
public final int lastLine;
public final int firstCol;
public final int lastCol;
private Position(int firstLine, int lastLine, int firstCol, int lastCol) {
this.firstLine = firstLine;
this.lastLine = lastLine;
this.firstCol = firstCol;
this.lastCol = lastCol;
}
public int compareTo(Object o) {
if (o instanceof Position) {
Position p = (Position) o;
if (firstLine != p.firstLine) {
return firstLine - p.firstLine;
} else if (firstCol != p.firstCol) {
return firstCol - p.firstCol;
} else if (lastLine != p.lastLine) {
return lastLine - p.lastLine;
} else if (lastCol != p.lastCol) {
return lastCol - p.lastCol;
} else {
return 0;
}
} else {
return -1;
}
}
}
public static Position findParameterPosition(int methodNr, CodeReader code) throws InvalidClassFileException, IOException {
if (code == null) {
throw new IllegalArgumentException();
}
Position params = null;
// read parameter positions
{
ClassReader.AttrIterator cIter = new ClassReader.AttrIterator();
ClassReader cr = code.getClassReader();
cr.initMethodAttributeIterator(methodNr, cIter);
for (;cIter.isValid(); cIter.advance()) {
if (MethodPositions.ATTRIBUTE_NAME.equals(cIter.getName())) {
byte data[] = getData(cr, cIter.getRawOffset(), cIter.getRawSize());
MethodPositions mPos = new MethodPositions(data);
Range r = mPos.getMethodInfo();
params = convert(r);
}
}
}
return params;
}
public static Position[] makeBytecodeToPositionMap(CodeReader code) throws InvalidClassFileException, IOException {
if (code == null) {
throw new IllegalArgumentException();
}
Position pos[] = null;
ClassReader.AttrIterator iter = new ClassReader.AttrIterator();
code.initAttributeIterator(iter);
for (; iter.isValid(); iter.advance()) {
if (CRTable.ATTRIBUTE_NAME.equals(iter.getName())) {
if (pos == null) {
pos = new Position[code.getBytecodeLength()];
}
SourcePositionTableReader spRead = new SourcePositionTableReader(iter);
spRead.fillBytecodeToPositionMap(pos);
}
}
if (pos != null) {
// fill in gaps
Position last = new Position(0, 0, 0, 0);
for (int i = 0; i < pos.length; i++) {
Position cur = pos[i];
if (cur == null) {
pos[i] = last;
} else {
last = cur;
}
}
}
return pos;
}
private static final int ATTRIBUTE_HEADER_SIZE = 6;
private static final byte[] getData(ClassReader cr, int rawOffset, int rawSize) {
// prepare raw data of attribute to pass to sourceinfo
byte klass[] = cr.getBytes();
int size = rawSize - ATTRIBUTE_HEADER_SIZE;
byte data[] = new byte[size];
System.arraycopy(klass, rawOffset + ATTRIBUTE_HEADER_SIZE, data, 0, size);
return data;
}
private void fillBytecodeToPositionMap(Position[] pos) throws IOException {
byte tableData[] = getData(getClassReader(), getRawOffset(), getRawSize());
CRTable crTable = new CRTable(tableData);
for (int pc = 0; pc < pos.length; pc++) {
Range r = crTable.getSourceInfo(pc);
Position p = convert(r);
pos[pc] = p;
}
}
private final static Position convert(Range r) {
Position pos = null;
if (r != null) {
joana.sourceinfo.Position start = r.getStartPosition();
joana.sourceinfo.Position end = r.getEndPosition();
if (start != null && !start.isUndefined()) {
if (end != null && !end.isUndefined()) {
pos = new Position(start.getLine(), end.getLine(), start.getColumn(), end.getColumn());
} else {
pos = new Position(start.getLine(), start.getLine(), -1, -1);
}
}
}
return pos;
}
public static Position[] makeLineNumberToPositionMap(int[] lineNumberMap) {
Position pos[] = new Position[lineNumberMap.length];
for (int i = 0; i < pos.length; i++) {
int line = lineNumberMap[i];
pos[i] = new Position(line, line, -1, -1);
}
return pos;
}
}