/* * (C) Copyright 2010-2015 SAP SE. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * */ package com.logicalhacking.dasca.crosslanguage.builder import java.io.File import scala.collection.JavaConverters._ import scala.io.Source import scala.{ Option => ? } import com.ibm.wala.dalvik.classLoader.DexIMethod import com.ibm.wala.ipa.callgraph.CallGraph import org.apache.commons.io.FileUtils object DalvikLineNumberCalculator { val MethodRegex = """\s*\.method (.+)""".r val LineRegex = """\s*\.line ([0-9]+)\s*""".r val AnnotationRegex = """\s*\.annotation .+""".r val EndAnnotationRegex = """\s*\.end annotation\s*""".r val InstructionRegex = """\s*[a-zA-Z].*""".r def setLineNumbers(apkUnzipDir: File, cg: CallGraph) = { for ( node <- cg.iterator().asScala; method <- ?(node.getMethod).collect({ case m: DexIMethod => m }) ) { val path = method.getDeclaringClass.getName.toString().substring(1) + ".smali" val smaliFile = new File(new File(apkUnzipDir, "smali"), path) val methodString = method.getReference().getName().toString() + node.getMethod().getReference().getDescriptor() var lastLine = -1 var inCorrectMethod = false var correctMethodFound = false var inAnnotation = false var instCounter = 0 for (line <- FileUtils.readLines(smaliFile).asScala.takeWhile(_ => !correctMethodFound || inCorrectMethod)) line match { case MethodRegex(rest) => { inCorrectMethod = rest.endsWith(methodString) if (inCorrectMethod) correctMethodFound = true } case LineRegex(line) if inCorrectMethod => lastLine = line.toInt case AnnotationRegex() => inAnnotation = true case EndAnnotationRegex() => inAnnotation = false case InstructionRegex() if (inCorrectMethod && !inAnnotation) => { method.setLineNumber(instCounter, lastLine) instCounter += 1 } case _ => } } } }