use of com.taobao.android.dx.rop.annotation.AnnotationsList in project atlas by alibaba.
the class CfTranslator method processMethods.
/**
* Processes the methods of the given class.
*
* @param cf {@code non-null;} class being translated
* @param cfOptions {@code non-null;} options for class translation
* @param dexOptions {@code non-null;} options for dex output
* @param out {@code non-null;} output class
* @param dexFile {@code non-null;} dex output
*/
private static void processMethods(DirectClassFile cf, CfOptions cfOptions, DexOptions dexOptions, OptimizerOptions optimizerOptions, ClassDefItem out, DexFile dexFile) {
CstType thisClass = cf.getThisClass();
MethodList methods = cf.getMethods();
int sz = methods.size();
for (int i = 0; i < sz; i++) {
Method one = methods.get(i);
try {
CstMethodRef meth = new CstMethodRef(thisClass, one.getNat());
int accessFlags = one.getAccessFlags();
boolean isStatic = AccessFlags.isStatic(accessFlags);
boolean isPrivate = AccessFlags.isPrivate(accessFlags);
boolean isNative = AccessFlags.isNative(accessFlags);
boolean isAbstract = AccessFlags.isAbstract(accessFlags);
boolean isConstructor = meth.isInstanceInit() || meth.isClassInit();
DalvCode code;
if (isNative || isAbstract) {
// There's no code for native or abstract methods.
code = null;
} else {
ConcreteMethod concrete = new ConcreteMethod(one, cf, (cfOptions.positionInfo != PositionList.NONE), cfOptions.localInfo);
TranslationAdvice advice;
advice = DexTranslationAdvice.THE_ONE;
RopMethod rmeth = Ropper.convert(concrete, advice, methods);
RopMethod nonOptRmeth = null;
int paramSize;
paramSize = meth.getParameterWordCount(isStatic);
String canonicalName = thisClass.getClassType().getDescriptor() + "." + one.getName().getString();
if (cfOptions.optimize && optimizerOptions.shouldOptimize(canonicalName)) {
if (DEBUG) {
System.err.println("Optimizing " + canonicalName);
}
nonOptRmeth = rmeth;
rmeth = new Optimizer().optimize(rmeth, paramSize, isStatic, cfOptions.localInfo, advice);
if (DEBUG) {
OptimizerOptions.compareOptimizerStep(nonOptRmeth, paramSize, isStatic, cfOptions, advice, rmeth);
}
if (cfOptions.statistics) {
cfOptions.codeStatistics.updateRopStatistics(nonOptRmeth, rmeth);
}
}
LocalVariableInfo locals = null;
if (cfOptions.localInfo) {
locals = LocalVariableExtractor.extract(rmeth);
}
code = RopTranslator.translate(rmeth, cfOptions.positionInfo, locals, paramSize, dexOptions);
if (cfOptions.statistics && nonOptRmeth != null) {
updateDexStatistics(cfOptions, dexOptions, rmeth, nonOptRmeth, locals, paramSize, concrete.getCode().size());
}
}
// Preserve the synchronized flag as its "declared" variant...
if (AccessFlags.isSynchronized(accessFlags)) {
accessFlags |= AccessFlags.ACC_DECLARED_SYNCHRONIZED;
/*
* ...but only native methods are actually allowed to be
* synchronized.
*/
if (!isNative) {
accessFlags &= ~AccessFlags.ACC_SYNCHRONIZED;
}
}
if (isConstructor) {
accessFlags |= AccessFlags.ACC_CONSTRUCTOR;
}
TypeList exceptions = AttributeTranslator.getExceptions(one);
EncodedMethod mi = new EncodedMethod(meth, accessFlags, code, exceptions);
if (meth.isInstanceInit() || meth.isClassInit() || isStatic || isPrivate) {
out.addDirectMethod(mi);
} else {
out.addVirtualMethod(mi);
}
Annotations annotations = AttributeTranslator.getMethodAnnotations(one);
if (annotations.size() != 0) {
if (list.contains(meth.toString())) {
System.out.println(meth.toString());
} else {
list.add(meth.toString());
}
out.addMethodAnnotations(meth, annotations, dexFile);
}
AnnotationsList list = AttributeTranslator.getParameterAnnotations(one);
if (list.size() != 0) {
out.addParameterAnnotations(meth, list, dexFile);
}
dexFile.getMethodIds().intern(meth);
} catch (RuntimeException ex) {
String msg = "...while processing " + one.getName().toHuman() + " " + one.getDescriptor().toHuman();
throw ExceptionWithContext.withContext(ex, msg);
}
}
}
use of com.taobao.android.dx.rop.annotation.AnnotationsList in project atlas by alibaba.
the class Main method dumpMethod.
/**
* Dumps any method with the given name in the given file.
*
* @param dex {@code non-null;} the dex file
* @param fqName {@code non-null;} the fully-qualified name of the
* method(s)
* @param out {@code non-null;} where to dump to
*/
private void dumpMethod(DexFile dex, String fqName, OutputStreamWriter out) {
boolean wildcard = fqName.endsWith("*");
int lastDot = fqName.lastIndexOf('.');
if ((lastDot <= 0) || (lastDot == (fqName.length() - 1))) {
DxConsole.err.println("bogus fully-qualified method name: " + fqName);
return;
}
String className = fqName.substring(0, lastDot).replace('.', '/');
String methodName = fqName.substring(lastDot + 1);
ClassDefItem clazz = dex.getClassOrNull(className);
if (clazz == null) {
DxConsole.err.println("no such class: " + className);
return;
}
if (wildcard) {
methodName = methodName.substring(0, methodName.length() - 1);
}
ArrayList<EncodedMethod> allMeths = clazz.getMethods();
TreeMap<CstNat, EncodedMethod> meths = new TreeMap<CstNat, EncodedMethod>();
/*
* Figure out which methods to include in the output, and get them
* all sorted, so that the printout code is robust with respect to
* changes in the underlying order.
*/
for (EncodedMethod meth : allMeths) {
String methName = meth.getName().getString();
if ((wildcard && methName.startsWith(methodName)) || (!wildcard && methName.equals(methodName))) {
meths.put(meth.getRef().getNat(), meth);
}
}
if (meths.size() == 0) {
DxConsole.err.println("no such method: " + fqName);
return;
}
PrintWriter pw = new PrintWriter(out);
for (EncodedMethod meth : meths.values()) {
// TODO: Better stuff goes here, perhaps.
meth.debugPrint(pw, args.verboseDump);
/*
* The (default) source file is an attribute of the class, but
* it's useful to see it in method dumps.
*/
CstString sourceFile = clazz.getSourceFile();
if (sourceFile != null) {
pw.println(" source file: " + sourceFile.toQuoted());
}
Annotations methodAnnotations = clazz.getMethodAnnotations(meth.getRef());
AnnotationsList parameterAnnotations = clazz.getParameterAnnotations(meth.getRef());
if (methodAnnotations != null) {
pw.println(" method annotations:");
for (Annotation a : methodAnnotations.getAnnotations()) {
pw.println(" " + a);
}
}
if (parameterAnnotations != null) {
pw.println(" parameter annotations:");
int sz = parameterAnnotations.size();
for (int i = 0; i < sz; i++) {
pw.println(" parameter " + i);
Annotations annotations = parameterAnnotations.get(i);
for (Annotation a : annotations.getAnnotations()) {
pw.println(" " + a);
}
}
}
}
pw.flush();
}
use of com.taobao.android.dx.rop.annotation.AnnotationsList in project atlas by alibaba.
the class AnnotationParser method parseAnnotationsList.
/**
* Parses a list of annotation lists.
*
* @param visibility {@code non-null;} visibility of the parsed annotations
* @return {@code non-null;} the list of annotation lists read from the attribute
* data
*/
private AnnotationsList parseAnnotationsList(AnnotationVisibility visibility) throws IOException {
int count = input.readUnsignedByte();
if (observer != null) {
parsed(1, "num_parameters: " + Hex.u1(count));
}
AnnotationsList outerList = new AnnotationsList(count);
for (int i = 0; i < count; i++) {
if (observer != null) {
parsed(0, "parameter_annotations[" + i + "]:");
changeIndent(1);
}
Annotations annotations = parseAnnotations(visibility);
outerList.set(i, annotations);
if (observer != null) {
observer.changeIndent(-1);
}
}
outerList.setImmutable();
return outerList;
}
use of com.taobao.android.dx.rop.annotation.AnnotationsList in project atlas by alibaba.
the class CfTranslator method processMethods.
/**
* Processes the methods of the given class.
*
* @param cf {@code non-null;} class being translated
* @param cfOptions {@code non-null;} options for class translation
* @param dexOptions {@code non-null;} options for dex output
* @param out {@code non-null;} output class
* @param dexFile {@code non-null;} dex output
*/
private static void processMethods(DirectClassFile cf, CfOptions cfOptions, DexOptions dexOptions, ClassDefItem out, DexFile dexFile) {
CstType thisClass = cf.getThisClass();
MethodList methods = cf.getMethods();
int sz = methods.size();
for (int i = 0; i < sz; i++) {
Method one = methods.get(i);
try {
CstMethodRef meth = new CstMethodRef(thisClass, one.getNat());
int accessFlags = one.getAccessFlags();
boolean isStatic = AccessFlags.isStatic(accessFlags);
boolean isPrivate = AccessFlags.isPrivate(accessFlags);
boolean isNative = AccessFlags.isNative(accessFlags);
boolean isAbstract = AccessFlags.isAbstract(accessFlags);
boolean isConstructor = meth.isInstanceInit() || meth.isClassInit();
DalvCode code;
if (isNative || isAbstract) {
// There's no code for native or abstract methods.
code = null;
} else {
ConcreteMethod concrete = new ConcreteMethod(one, cf, (cfOptions.positionInfo != PositionList.NONE), cfOptions.localInfo);
TranslationAdvice advice;
advice = DexTranslationAdvice.THE_ONE;
RopMethod rmeth = Ropper.convert(concrete, advice, methods);
RopMethod nonOptRmeth = null;
int paramSize;
paramSize = meth.getParameterWordCount(isStatic);
String canonicalName = thisClass.getClassType().getDescriptor() + "." + one.getName().getString();
if (cfOptions.optimize && OptimizerOptions.shouldOptimize(canonicalName)) {
if (DEBUG) {
System.err.println("Optimizing " + canonicalName);
}
nonOptRmeth = rmeth;
rmeth = Optimizer.optimize(rmeth, paramSize, isStatic, cfOptions.localInfo, advice);
if (DEBUG) {
OptimizerOptions.compareOptimizerStep(nonOptRmeth, paramSize, isStatic, cfOptions, advice, rmeth);
}
if (cfOptions.statistics) {
CodeStatistics.updateRopStatistics(nonOptRmeth, rmeth);
}
}
LocalVariableInfo locals = null;
if (cfOptions.localInfo) {
locals = LocalVariableExtractor.extract(rmeth);
}
code = RopTranslator.translate(rmeth, cfOptions.positionInfo, locals, paramSize, dexOptions);
if (cfOptions.statistics && nonOptRmeth != null) {
updateDexStatistics(cfOptions, dexOptions, rmeth, nonOptRmeth, locals, paramSize, concrete.getCode().size());
}
}
// Preserve the synchronized flag as its "declared" variant...
if (AccessFlags.isSynchronized(accessFlags)) {
accessFlags |= AccessFlags.ACC_DECLARED_SYNCHRONIZED;
/*
* ...but only native methods are actually allowed to be
* synchronized.
*/
if (!isNative) {
accessFlags &= ~AccessFlags.ACC_SYNCHRONIZED;
}
}
if (isConstructor) {
accessFlags |= AccessFlags.ACC_CONSTRUCTOR;
}
TypeList exceptions = AttributeTranslator.getExceptions(one);
EncodedMethod mi = new EncodedMethod(meth, accessFlags, code, exceptions);
if (meth.isInstanceInit() || meth.isClassInit() || isStatic || isPrivate) {
out.addDirectMethod(mi);
} else {
out.addVirtualMethod(mi);
}
Annotations annotations = AttributeTranslator.getMethodAnnotations(one);
if (annotations.size() != 0) {
out.addMethodAnnotations(meth, annotations, dexFile);
}
AnnotationsList list = AttributeTranslator.getParameterAnnotations(one);
if (list.size() != 0) {
out.addParameterAnnotations(meth, list, dexFile);
}
dexFile.getMethodIds().intern(meth);
} catch (RuntimeException ex) {
String msg = "...while processing " + one.getName().toHuman() + " " + one.getDescriptor().toHuman();
throw ExceptionWithContext.withContext(ex, msg);
}
}
}
use of com.taobao.android.dx.rop.annotation.AnnotationsList in project atlas by alibaba.
the class StdAttributeFactory method runtimeVisibleParameterAnnotations.
/**
* Parses a {@code RuntimeVisibleParameterAnnotations} attribute.
*/
private Attribute runtimeVisibleParameterAnnotations(DirectClassFile cf, int offset, int length, ParseObserver observer) {
if (length < 2) {
throwSeverelyTruncated();
}
AnnotationParser ap = new AnnotationParser(cf, offset, length, observer);
AnnotationsList list = ap.parseParameterAttribute(AnnotationVisibility.RUNTIME);
return new AttRuntimeVisibleParameterAnnotations(list, length);
}
Aggregations