com.ibm.wala.ipa.cha.IClassHierarchy Java Examples

The following examples show how to use com.ibm.wala.ipa.cha.IClassHierarchy. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: LayoutFileParser.java    From LibScout with Apache License 2.0 6 votes vote down vote up
private IClass getLayoutClass(IClassHierarchy cha, String clazzName) {
	// This is due to the fault-tolerant xml parser
	if (clazzName.equals("view")) clazzName = "View";

	IClass iclazz = null;
	if (iclazz == null)
		iclazz = cha.lookupClass(TypeReference.findOrCreate(ClassLoaderReference.Application, Utils.convertToBrokenDexBytecodeNotation(clazzName)));
	if (iclazz == null && !packageName.isEmpty())
		iclazz = cha.lookupClass(TypeReference.findOrCreate(ClassLoaderReference.Application, Utils.convertToBrokenDexBytecodeNotation(packageName + "." + clazzName)));
	if (iclazz == null)
		iclazz = cha.lookupClass(TypeReference.findOrCreate(ClassLoaderReference.Application, Utils.convertToBrokenDexBytecodeNotation("android.widget." + clazzName)));
	if (iclazz == null)	
		iclazz = cha.lookupClass(TypeReference.findOrCreate(ClassLoaderReference.Application, Utils.convertToBrokenDexBytecodeNotation("android.webkit." + clazzName)));
	if (iclazz == null)
		iclazz = cha.lookupClass(TypeReference.findOrCreate(ClassLoaderReference.Application, Utils.convertToBrokenDexBytecodeNotation("android.view." + clazzName)));
	
	// PreferenceScreen, PreferenceCategory, (i)shape, item, selector, scale, corners, solid .. tags are no classes and thus there will be no corresponding layout class
	if (iclazz == null)	
		logger.trace(Utils.INDENT + "Could not find layout class " + clazzName);

	return iclazz;
}
 
Example #2
Source File: WalaUtils.java    From LibScout with Apache License 2.0 6 votes vote down vote up
public static IMethod getIMethod(IClassHierarchy cha, String signature) {  // TODO: throw exceptions
	String clazzName = Utils.getFullClassName(signature);
	String selector = signature.substring(clazzName.length()+1); 

	try {
		IClass clazz = WalaUtils.lookupClass(cha, clazzName);
		for (IMethod m: clazz.getAllMethods()) { // DeclaredMethods()) -> only impl./overriden methods
			if (m.getSelector().toString().equals(selector)) {
				return m;
			}
		}
	} catch (ClassNotFoundException e) {
		logger.debug("Classname " + clazzName + " could not be looked up!");
	}
	return null;  // TODO: throw exception
}
 
Example #3
Source File: PublicInterfaceExtractor.java    From LibScout with Apache License 2.0 6 votes vote down vote up
public static Set<IMethod> getPublicInterface(IClassHierarchy cha) {
    int classCount = 0;   // how many distinct classes have public methods
    HashSet<IMethod> pubMethods = new HashSet<IMethod>();

    for (IClass clazz: cha) {
        if (!WalaUtils.isAppClass(clazz)) continue;

        Collection<? extends IMethod> methods = clazz.getDeclaredMethods();

        // filter anything but public and non-compiler generated methods
        methods = methods.stream()
                .filter(m -> {
                    int code = AccessFlags.getMethodAccessCode(m);
                    return code > 0 && (code & AccessFlags.getPublicOnlyFilter()) == 0x0;
                })  // if predicate is true, keep in list
                .filter(m -> !(m.isBridge() || m.isSynthetic()))   // filter compiler-generated methods
                .collect(Collectors.toCollection(ArrayList::new));

        if (!methods.isEmpty()) classCount++;
        pubMethods.addAll(methods);
    }

    logger.debug("[getPublicInterface] Retrieved " + pubMethods.size() + " public methods from " + classCount + " distinct classes");
    return pubMethods;
}
 
Example #4
Source File: PublicInterfaceExtractor.java    From LibScout with Apache License 2.0 6 votes vote down vote up
/**
     * Try to programmatically infer the documented public library interface, i.e., the public methods
     * that the app developer is supposed to use.
     * This filter obfuscated names (id-renaming via ProGuard), public method of anonymous inner-classes and
     * public methods in internal packages (based on keywords)
     * @param cha
     * @return
     */
    public static Set<IMethod> getDocumentedPublicInterface(IClassHierarchy cha) {
        Set<IMethod> methods = getPublicInterface(cha);
        int pubApiCount = methods.size();

        methods = methods.stream()
                .filter(m -> !WalaUtils.isAnonymousInnerClass(m.getDeclaringClass()))  // filter pub methods in anonymous inner classes
                .filter(m -> !isSignatureRenamed(m))   // filter obfuscated names
                .filter(m -> !isLibInternalMethod(m))  // is lib internal based on keywords
                .collect(Collectors.toCollection(HashSet::new));

        ArrayList<IMethod> list = new ArrayList<IMethod>(methods);
        list.sort(Comparator.comparing(IMethod::getSignature));


//        list.forEach(m -> logger.debug(Utils.INDENT + "[DocAPI] " + m.getSignature() + (m.getDeclaringClass().isInterface()? "   [IS_IF_METHOD] " : "  ")));
        logger.debug("[getDocumentedPublicInterface] Retrieved " + list.size() + " doc public APIs  (filtered: " + (pubApiCount-list.size()) + " public APIs)");


        // TODO: entrypoint analysis with code?
        // filter other? find lib entry points (calls within the lib?)
        // -> if pub method is never called, likely to be doc api  (or thread->start -> run)

        return methods;
    }
 
Example #5
Source File: AppProfile.java    From LibScout with Apache License 2.0 6 votes vote down vote up
public static AppProfile create(IClassHierarchy cha) {
	long startTime = System.currentTimeMillis();
	
	// generate app package tree
	PackageTree ptree = Profile.generatePackageTree(cha);
	logger.info("- generated app package tree (in " + Utils.millisecondsToFormattedTime(System.currentTimeMillis() - startTime) + ")");
	logger.info("");
	
	// generate app hash trees
	startTime = System.currentTimeMillis();
	List<HashTree> hashTrees = Profile.generateHashTrees(cha);
	logger.info("- generated app hash trees (in " + Utils.millisecondsToFormattedTime(System.currentTimeMillis() - startTime) + ")");
	logger.info("");
	
	return new AppProfile(ptree, hashTrees);
}
 
Example #6
Source File: LibraryApiAnalysis.java    From LibScout with Apache License 2.0 6 votes vote down vote up
private IClassHierarchy createClassHierarchy(File libCodeFile)  throws ClassHierarchyException, IOException, ClassNotFoundException {
    // create analysis scope and generate class hierarchy
    final AnalysisScope scope = AnalysisScope.createJavaAnalysisScope();

    JarFile jf = libCodeFile.getName().endsWith(".aar")? new AarFile(libCodeFile).getJarFile() : new JarFile((libCodeFile));
    scope.addToScope(ClassLoaderReference.Application, jf);
    scope.addToScope(ClassLoaderReference.Primordial, new JarFile(LibScoutConfig.pathToAndroidJar));
    IClassHierarchy cha = ClassHierarchyFactory.makeWithRoot(scope);

    // cleanup tmp files if library input was an .aar file
    if (libCodeFile.getName().endsWith(".aar")) {
        File tmpJar = new File(jf.getName());
        tmpJar.delete();
        logger.trace(Utils.indent() + "tmp jar-file deleted at " + tmpJar.getName());
    }

    return cha;
}
 
Example #7
Source File: LibraryIdentifier.java    From LibScout with Apache License 2.0 6 votes vote down vote up
/**
 * Compute similarity scores for all provided {@link HashTree}.
 * @param cha the {@link IClassHierarchy}
 * @param appProfile  the {@link AppProfile}
 * @param libProfile  the {@link LibProfile}
 * @param lvl  the level of matching to be applied (currently either Package or Class level)
 * @return  a {@link ProfileMatch} for the provided library profile
 * @throws NoSuchAlgorithmException
 */
public ProfileMatch partialMatchForTrees(final IClassHierarchy cha, final AppProfile appProfile, final LibProfile libProfile, final MatchLevel lvl) throws NoSuchAlgorithmException {
	ProfileMatch pMatch = new ProfileMatch(libProfile);
	logger.trace("Partial match of lib: " + libProfile);
	
	// check if library root package is present in app (for validation purposes)
	String rootPackage = libProfile.packageTree.getRootPackage();
	pMatch.libRootPackagePresent = rootPackage == null? false : appProfile.packageTree.containsPackage(rootPackage);
	logger.trace(Utils.INDENT + "Library root package " + rootPackage + " is " + (pMatch.libRootPackagePresent? "" : "not ") + " present in app!");
	 
	// calculate scores for each hash tree
	for (HashTree tree : appProfile.hashTrees) {
		partialMatch(cha, pMatch, tree, appProfile.packageTree, libProfile, lvl);
	}	

	if (logger.isTraceEnabled())
		pMatch.printResults(3);
	return pMatch;
}
 
Example #8
Source File: DefaultPackageNodeComp.java    From LibScout with Apache License 2.0 5 votes vote down vote up
@Override
public PackageNode comp(Collection<? extends Node> classNodes, String packageName, IClassHierarchy cha, TreeConfig config) {

    // default behaviour, just create hash from child nodes
    PackageNode pn = new PackageNode(HashTree.compNode(classNodes, false, config.getHasher()).hash, (config.keepPackageNames? packageName : ""));
    if (!config.pruneClasses) pn.childs = new ArrayList<>(classNodes);

    return pn;
}
 
Example #9
Source File: WalaUtils.java    From LibScout with Apache License 2.0 5 votes vote down vote up
/**
 * Looks up an IClass for a given class name
 * @param cha  a {@link IClassHierarchy}
 * @param clazzName  in java notation, e.g. "de.infsec.MyActivity"
 * @return a {@link IClass} object
 * @throws ClassNotFoundException
 */
public static IClass lookupClass(IClassHierarchy cha, String clazzName) throws ClassNotFoundException {
	if (clazzName == null)
		throw new ClassNotFoundException(Utils.INDENT + "class name is NULL");
	
	String convertedClass = Utils.convertToBrokenDexBytecodeNotation(clazzName);
	IClass iclazz = cha.lookupClass(TypeReference.findOrCreate(ClassLoaderReference.Application, convertedClass));
	
	if (iclazz == null)
		throw new ClassNotFoundException(Utils.INDENT + "[lookupClass] Could'nt lookup IClass for " + clazzName);
	
	return iclazz;
}
 
Example #10
Source File: Profile.java    From LibScout with Apache License 2.0 5 votes vote down vote up
public static PackageTree generatePackageTree(IClassHierarchy cha) {
	logger.info("= PackageTree =");
	PackageTree tree = PackageTree.make(cha, true);
	tree.print(true);
	
	logger.debug("");
	logger.debug("Package names (included classes):");
	Map<String,Integer> pTree = tree.getPackages();
	for (String pkg: pTree.keySet())
		logger.debug(Utils.INDENT + pkg + " (" + pTree.get(pkg) + ")");

	logger.info("");
	
	return tree;
}
 
Example #11
Source File: LibraryApiAnalysis.java    From LibScout with Apache License 2.0 5 votes vote down vote up
private void parseLibrarySDKs(boolean skipBeta) {
    for (File libXML : meta2Code.keySet()) {
        try {
            LibraryDescription ld = XMLParser.readLibraryXML(libXML);

            if (ld.version.matches(".*[a-zA-Z-]+.*") && skipBeta) {  // skip alpha/beta/rc ..
                logger.info("Skip lib: " + ld.name + "   version: " + ld.version);
                continue;
            }

            logger.info("- Parse lib: " + ld.name + "   version: " + ld.version);

            // if stats file not existing add new one
            if (!libName2Stats.containsKey(ld.name))
                libName2Stats.put(ld.name, new LibApiStats(ld.name));

            libName2Stats.get(ld.name).addVersion(ld.version);

            // extract public documented API
            IClassHierarchy cha = createClassHierarchy(meta2Code.get(libXML));
            Set<IMethod> docAPIs = PublicInterfaceExtractor.getDocumentedPublicInterface(cha);
            libName2Stats.get(ld.name).setDocumentedAPIs(ld.version, docAPIs);
            logger.info(Utils.INDENT + "- " + docAPIs.size() + " documented public APIs");

        } catch (Exception e) {
            logger.warn(Utils.stacktrace2Str(e));
        }
    }
}
 
Example #12
Source File: PackageTree.java    From LibScout with Apache License 2.0 5 votes vote down vote up
public static PackageTree make(IClassHierarchy cha, boolean appClassesOnly, Set<String> filteredPackages) {
	PackageTree tree = new PackageTree();
	for (IClass clazz: cha) {
		if (!appClassesOnly || (appClassesOnly && WalaUtils.isAppClass(clazz))) {
			if (filteredPackages == null || !filteredPackages.contains(PackageUtils.getPackageName(clazz)))
				tree.update(clazz);
		}
	}
	return tree;
	
}
 
Example #13
Source File: PackageTree.java    From LibScout with Apache License 2.0 5 votes vote down vote up
public void updateTreeClazzCount(IClassHierarchy cha) {
	Set<String> packages = this.getAllPackages();
	
	for (IClass clazz: cha) {
		if (WalaUtils.isAppClass(clazz)) {
			if (packages.contains(PackageUtils.getPackageName(clazz))) {
				updateClazzCount(clazz);
			}
		}
	}
	
}
 
Example #14
Source File: PackageTree.java    From LibScout with Apache License 2.0 4 votes vote down vote up
public static PackageTree make(IClassHierarchy cha, boolean appClassesOnly) {
	return make(cha, appClassesOnly, null);
}
 
Example #15
Source File: PackageTree.java    From LibScout with Apache License 2.0 4 votes vote down vote up
public static PackageTree make(IClassHierarchy cha) {
	return make(cha, false);
}
 
Example #16
Source File: LayoutFileParser.java    From LibScout with Apache License 2.0 4 votes vote down vote up
public LayoutParser(IClassHierarchy cha, String layoutFile, IClass clazz) {
	this.cha = cha;
	this.layoutFile = layoutFile;
	this.clazz = clazz;
}
 
Example #17
Source File: HashTree.java    From LibScout with Apache License 2.0 4 votes vote down vote up
public void generate(IClassHierarchy cha) {
	logger.debug("Generate hash tree..");

	int classHashCount = 0;
	int methodHashCount = 0;

	// create map package name -> set of clazzNodes
	HashMap<String, List<ClassNode>> packageMap = new HashMap<>();

	for (IClass clazz: cha) {
		if (WalaUtils.isAppClass(clazz)) {

			Collection<? extends IMethod> methods = clazz.getDeclaredMethods();

			// filter methods by access flag
			if (config.accessFlagsFilter != AccessFlags.NO_FLAG) {
				methods = methods.stream()
					.filter(m -> { int code = AccessFlags.getMethodAccessCode(m);  return code > 0 && (code & config.accessFlagsFilter.getValue()) == 0x0; })  // if predicate is true, keep in list
					.collect(Collectors.toCollection(ArrayList::new));
			}

			List<MethodNode> methodNodes = methods.stream()
				 .filter(m -> !(m.isBridge() || m.isSynthetic()))  // normalize java|dex bytecode by skipping compiler-generated methods
				 .map(m -> mnComp.comp(m, config))
				 .sorted(HashUtils.comp)  // sort but do not filter dups
				 .collect(Collectors.toList());

			// normalize - skip classes with no methods
			if (methodNodes.isEmpty()) {
				logger.trace(Utils.INDENT + ">> No methods found for clazz: " + WalaUtils.simpleName(clazz));
				continue;
			}

			// update stats
			methodHashCount += methodNodes.size();
			classHashCount++;

			ClassNode clazzNode = cnComp.comp(methodNodes, clazz, config);

			// keep track on classes per package
			String pckgName = PackageUtils.getPackageName(clazz);
			if (!packageMap.containsKey(pckgName)) {
				packageMap.put(pckgName, new ArrayList<>());
			}
			packageMap.get(pckgName).add(clazzNode);
		}
	}

	packageMap.values().forEach(l -> l.sort(HashUtils.comp));  // sort class nodes
	List<PackageNode> packageNodes = packageMap.keySet().stream()
		.map(p -> pnComp.comp(packageMap.get(p), p, cha, config))
		.sorted(HashUtils.comp)
		.collect(Collectors.toList());

	// generate root
	rootNode = compNode(packageNodes, false, config.getHasher());

	logger.debug(Utils.INDENT + "- generated " + packageNodes.size() + " package hashes.");
	logger.debug(Utils.INDENT + "- generated " + classHashCount    + " clazz hashes.");
	logger.debug(Utils.INDENT + "- generated " + methodHashCount   + " method hashes.");
	logger.debug(Utils.INDENT + "=> Library Hash: " + HashUtils.hash2Str(rootNode.hash));
}
 
Example #18
Source File: LayoutFileParser.java    From LibScout with Apache License 2.0 4 votes vote down vote up
public FragmentParser(IClassHierarchy cha, String layoutFile, IClass viewClazz) {
	super(cha, layoutFile, viewClazz);
}
 
Example #19
Source File: WalaUtils.java    From LibScout with Apache License 2.0 4 votes vote down vote up
public static AndroidClassType classifyClazz(IClassHierarchy cha, String clazzName) throws ClassNotFoundException {
	IClass ic = lookupClass(cha, clazzName);
	return classifyClazz(ic);
}
 
Example #20
Source File: Profile.java    From LibScout with Apache License 2.0 4 votes vote down vote up
public static List<HashTree> generateHashTrees(final IClassHierarchy cha) {
	HashTree ht = new HashTree();
	ht.generate(cha);
	return Collections.singletonList(ht);
}
 
Example #21
Source File: LibraryProfiler.java    From LibScout with Apache License 2.0 4 votes vote down vote up
private void extractFingerPrints() throws IOException, ClassHierarchyException, ClassNotFoundException {
	long starttime = System.currentTimeMillis();
	
	logger.info("Process library: " + libraryFile.getName());
	logger.info("Library description:");
	for (String desc: libDesc.getDescription())
		logger.info(desc);
	
	// create analysis scope and generate class hierarchy
	final AnalysisScope scope = AnalysisScope.createJavaAnalysisScope();
	
	JarFile jf = libraryFile.getName().endsWith(".aar")? new AarFile(libraryFile).getJarFile() : new JarFile(libraryFile); 
	scope.addToScope(ClassLoaderReference.Application, jf);
	scope.addToScope(ClassLoaderReference.Primordial, new JarFile(LibScoutConfig.pathToAndroidJar));

	IClassHierarchy cha = ClassHierarchyFactory.makeWithRoot(scope);
	WalaUtils.getChaStats(cha);
	
	// cleanup tmp files if library input was an .aar file
	if (libraryFile.getName().endsWith(".aar")) {
		File tmpJar = new File(jf.getName());
		tmpJar.delete();
		logger.debug(Utils.indent() + "tmp jar-file deleted at " + tmpJar.getName());
	}
	
	PackageTree pTree = Profile.generatePackageTree(cha);
	if (pTree.getRootPackage() == null) {
		logger.warn(Utils.INDENT + "Library contains multiple root packages");
	}

	List<HashTree> hTrees = Profile.generateHashTrees(cha);

	// if hash tree is empty do not dump a profile
	if (hTrees.isEmpty() || hTrees.get(0).getNumberOfClasses() == 0) {
		logger.error("Empty Hash Tree generated - SKIP");
		return;
	}

	// write profile to disk
	serialize(pTree, hTrees);

	logger.info("");
	logger.info("Processing time: " + Utils.millisecondsToFormattedTime(System.currentTimeMillis() - starttime));
}
 
Example #22
Source File: DefinitelyDerefedParamsDriver.java    From NullAway with MIT License 4 votes vote down vote up
private void analyzeFile(String pkgName, String inPath, boolean includeNonPublicClasses)
    throws IOException, ClassHierarchyException {
  InputStream jarIS = null;
  if (inPath.endsWith(".jar") || inPath.endsWith(".aar")) {
    jarIS = getInputStream(inPath);
    if (jarIS == null) {
      return;
    }
  } else if (!new File(inPath).exists()) {
    return;
  }
  AnalysisScope scope = AnalysisScopeReader.makePrimordialScope(null);
  scope.setExclusions(
      new FileOfClasses(
          new ByteArrayInputStream(DEFAULT_EXCLUSIONS.getBytes(StandardCharsets.UTF_8))));
  if (jarIS != null) scope.addInputStreamForJarToScope(ClassLoaderReference.Application, jarIS);
  else AnalysisScopeReader.addClassPathToScope(inPath, scope, ClassLoaderReference.Application);
  AnalysisOptions options = new AnalysisOptions(scope, null);
  AnalysisCache cache = new AnalysisCacheImpl();
  IClassHierarchy cha = ClassHierarchyFactory.makeWithRoot(scope);
  Warnings.clear();

  // Iterate over all classes:methods in the 'Application' and 'Extension' class loaders
  for (IClassLoader cldr : cha.getLoaders()) {
    if (!cldr.getName().toString().equals("Primordial")) {
      for (IClass cls : Iterator2Iterable.make(cldr.iterateAllClasses())) {
        if (cls instanceof PhantomClass) continue;
        // Only process classes in specified classpath and not its dependencies.
        // TODO: figure the right way to do this
        if (!pkgName.isEmpty() && !cls.getName().toString().startsWith(pkgName)) continue;
        // Skip non-public / ABI classes
        if (!cls.isPublic() && !includeNonPublicClasses) continue;
        LOG(DEBUG, "DEBUG", "analyzing class: " + cls.getName().toString());
        for (IMethod mtd : Iterator2Iterable.make(cls.getDeclaredMethods().iterator())) {
          // Skip methods without parameters, abstract methods, native methods
          // some Application classes are Primordial (why?)
          if (shouldCheckMethod(mtd)) {
            Preconditions.checkNotNull(mtd, "method not found");
            DefinitelyDerefedParams analysisDriver = null;
            String sign = "";
            // Parameter analysis
            if (mtd.getNumberOfParameters() > (mtd.isStatic() ? 0 : 1)) {
              // Skip methods by looking at bytecode
              try {
                if (!CodeScanner.getFieldsRead(mtd).isEmpty()
                    || !CodeScanner.getFieldsWritten(mtd).isEmpty()
                    || !CodeScanner.getCallSites(mtd).isEmpty()) {
                  analysisDriver = getAnalysisDriver(mtd, options, cache);
                  Set<Integer> result = analysisDriver.analyze();
                  sign = getSignature(mtd);
                  LOG(DEBUG, "DEBUG", "analyzed method: " + sign);
                  if (!result.isEmpty() || DEBUG) {
                    nonnullParams.put(sign, result);
                    LOG(
                        DEBUG,
                        "DEBUG",
                        "Inferred Nonnull param for method: " + sign + " = " + result.toString());
                  }
                }
              } catch (Exception e) {
                LOG(
                    DEBUG,
                    "DEBUG",
                    "Exception while scanning bytecodes for " + mtd + " " + e.getMessage());
              }
            }
            analyzeReturnValue(options, cache, mtd, analysisDriver, sign);
          }
        }
      }
    }
  }
  long endTime = System.currentTimeMillis();
  LOG(
      VERBOSE,
      "Stats",
      inPath
          + " >> time(ms): "
          + (endTime - analysisStartTime)
          + ", bytecode size: "
          + analyzedBytes
          + ", rate (ms/KB): "
          + (analyzedBytes > 0 ? (((endTime - analysisStartTime) * 1000) / analyzedBytes) : 0));
}
 
Example #23
Source File: AnalysisContext.java    From fasten with Apache License 2.0 4 votes vote down vote up
/**
 * Construct analysis context.
 *
 * @param cha Class hierarchy analysis
 */
public AnalysisContext(final IClassHierarchy cha) {
    this.internalDictionary = new HashMap<>();
    this.externalDictionary = new HashMap<>();
    this.artifactResolver = new ArtifactResolver(cha);
}
 
Example #24
Source File: EntryPointsGenerator.java    From fasten with Apache License 2.0 4 votes vote down vote up
public EntryPointsGenerator(final IClassHierarchy cha) {
    this.cha = cha;
}
 
Example #25
Source File: ArtifactResolver.java    From fasten with Apache License 2.0 2 votes vote down vote up
/**
 * Construct artifact resolver.
 *
 * @param cha Class hierarchy
 */
public ArtifactResolver(final IClassHierarchy cha) {
    this.cha = cha;
}
 
Example #26
Source File: IPackageNodeComp.java    From LibScout with Apache License 2.0 votes vote down vote up
PackageNode comp(Collection<? extends Node> classNodes, String packageName, IClassHierarchy cha, TreeConfig config);