-
Notifications
You must be signed in to change notification settings - Fork 224
Mapping to source code
Some notes on mapping back to source when analyzing bytecode. This does not include the CAst functionality.
This page is incomplete.
Note that IClass
has a method getSourceFileName()
. The
ClassLoaderImpl
attempts to set up a mapping between IClasses and
source files during class loading. After loading all classes, the class
loader goes back and looks at each .java
file in the scope, and maps
it to a loaded IClass
. So, in order to use getSourceFileName()
, be
sure to include the source files in the analysis scope.
If the information is available, you can retrieve it via
IR.getLocalNames()
. Note that not every value number corresponds to a
local variable in Java source code. Some value numbers may represent
multiple local variables, as a result of copy propagation during IR
construction.
Given the index i
of some SSAInstruction
in an IR ir
produced from
bytecode, you can get the corresponding bytecode index and source line
number as follows:
IBytecodeMethod method = (IBytecodeMethod)ir.getMethod();
int bytecodeIndex = method.getBytecodeIndex(i);
int sourceLineNum = method.getLineNumber(bytecodeIndex);
Note that source line information may not always be available.
Given a Statement
that came from a Java bytecode file (via Shrike),
you can get the line number in the original source with the following:
if (s.getKind() == Statement.Kind.NORMAL) { // ignore special kinds of statements
int bcIndex, instructionIndex = ((NormalStatement) s).getInstructionIndex();
try {
bcIndex = ((ShrikeBTMethod) s.getNode().getMethod()).getBytecodeIndex(instructionIndex);
try {
int src_line_number = s.getNode().getMethod().getLineNumber(bcIndex);
System.err.println ( "Source line number = " + src_line_number );
} catch (Exception e) {
System.err.println("Bytecode index no good");
System.err.println(e.getMessage());
}
} catch (Exception e ) {
System.err.println("it's probably not a BT method (e.g. it's a fakeroot method)");
System.err.println(e.getMessage());
}
}
For Statement
s that came from a Java source file thru cast, there is
no bytecode index, so (despite what the javadoc may lead you to believe)
the parameter to getLineNumber()
is simply an instruction index:
if (s.getKind() == Statement.Kind.NORMAL) {
int instructionIndex = ((NormalStatement) s).getInstructionIndex();
int lineNum = ((ConcreteJavaMethod) s.getNode().getMethod()).getLineNumber(instructionIndex);
System.out.println("Source line number = " + lineNum );
}
This is useful when investigating the output of slicing.
If you have an IClass klass representing a .class file inside a .jar, you can do the following to figure out the .jar file name:
ShrikeClass shrikeKlass = (ShrikeClass) klass;
JarFileEntry moduleEntry = (JarFileEntry) shrikeKlass.getModuleEntry();
String jarFile = moduleEntry.getJarFile();
Note that the casts may fail if it's not a .class file inside a .jar.