capacitor-dex-editor 0.0.16 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -29,6 +29,8 @@ import com.android.tools.smali.dexlib2.writer.io.FileDataStore;
|
|
|
29
29
|
import com.android.tools.smali.dexlib2.writer.pool.DexPool;
|
|
30
30
|
import com.android.tools.smali.baksmali.Baksmali;
|
|
31
31
|
import com.android.tools.smali.baksmali.BaksmaliOptions;
|
|
32
|
+
import com.android.tools.smali.baksmali.Adaptors.ClassDefinition;
|
|
33
|
+
import com.android.tools.smali.baksmali.formatter.BaksmaliWriter;
|
|
32
34
|
import com.android.tools.smali.smali.Smali;
|
|
33
35
|
import com.android.tools.smali.smali.SmaliOptions;
|
|
34
36
|
|
|
@@ -1588,120 +1590,16 @@ public class DexManager {
|
|
|
1588
1590
|
return result;
|
|
1589
1591
|
}
|
|
1590
1592
|
|
|
1591
|
-
//
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
int accessFlags = targetClass.getAccessFlags();
|
|
1595
|
-
if ((accessFlags & 0x0001) != 0) smali.append("public ");
|
|
1596
|
-
if ((accessFlags & 0x0010) != 0) smali.append("final ");
|
|
1597
|
-
if ((accessFlags & 0x0020) != 0) smali.append("super ");
|
|
1598
|
-
if ((accessFlags & 0x0200) != 0) smali.append("interface ");
|
|
1599
|
-
if ((accessFlags & 0x0400) != 0) smali.append("abstract ");
|
|
1600
|
-
if ((accessFlags & 0x1000) != 0) smali.append("synthetic ");
|
|
1601
|
-
if ((accessFlags & 0x2000) != 0) smali.append("annotation ");
|
|
1602
|
-
if ((accessFlags & 0x4000) != 0) smali.append("enum ");
|
|
1603
|
-
smali.append(targetClass.getType()).append("\n");
|
|
1593
|
+
// 使用 baksmali 库生成正确的 Smali 代码
|
|
1594
|
+
BaksmaliOptions options = new BaksmaliOptions();
|
|
1595
|
+
ClassDefinition classDefinition = new ClassDefinition(options, targetClass);
|
|
1604
1596
|
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
}
|
|
1610
|
-
|
|
1611
|
-
// 源文件
|
|
1612
|
-
String sourceFile = targetClass.getSourceFile();
|
|
1613
|
-
if (sourceFile != null) {
|
|
1614
|
-
smali.append(".source \"").append(sourceFile).append("\"\n");
|
|
1615
|
-
}
|
|
1616
|
-
|
|
1617
|
-
// 实现的接口
|
|
1618
|
-
for (String iface : targetClass.getInterfaces()) {
|
|
1619
|
-
smali.append(".implements ").append(iface).append("\n");
|
|
1620
|
-
}
|
|
1621
|
-
|
|
1622
|
-
smali.append("\n");
|
|
1623
|
-
|
|
1624
|
-
// 分离静态字段和实例字段
|
|
1625
|
-
java.util.List<Field> staticFields = new java.util.ArrayList<>();
|
|
1626
|
-
java.util.List<Field> instanceFields = new java.util.ArrayList<>();
|
|
1627
|
-
for (Field field : targetClass.getFields()) {
|
|
1628
|
-
if ((field.getAccessFlags() & 0x0008) != 0) {
|
|
1629
|
-
staticFields.add(field);
|
|
1630
|
-
} else {
|
|
1631
|
-
instanceFields.add(field);
|
|
1632
|
-
}
|
|
1633
|
-
}
|
|
1597
|
+
java.io.StringWriter stringWriter = new java.io.StringWriter();
|
|
1598
|
+
BaksmaliWriter writer = new BaksmaliWriter(stringWriter, null);
|
|
1599
|
+
classDefinition.writeTo(writer);
|
|
1600
|
+
writer.close();
|
|
1634
1601
|
|
|
1635
|
-
|
|
1636
|
-
if (!staticFields.isEmpty()) {
|
|
1637
|
-
smali.append("# static fields\n");
|
|
1638
|
-
for (Field field : staticFields) {
|
|
1639
|
-
smali.append(".field ");
|
|
1640
|
-
int fFlags = field.getAccessFlags();
|
|
1641
|
-
if ((fFlags & 0x0001) != 0) smali.append("public ");
|
|
1642
|
-
if ((fFlags & 0x0002) != 0) smali.append("private ");
|
|
1643
|
-
if ((fFlags & 0x0004) != 0) smali.append("protected ");
|
|
1644
|
-
smali.append("static ");
|
|
1645
|
-
if ((fFlags & 0x0010) != 0) smali.append("final ");
|
|
1646
|
-
if ((fFlags & 0x0040) != 0) smali.append("volatile ");
|
|
1647
|
-
if ((fFlags & 0x0080) != 0) smali.append("transient ");
|
|
1648
|
-
if ((fFlags & 0x1000) != 0) smali.append("synthetic ");
|
|
1649
|
-
if ((fFlags & 0x4000) != 0) smali.append("enum ");
|
|
1650
|
-
smali.append(field.getName()).append(":").append(field.getType()).append("\n");
|
|
1651
|
-
}
|
|
1652
|
-
smali.append("\n");
|
|
1653
|
-
}
|
|
1654
|
-
|
|
1655
|
-
// 实例字段
|
|
1656
|
-
if (!instanceFields.isEmpty()) {
|
|
1657
|
-
smali.append("# instance fields\n");
|
|
1658
|
-
for (Field field : instanceFields) {
|
|
1659
|
-
smali.append(".field ");
|
|
1660
|
-
int fFlags = field.getAccessFlags();
|
|
1661
|
-
if ((fFlags & 0x0001) != 0) smali.append("public ");
|
|
1662
|
-
if ((fFlags & 0x0002) != 0) smali.append("private ");
|
|
1663
|
-
if ((fFlags & 0x0004) != 0) smali.append("protected ");
|
|
1664
|
-
if ((fFlags & 0x0010) != 0) smali.append("final ");
|
|
1665
|
-
if ((fFlags & 0x0040) != 0) smali.append("volatile ");
|
|
1666
|
-
if ((fFlags & 0x0080) != 0) smali.append("transient ");
|
|
1667
|
-
if ((fFlags & 0x1000) != 0) smali.append("synthetic ");
|
|
1668
|
-
if ((fFlags & 0x4000) != 0) smali.append("enum ");
|
|
1669
|
-
smali.append(field.getName()).append(":").append(field.getType()).append("\n");
|
|
1670
|
-
}
|
|
1671
|
-
smali.append("\n");
|
|
1672
|
-
}
|
|
1673
|
-
|
|
1674
|
-
// 分离直接方法和虚拟方法
|
|
1675
|
-
java.util.List<Method> directMethods = new java.util.ArrayList<>();
|
|
1676
|
-
java.util.List<Method> virtualMethods = new java.util.ArrayList<>();
|
|
1677
|
-
for (Method method : targetClass.getMethods()) {
|
|
1678
|
-
int mFlags = method.getAccessFlags();
|
|
1679
|
-
// direct methods: private, static, constructor
|
|
1680
|
-
if ((mFlags & 0x0002) != 0 || (mFlags & 0x0008) != 0 ||
|
|
1681
|
-
method.getName().equals("<init>") || method.getName().equals("<clinit>")) {
|
|
1682
|
-
directMethods.add(method);
|
|
1683
|
-
} else {
|
|
1684
|
-
virtualMethods.add(method);
|
|
1685
|
-
}
|
|
1686
|
-
}
|
|
1687
|
-
|
|
1688
|
-
// 直接方法
|
|
1689
|
-
if (!directMethods.isEmpty()) {
|
|
1690
|
-
smali.append("\n# direct methods\n");
|
|
1691
|
-
for (Method method : directMethods) {
|
|
1692
|
-
outputMethod(smali, method);
|
|
1693
|
-
}
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
|
-
// 虚拟方法
|
|
1697
|
-
if (!virtualMethods.isEmpty()) {
|
|
1698
|
-
smali.append("\n# virtual methods\n");
|
|
1699
|
-
for (Method method : virtualMethods) {
|
|
1700
|
-
outputMethod(smali, method);
|
|
1701
|
-
}
|
|
1702
|
-
}
|
|
1703
|
-
|
|
1704
|
-
result.put("smali", smali.toString());
|
|
1602
|
+
result.put("smali", stringWriter.toString());
|
|
1705
1603
|
|
|
1706
1604
|
} finally {
|
|
1707
1605
|
if (dexInputStream != null) {
|
|
@@ -1715,179 +1613,6 @@ public class DexManager {
|
|
|
1715
1613
|
return result;
|
|
1716
1614
|
}
|
|
1717
1615
|
|
|
1718
|
-
/**
|
|
1719
|
-
* 输出单个方法的 Smali 代码 (MT 风格)
|
|
1720
|
-
*/
|
|
1721
|
-
private void outputMethod(StringBuilder smali, Method method) {
|
|
1722
|
-
smali.append(".method ");
|
|
1723
|
-
int mFlags = method.getAccessFlags();
|
|
1724
|
-
if ((mFlags & 0x0001) != 0) smali.append("public ");
|
|
1725
|
-
if ((mFlags & 0x0002) != 0) smali.append("private ");
|
|
1726
|
-
if ((mFlags & 0x0004) != 0) smali.append("protected ");
|
|
1727
|
-
if ((mFlags & 0x0008) != 0) smali.append("static ");
|
|
1728
|
-
if ((mFlags & 0x0010) != 0) smali.append("final ");
|
|
1729
|
-
if ((mFlags & 0x0020) != 0) smali.append("synchronized ");
|
|
1730
|
-
if ((mFlags & 0x0040) != 0) smali.append("bridge ");
|
|
1731
|
-
if ((mFlags & 0x0080) != 0) smali.append("varargs ");
|
|
1732
|
-
if ((mFlags & 0x0100) != 0) smali.append("native ");
|
|
1733
|
-
if ((mFlags & 0x0400) != 0) smali.append("abstract ");
|
|
1734
|
-
if ((mFlags & 0x0800) != 0) smali.append("strictfp ");
|
|
1735
|
-
if ((mFlags & 0x1000) != 0) smali.append("synthetic ");
|
|
1736
|
-
if ((mFlags & 0x10000) != 0) smali.append("constructor ");
|
|
1737
|
-
if ((mFlags & 0x20000) != 0) smali.append("declared-synchronized ");
|
|
1738
|
-
|
|
1739
|
-
smali.append(method.getName());
|
|
1740
|
-
smali.append("(");
|
|
1741
|
-
for (CharSequence param : method.getParameterTypes()) {
|
|
1742
|
-
smali.append(param);
|
|
1743
|
-
}
|
|
1744
|
-
smali.append(")");
|
|
1745
|
-
smali.append(method.getReturnType());
|
|
1746
|
-
smali.append("\n");
|
|
1747
|
-
|
|
1748
|
-
MethodImplementation impl = method.getImplementation();
|
|
1749
|
-
if (impl != null) {
|
|
1750
|
-
smali.append(" .registers ").append(impl.getRegisterCount()).append("\n\n");
|
|
1751
|
-
|
|
1752
|
-
// 输出指令,跟踪标签位置
|
|
1753
|
-
java.util.Map<Integer, String> labelMap = new java.util.HashMap<>();
|
|
1754
|
-
int codeOffset = 0;
|
|
1755
|
-
|
|
1756
|
-
// 第一遍:收集所有标签位置
|
|
1757
|
-
for (Instruction instruction : impl.getInstructions()) {
|
|
1758
|
-
if (instruction instanceof com.android.tools.smali.dexlib2.iface.instruction.OffsetInstruction) {
|
|
1759
|
-
com.android.tools.smali.dexlib2.iface.instruction.OffsetInstruction offInstr =
|
|
1760
|
-
(com.android.tools.smali.dexlib2.iface.instruction.OffsetInstruction) instruction;
|
|
1761
|
-
int targetOffset = codeOffset + offInstr.getCodeOffset();
|
|
1762
|
-
labelMap.put(targetOffset, ":cond_" + Integer.toHexString(targetOffset));
|
|
1763
|
-
}
|
|
1764
|
-
codeOffset += instruction.getCodeUnits();
|
|
1765
|
-
}
|
|
1766
|
-
|
|
1767
|
-
// 第二遍:输出指令 (MT 风格:每条指令后有空行)
|
|
1768
|
-
codeOffset = 0;
|
|
1769
|
-
for (Instruction instruction : impl.getInstructions()) {
|
|
1770
|
-
// 输出标签(如果有)
|
|
1771
|
-
if (labelMap.containsKey(codeOffset)) {
|
|
1772
|
-
smali.append("\n ").append(labelMap.get(codeOffset)).append("\n");
|
|
1773
|
-
}
|
|
1774
|
-
|
|
1775
|
-
smali.append(" ").append(instruction.getOpcode().name.toLowerCase().replace('_', '-'));
|
|
1776
|
-
String params = formatInstruction(instruction);
|
|
1777
|
-
if (!params.isEmpty()) {
|
|
1778
|
-
smali.append(" ").append(params);
|
|
1779
|
-
}
|
|
1780
|
-
smali.append("\n\n"); // MT 风格:每条指令后有空行
|
|
1781
|
-
|
|
1782
|
-
codeOffset += instruction.getCodeUnits();
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
|
|
1786
|
-
smali.append(".end method\n");
|
|
1787
|
-
}
|
|
1788
|
-
|
|
1789
|
-
/**
|
|
1790
|
-
* 格式化指令参数 - 使用正确的 Smali 语法格式
|
|
1791
|
-
* invoke 指令格式: invoke-xxx {v0, v1}, Lclass;->method()V
|
|
1792
|
-
*/
|
|
1793
|
-
private String formatInstruction(Instruction instruction) {
|
|
1794
|
-
StringBuilder sb = new StringBuilder();
|
|
1795
|
-
String opName = instruction.getOpcode().name.toLowerCase();
|
|
1796
|
-
boolean isInvokeOrFilled = opName.startsWith("invoke") || opName.startsWith("filled-new-array");
|
|
1797
|
-
|
|
1798
|
-
// 收集寄存器
|
|
1799
|
-
java.util.List<Integer> registers = new java.util.ArrayList<>();
|
|
1800
|
-
|
|
1801
|
-
// 处理多寄存器指令 (invoke 指令使用 FiveRegisterInstruction)
|
|
1802
|
-
if (instruction instanceof com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction) {
|
|
1803
|
-
com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction regInstr =
|
|
1804
|
-
(com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction) instruction;
|
|
1805
|
-
int regCount = regInstr.getRegisterCount();
|
|
1806
|
-
if (regCount >= 1) registers.add(regInstr.getRegisterC());
|
|
1807
|
-
if (regCount >= 2) registers.add(regInstr.getRegisterD());
|
|
1808
|
-
if (regCount >= 3) registers.add(regInstr.getRegisterE());
|
|
1809
|
-
if (regCount >= 4) registers.add(regInstr.getRegisterF());
|
|
1810
|
-
if (regCount >= 5) registers.add(regInstr.getRegisterG());
|
|
1811
|
-
} else if (instruction instanceof com.android.tools.smali.dexlib2.iface.instruction.RegisterRangeInstruction) {
|
|
1812
|
-
com.android.tools.smali.dexlib2.iface.instruction.RegisterRangeInstruction regInstr =
|
|
1813
|
-
(com.android.tools.smali.dexlib2.iface.instruction.RegisterRangeInstruction) instruction;
|
|
1814
|
-
int start = regInstr.getStartRegister();
|
|
1815
|
-
int count = regInstr.getRegisterCount();
|
|
1816
|
-
for (int i = 0; i < count; i++) {
|
|
1817
|
-
registers.add(start + i);
|
|
1818
|
-
}
|
|
1819
|
-
} else {
|
|
1820
|
-
// 处理普通寄存器指令
|
|
1821
|
-
if (instruction instanceof com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction) {
|
|
1822
|
-
com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction regInstr =
|
|
1823
|
-
(com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction) instruction;
|
|
1824
|
-
registers.add(regInstr.getRegisterA());
|
|
1825
|
-
}
|
|
1826
|
-
|
|
1827
|
-
if (instruction instanceof com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction) {
|
|
1828
|
-
com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction regInstr =
|
|
1829
|
-
(com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction) instruction;
|
|
1830
|
-
registers.add(regInstr.getRegisterB());
|
|
1831
|
-
}
|
|
1832
|
-
|
|
1833
|
-
if (instruction instanceof com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction) {
|
|
1834
|
-
com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction regInstr =
|
|
1835
|
-
(com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction) instruction;
|
|
1836
|
-
registers.add(regInstr.getRegisterC());
|
|
1837
|
-
}
|
|
1838
|
-
}
|
|
1839
|
-
|
|
1840
|
-
// 格式化寄存器部分
|
|
1841
|
-
if (!registers.isEmpty()) {
|
|
1842
|
-
if (isInvokeOrFilled) {
|
|
1843
|
-
// invoke 指令使用 {} 包裹寄存器
|
|
1844
|
-
sb.append("{");
|
|
1845
|
-
for (int i = 0; i < registers.size(); i++) {
|
|
1846
|
-
if (i > 0) sb.append(", ");
|
|
1847
|
-
sb.append("v").append(registers.get(i));
|
|
1848
|
-
}
|
|
1849
|
-
sb.append("}");
|
|
1850
|
-
} else {
|
|
1851
|
-
// 普通指令直接列出寄存器
|
|
1852
|
-
for (int i = 0; i < registers.size(); i++) {
|
|
1853
|
-
if (i > 0) sb.append(", ");
|
|
1854
|
-
sb.append("v").append(registers.get(i));
|
|
1855
|
-
}
|
|
1856
|
-
}
|
|
1857
|
-
}
|
|
1858
|
-
|
|
1859
|
-
// 处理引用指令
|
|
1860
|
-
if (instruction instanceof com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction) {
|
|
1861
|
-
com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction refInstr =
|
|
1862
|
-
(com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction) instruction;
|
|
1863
|
-
if (sb.length() > 0) sb.append(", ");
|
|
1864
|
-
sb.append(refInstr.getReference().toString());
|
|
1865
|
-
}
|
|
1866
|
-
|
|
1867
|
-
// 处理字面量指令
|
|
1868
|
-
if (instruction instanceof com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction) {
|
|
1869
|
-
com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction litInstr =
|
|
1870
|
-
(com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction) instruction;
|
|
1871
|
-
if (sb.length() > 0) sb.append(", ");
|
|
1872
|
-
sb.append("0x").append(Long.toHexString(litInstr.getWideLiteral()));
|
|
1873
|
-
} else if (instruction instanceof com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction) {
|
|
1874
|
-
com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction litInstr =
|
|
1875
|
-
(com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction) instruction;
|
|
1876
|
-
if (sb.length() > 0) sb.append(", ");
|
|
1877
|
-
sb.append("0x").append(Integer.toHexString(litInstr.getNarrowLiteral()));
|
|
1878
|
-
}
|
|
1879
|
-
|
|
1880
|
-
// 处理偏移指令
|
|
1881
|
-
if (instruction instanceof com.android.tools.smali.dexlib2.iface.instruction.OffsetInstruction) {
|
|
1882
|
-
com.android.tools.smali.dexlib2.iface.instruction.OffsetInstruction offInstr =
|
|
1883
|
-
(com.android.tools.smali.dexlib2.iface.instruction.OffsetInstruction) instruction;
|
|
1884
|
-
if (sb.length() > 0) sb.append(", ");
|
|
1885
|
-
sb.append(":label_").append(offInstr.getCodeOffset());
|
|
1886
|
-
}
|
|
1887
|
-
|
|
1888
|
-
return sb.toString();
|
|
1889
|
-
}
|
|
1890
|
-
|
|
1891
1616
|
/**
|
|
1892
1617
|
* 保存修改后的 Smali 代码到 APK 中的 DEX 文件
|
|
1893
1618
|
* 注意:这是一个复杂操作,需要重新编译 Smali 并修改 DEX 文件
|