Merge branch 'master' into smalidea3

This commit is contained in:
Ben Gruver 2015-03-04 20:58:14 -08:00
commit 8c1d8ddef2
18 changed files with 136 additions and 244 deletions

3
.gitignore vendored
View File

@ -5,3 +5,6 @@
/dexlib2/accessorTestGenerator/build
/smali/build
/util/build
*.iml
*.ipr
*.iws

50
NOTICE
View File

@ -85,56 +85,6 @@ limitations under the License.
*******************************************************************************
The smali mojo plugin is (very loosely) based on an unknown mojo plugin with
the following license:
*******************************************************************************
Copyright 2001-2005 The Apache Software Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*******************************************************************************
The RadixTree implementation in the "util" project is taken from
http://code.google.com/p/radixtree/ (version .3), and is used with minor
modifications in accordance with the following license:
*******************************************************************************
The MIT License
Copyright (c) 2008 Tahseen Ur Rehman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*******************************************************************************
Some parts of the smalidea plugin are based on code from the IDEA project, per the
following license

View File

@ -29,8 +29,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
configurations {
proguard
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath depends.proguard_gradle
}
}
dependencies {
@ -41,8 +46,6 @@ dependencies {
testCompile depends.junit
testCompile project(':smali')
proguard depends.proguard
}
processResources.inputs.property('version', version)
@ -59,11 +62,11 @@ task fatJar(type: Jar) {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest {
attributes("Main-Class": "org.jf.baksmali.main")
attributes('Main-Class': 'org.jf.baksmali.main')
}
doLast {
if (!System.getProperty("os.name").toLowerCase().contains("windows")) {
if (!System.getProperty('os.name').toLowerCase().contains('windows')) {
ant.symlink(link: file("${destinationDir}/baksmali.jar"), resource: archivePath, overwrite: true)
}
}
@ -81,22 +84,22 @@ uploadArchives {
}
}
task proguard(type: JavaExec, dependsOn: fatJar) {
task proguard(type: proguard.gradle.ProGuardTask, dependsOn: fatJar) {
def outFile = fatJar.destinationDir.getPath() + '/' + fatJar.baseName + '-' + fatJar.version + '-small' + '.' + fatJar.extension
inputs.file fatJar.archivePath
outputs.file outFile
classpath = configurations.proguard
main = 'proguard.ProGuard'
args '-injars ' + fatJar.archivePath
args '-outjars ' + outFile
args '-libraryjars ' + System.properties['java.home'] + '/lib/rt.jar'
args '-dontobfuscate'
args '-dontoptimize'
args '-keep public class org.jf.baksmali.main { public static void main(java.lang.String[]); }'
args '-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); }'
args '-dontwarn com.google.common.**'
args '-dontnote com.google.common.**'
injars fatJar.archivePath
outjars outFile
libraryjars "${System.properties['java.home']}/lib/rt.jar"
dontobfuscate
dontoptimize
keep 'public class org.jf.baksmali.main { public static void main(java.lang.String[]); }'
keepclassmembers 'enum * { public static **[] values(); public static ** valueOf(java.lang.String); }'
dontwarn 'com.google.common.**'
dontnote 'com.google.common.**'
}
tasks.getByPath(':release').dependsOn(proguard)

View File

@ -39,7 +39,7 @@ if (!('release' in gradle.startParameter.taskNames)) {
def versionSuffix
try {
def git = org.eclipse.jgit.api.Git.open(file('.'))
def head = git.getRepository().getRef("HEAD")
def head = git.getRepository().getRef('HEAD')
versionSuffix = head.getObjectId().abbreviate(8).name()
if (!git.status().call().clean) {
@ -90,7 +90,8 @@ subprojects {
stringtemplate: 'org.antlr:stringtemplate:3.2.1',
commons_cli: 'commons-cli:commons-cli:1.2',
jflex: 'de.jflex:jflex:1.4.3',
proguard: 'net.sf.proguard:proguard-base:4.8'
jflex_plugin: 'co.tomlee.gradle.plugins:gradle-jflex-plugin:0.0.1',
proguard_gradle: 'net.sf.proguard:proguard-gradle:5.1'
]
}
@ -124,7 +125,7 @@ subprojects {
}
signing {
required { gradle.taskGraph.hasTask("uploadArchives") }
required { gradle.taskGraph.hasTask('uploadArchives') }
sign configurations.archives
}
@ -135,7 +136,7 @@ subprojects {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
if (rootProject.hasProperty('sonatypeUsername') && rootProject.hasProperty('sonatypePassword')) {
repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2/') {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
}
@ -182,5 +183,5 @@ buildscript {
}
task wrapper(type: Wrapper) {
gradleVersion = '1.10'
gradleVersion = '2.3'
}

View File

@ -39,4 +39,6 @@ LOCAL_SHARED_LIBRARIES := libdl
LOCAL_MODULE_TAGS := optional
LOCAL_LDFLAGS := -Wl,--hash-style=sysv
include $(BUILD_EXECUTABLE)

View File

@ -46,37 +46,6 @@ dependencies {
ext.testAccessorOutputDir = file("${buildDir}/generated-accessor-test-sources")
ext.testAccessorOutputFile = file("${buildDir}/generated-accessor-test-sources/org/jf/dexlib2/AccessorTypes.java")
sourceSets {
// The sources for building the test dex file for the accessor test
accessorTestDex {
java {
srcDir testAccessorOutputDir
}
}
// The sources for the accessor test itself
accessorTest {
java {
compileClasspath += main.output
runtimeClasspath += main.output
}
}
}
configurations {
accessorTestDexCompile.extendsFrom compile
accessorTestDexRuntime.extendsFrom runtime
accessorTestCompile.extendsFrom testCompile
accessorTestRuntime.extendsFrom testRuntime
}
idea {
module {
testSourceDirs += sourceSets.accessorTest.java.srcDirs
}
}
// You must manually execute this task to regenerate SyntheticAccessorFSM.java, after modifying the ragel file
// e.g. ./gradlew ragel
task ragel(type:Exec) {
@ -87,36 +56,47 @@ task ragel(type:Exec) {
}
task generateAccessorTestSource(type: JavaExec) {
outputs.dir file(testAccessorOutputDir)
doFirst {
file(testAccessorOutputFile.parent).mkdirs()
}
mkdir(file(testAccessorOutputFile).parent)
outputs.dir file(testAccessorOutputDir)
sourceSets['test'].java.srcDir file(testAccessorOutputDir)
classpath = configurations.accessorTestGenerator
main = 'org.jf.dexlib2.AccessorTestGenerator'
args testAccessorOutputFile
}
compileAccessorTestDexJava.dependsOn(generateAccessorTestSource)
compileTestJava.dependsOn generateAccessorTestSource
task generateAccessorTestDex(type: Exec, dependsOn: compileAccessorTestDexJava) {
def outputDex = file("${sourceSets.accessorTest.output.resourcesDir}/accessorTest.dex")
mkdir(outputDex.parent)
task generateAccessorTestDex(type: Exec, dependsOn: compileTestJava) {
def outputDex = file(new File(sourceSets.test.output.resourcesDir, 'accessorTest.dex'))
inputs.dir project.sourceSets.accessorTestDex.output.classesDir
doFirst {
file(outputDex.parent).mkdirs()
}
inputs.dir(project.sourceSets.test.output.classesDir)
outputs.file outputDex
sourceSets.accessorTest.resources
workingDir project.sourceSets.accessorTestDex.output.classesDir
workingDir project.sourceSets.test.output.classesDir
executable 'dx'
args '--dex'
args '--no-strict'
args "--output=${outputDex}"
args '.'
}
task accessorTest(type: Test, dependsOn: generateAccessorTestDex) {
testClassesDir = project.sourceSets.accessorTest.output.classesDir
classpath = project.sourceSets.accessorTest.runtimeClasspath
doFirst {
// this has to be done in doFirst, so that the generated classes will be available.
// otherwise, it the tree will be populated while the build is being configured,
// which is before the compileTestJava has run
fileTree(project.sourceSets.test.output.classesDir) {
include 'org/jf/dexlib2/AccessorTypes*.class'
}.each { File file ->
args file
}
}
}
test.dependsOn generateAccessorTestDex
uploadArchives {
repositories.mavenDeployer {

View File

@ -576,6 +576,9 @@ public abstract class DexWriter<
private void writeAnnotationSets(@Nonnull DexDataWriter writer) throws IOException {
writer.align();
annotationSetSectionOffset = writer.getPosition();
if (shouldCreateEmptyAnnotationSet()) {
writer.writeInt(0);
}
for (Map.Entry<? extends AnnotationSetKey, Integer> entry: annotationSetSection.getItems()) {
Collection<? extends AnnotationKey> annotations = Ordering.from(BaseAnnotation.BY_TYPE)
.immutableSortedCopy(annotationSetSection.getAnnotations(entry.getKey()));
@ -613,6 +616,8 @@ public abstract class DexWriter<
for (AnnotationSetKey annotationSetKey: parameterAnnotations) {
if (annotationSetSection.getAnnotations(annotationSetKey).size() > 0) {
writer.writeInt(annotationSetSection.getItemOffset(annotationSetKey));
} else if (shouldCreateEmptyAnnotationSet()) {
writer.writeInt(annotationSetSectionOffset);
} else {
writer.writeInt(NO_OFFSET);
}
@ -1115,7 +1120,7 @@ public abstract class DexWriter<
if (annotationSection.getItems().size() > 0) {
numItems++;
}
if (annotationSetSection.getItems().size() > 0) {
if (annotationSetSection.getItems().size() > 0 || shouldCreateEmptyAnnotationSet()) {
numItems++;
}
if (numAnnotationSetRefItems > 0) {
@ -1163,8 +1168,8 @@ public abstract class DexWriter<
writeMapItem(writer, ItemType.TYPE_LIST, typeListSection.getItems().size(), typeListSectionOffset);
writeMapItem(writer, ItemType.ENCODED_ARRAY_ITEM, numEncodedArrayItems, encodedArraySectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_ITEM, annotationSection.getItems().size(), annotationSectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_SET_ITEM, annotationSetSection.getItems().size(),
annotationSetSectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_SET_ITEM,
annotationSetSection.getItems().size() + (shouldCreateEmptyAnnotationSet() ? 1 : 0), annotationSetSectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_SET_REF_LIST, numAnnotationSetRefItems, annotationSetRefSectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_DIRECTORY_ITEM, numAnnotationDirectoryItems,
annotationDirectorySectionOffset);
@ -1226,4 +1231,11 @@ public abstract class DexWriter<
writer.writeInt(0);
}
}
private boolean shouldCreateEmptyAnnotationSet() {
// Workaround for a crash in Dalvik VM before Jelly Bean MR1 (4.2)
// which is triggered by NO_OFFSET in parameter annotation list.
// (https://code.google.com/p/android/issues/detail?id=35304)
return (api < 17);
}
}

View File

@ -1 +1,2 @@
org.gradle.daemon=true
org.gradle.parallel=true

Binary file not shown.

View File

@ -1,6 +1,6 @@
#Sun Feb 02 12:47:14 PST 2014
#Sun Mar 01 19:20:47 PST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-all.zip

View File

@ -29,25 +29,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
configurations {
antlr3
jflex
proguard
apply plugin: 'antlr'
apply plugin: 'jflex'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath depends.jflex_plugin
classpath depends.proguard_gradle
}
}
ext.antlrSource = 'src/main/antlr3'
ext.antlrOutput = file("${buildDir}/generated-sources/antlr3")
configurations {
// Remove the full antlr library that's added by the antlr plugin. We manually
// add the smaller antlr_runtime library instead
compile.exclude group: 'org.antlr', module: 'antlr'
ext.jflexSource = "src/main/jflex"
ext.jflexOutput = file("${buildDir}/generated-sources/jflex")
ext.testAntlrSource = 'src/test/antlr3'
ext.testAntlrOutput = file("${buildDir}/generated-test-sources/antlr3")
sourceSets.main.java.srcDir antlrOutput
sourceSets.main.java.srcDir jflexOutput
sourceSets.test.java.srcDir testAntlrOutput
// The jflex lexer doesn't have any runtime dependencies, so remove the dependency
// that gets added by the jflex plugin
compile.exclude group: 'de.jflex', module: 'jflex'
}
idea {
module {
@ -73,68 +76,10 @@ dependencies {
testCompile depends.junit
antlr3 depends.antlr
antlr depends.antlr
jflex depends.jflex
proguard depends.proguard
}
task generateParserAntlrSource(type: JavaExec) {
inputs.dir file(antlrSource)
outputs.dir file(antlrOutput)
mkdir(antlrOutput)
def grammars = fileTree(antlrSource).include('**/smaliParser.g')
classpath = configurations.antlr3
main = 'org.antlr.Tool'
args '-fo', relativePath("${antlrOutput}/org/jf/smali")
args grammars.files
}
task generateTreeWalkerAntlrSource(type: JavaExec) {
inputs.dir file(antlrSource)
outputs.dir file(antlrOutput)
mkdir(antlrOutput)
def grammars = fileTree(antlrSource).include('**/smaliTreeWalker.g')
classpath = configurations.antlr3
main = 'org.antlr.Tool'
args '-fo', relativePath("${antlrOutput}/org/jf/smali")
args grammars.files
}
task generateTestAntlrSource(type: JavaExec) {
inputs.dir file(testAntlrSource)
outputs.dir file(testAntlrOutput)
mkdir(testAntlrOutput)
def grammars = fileTree(testAntlrSource).include('**/*.g')
classpath = configurations.antlr3
main = 'org.antlr.Tool'
args '-fo', relativePath("${testAntlrOutput}/org/jf/smali")
args grammars.files.join(' ')
}
task generateJflexSource(type: JavaExec) {
inputs.dir file(jflexSource)
outputs.dir file(jflexOutput)
mkdir(jflexOutput)
def grammars = fileTree(jflexSource).include('**/*.flex')
classpath = configurations.jflex
main = 'JFlex.Main'
args '-q'
args '-d', relativePath("${jflexOutput}/org/jf/smali")
args grammars.files.join(' ')
environment LC_ALL: "en_US"
}
compileJava.dependsOn generateParserAntlrSource, generateTreeWalkerAntlrSource, generateJflexSource
compileTestJava.dependsOn generateTestAntlrSource
processResources.inputs.property('version', version)
processResources.expand('version': version)
@ -149,17 +94,29 @@ task fatJar(type: Jar, dependsOn: jar) {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest {
attributes("Main-Class": "org.jf.smali.main")
attributes('Main-Class': 'org.jf.smali.main')
}
doLast {
if (!System.getProperty("os.name").toLowerCase().contains("windows")) {
if (!System.getProperty('os.name').toLowerCase().contains('windows')) {
ant.symlink(link: file("${destinationDir}/smali.jar"), resource: archivePath, overwrite: true)
}
}
}
tasks.getByPath('build').dependsOn(fatJar)
generateTestGrammarSource {
outputDirectory = new File(outputDirectory, 'org/jf/smali')
}
generateGrammarSource {
outputDirectory = new File(outputDirectory, 'org/jf/smali')
}
generateJFlexSource {
outputDirectory = new File(outputDirectory, 'org/jf/smali')
}
uploadArchives {
repositories.mavenDeployer {
pom.project {
@ -171,22 +128,23 @@ uploadArchives {
}
}
task proguard(type: JavaExec, dependsOn: fatJar) {
def outFile = fatJar.destinationDir.getPath() + '/' + fatJar.baseName + '-' + fatJar.version + '-small' + '.' + fatJar.extension
inputs.file fatJar.archivePath
outputs.file outFile
task proguard(type: proguard.gradle.ProGuardTask, dependsOn: fatJar) {
def outFile = fatJar.destinationDir.getPath() + '/' + fatJar.baseName + '-' +
fatJar.version + '-small' + '.' + fatJar.extension
classpath = configurations.proguard
main = 'proguard.ProGuard'
args "-injars ${fatJar.archivePath}(!**/TestStringTemplate*.class)"
args "-outjars ${outFile}"
args "-libraryjars ${System.properties['java.home']}/lib/rt.jar"
args '-dontobfuscate'
args '-dontoptimize'
args '-keep public class org.jf.smali.main { public static void main(java.lang.String[]); }'
args '-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); }'
args '-dontwarn com.google.common.**'
args '-dontnote com.google.common.**'
injars fatJar.archivePath
outjars outFile
libraryjars "${System.properties['java.home']}/lib/rt.jar"
dontobfuscate
dontoptimize
keep 'public class org.jf.smali.main { public static void main(java.lang.String[]); }'
keepclassmembers 'enum * { public static **[] values(); public static ** valueOf(java.lang.String); }'
dontwarn 'com.google.common.**'
dontnote 'com.google.common.**'
}
tasks.getByPath(':release').dependsOn(proguard)

View File

@ -667,5 +667,5 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
"." { return invalidToken("Invalid directive"); }
"." [a-zA-z\-_] { return invalidToken("Invalid directive"); }
"." [a-zA-z\-_] [a-zA-z0-9\-_]* { return invalidToken("Invalid directive"); }
. { return invalidToken("Invalid text"); }
[^] { return invalidToken("Invalid text"); }
}

View File

@ -40,6 +40,7 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
@ -158,7 +159,7 @@ public class LexerTest {
if (smaliStream == null) {
Assert.fail("Could not load " + smaliFile);
}
smaliFlexLexer lexer = new smaliFlexLexer(smaliStream);
smaliFlexLexer lexer = new smaliFlexLexer(new InputStreamReader(smaliStream));
lexer.setSourceFile(new File(test + ".smali"));
lexer.setSuppressErrors(true);

View File

@ -68,7 +68,7 @@ public class ClassFileNameHandler {
public ClassFileNameHandler(File path, String fileExtension) {
this.top = new DirectoryEntry(path);
this.fileExtension = fileExtension;
this.modifyWindowsReservedFilenames = testForWindowsReservedFileNames(path);
this.modifyWindowsReservedFilenames = isWindows();
}
// for testing
@ -229,27 +229,8 @@ public class ClassFileNameHandler {
return sb.toString();
}
private static boolean testForWindowsReservedFileNames(File path) {
String[] reservedNames = new String[]{"aux", "con", "com1", "com9", "lpt1", "com9"};
for (String reservedName: reservedNames) {
File f = new File(path, reservedName + ".smali");
if (f.exists()) {
continue;
}
try {
FileWriter writer = new FileWriter(f);
writer.write("test");
writer.flush();
writer.close();
f.delete(); //doesn't throw IOException
} catch (IOException ex) {
//if an exception occurred, it's likely that we're on a windows system.
return true;
}
}
return false;
private static boolean isWindows() {
return System.getProperty("os.name").startsWith("Windows");
}
private static Pattern reservedFileNameRegex = Pattern.compile("^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\\..*)?$",