├── smali2java
├── App.config
├── Smali
│ ├── SmaliParameter.cs
│ ├── SmaliField.cs
│ ├── SmaliEngine.cs
│ ├── SmaliMethod.cs
│ ├── SmaliClass.cs
│ ├── SmaliUtils.cs
│ ├── SmaliCall.cs
│ ├── 2SmaliMethod.cs
│ ├── SmaliVM.cs
│ └── SmaliLine.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── Smali2Java-v3.csproj
└── Samples
│ ├── AndroidHandler.smali
│ └── NetqinSmsFilter.smali
├── Smali2Java-v4
├── Smali
│ └── SmaliClass.cs
├── Program.cs
├── Parser
│ ├── Parser.cs
│ ├── Line.cs
│ └── LineGroup.cs
├── Properties
│ └── AssemblyInfo.cs
├── Smali2Java-v4.csproj
└── Samples
│ ├── AndroidHandler.smali
│ └── NetqinSmsFilter.smali
├── .gitattributes
├── README.md
├── Smali2Java-VS2012.sln
└── .gitignore
/smali2java/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Smali2Java-v4/Smali/SmaliClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Smali2Java_v4.Smali
7 | {
8 | public class SmaliClass
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Smali2Java-v4/Program.cs:
--------------------------------------------------------------------------------
1 | using Smali2Java_v4.Parser;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace Smali2Java_v4
8 | {
9 | class Program
10 | {
11 | public static void Main(string[] args)
12 | {
13 | ParserSmali p = new ParserSmali();
14 | p.Parse("Samples\\NetqinSmsFilter.smali");
15 |
16 | Console.ReadKey();
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/smali2java/Smali/SmaliParameter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Smali2Java
7 | {
8 | public class SmaliParameter
9 | {
10 | public String Register;
11 | public String Name;
12 | public String Type;
13 | public String Value;
14 |
15 | public String ToJava()
16 | {
17 | return SmaliUtils.General.Name2Java(SmaliUtils.General.ReturnType2Java(SmaliUtils.General.GetReturnType(Type), Type)).Replace(";", "").TrimEnd() + " " + Name;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/smali2java/Smali/SmaliField.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Smali2Java
7 | {
8 | public class SmaliField
9 | {
10 | public SmaliLine.EAccessMod AccessModifiers;
11 | public SmaliLine.ENonAccessMod NonAccessModifiers;
12 | public String Name;
13 | public String Type;
14 |
15 | public String ToJava()
16 | {
17 | return String.Format("{0} {1} {2} {3};\n",
18 | AccessModifiers == 0 ? "" : AccessModifiers.ToString().ToLowerInvariant().Replace(",", ""),
19 | NonAccessModifiers == 0 ? "" : NonAccessModifiers.ToString().ToLowerInvariant().Replace(",", ""),
20 | SmaliUtils.General.Name2Java(SmaliUtils.General.ReturnType2Java(SmaliUtils.General.GetReturnType(Type),Type)).Replace(";",""),
21 | Name
22 | );
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Smali2Java
2 | This is an attempt to develop a direct smali to java converter. The goal is for it to be able to decompile a whole framework.jar or any kind of main Android APK without too much trouble into an Eclipse solution.
3 |
4 | The project's "homepage" (actually a XDA-Developers DevDB thread) is [here](http://forum.xda-developers.com/showthread.php?t=2592266).
5 |
6 | ## Important notes
7 | * THIS IS A WORK IN PROGRESS. It is not complete at all, in fact, it needs YOUR help!. If you're able to fork it and improve it so it can be able to reach its goal, by any means, please do it!
8 | * Please use sample files made with smali 2.0.2 or later, as this project is aimed to use their new syntax, like .param instead of .parameter, and such.
9 |
10 | ## Compatibility
11 | * You need Visual Studio 2012 and .NET Framework 3.5 installed on your machine.
12 | * It has been reported that it also works with SharpDevelop and Mono, so you can compile it under Linux too!
13 |
--------------------------------------------------------------------------------
/Smali2Java-v4/Parser/Parser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace Smali2Java_v4.Parser
8 | {
9 | public class ParserSmali
10 | {
11 | public List Lines = new List();
12 | public List Output = new List();
13 |
14 | public void Parse(string filename)
15 | {
16 | foreach (String s in File.ReadAllLines(filename))
17 | if(!String.IsNullOrEmpty(s.Trim()))
18 | Lines.Add(new Line(s));
19 |
20 | LineGroup lastGroup = new LineGroup();
21 | foreach (Line l in Lines.Where(x => x.Type != ELineType.Comment))
22 | {
23 | if (l.NewGroup)
24 | {
25 | Output.Add(lastGroup.ToString());
26 | lastGroup = new LineGroup();
27 | }
28 | lastGroup.Add(l);
29 | }
30 | Output.Add("}");
31 |
32 | foreach (String s in Output)
33 | Console.WriteLine("[" + s + "]");
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/smali2java/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Smali2Java
7 | {
8 | class Program
9 | {
10 | public static bool Debug = true;
11 | public static void Main(string[] args)
12 | {
13 | if (args.Length == 0)
14 | Console.WriteLine("ERROR: No Input File! using sample file\n");
15 |
16 | String sFile = args.Length > 0 ? args[0] : "Samples\\AndroidHandler.smali";
17 | string destFile = args.Length > 1 ? args[1] : null;
18 |
19 | SmaliEngine e = new SmaliEngine();
20 | string contents = e.Indent(e.Decompile(sFile));
21 | if (string.IsNullOrEmpty(destFile))
22 | {
23 | Console.BufferHeight = 10000;
24 | Console.WindowWidth = Console.LargestWindowWidth;
25 | Console.BufferWidth = Console.LargestWindowWidth;
26 |
27 | Console.WriteLine("Decompiling file: " + sFile);
28 | Console.WriteLine("[");
29 |
30 | Console.Write(contents);
31 | Console.WriteLine("]");
32 | Console.ReadKey();
33 | }
34 | else
35 | {
36 | System.IO.File.WriteAllText(destFile, contents);
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Smali2Java-VS2012.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Smali2Java-v3", "smali2java\Smali2Java-v3.csproj", "{35577FBA-BEF5-43FB-8B2D-E6D10F0F62C0}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Smali2Java-v4", "Smali2Java-v4\Smali2Java-v4.csproj", "{DCA79475-B106-4055-85BB-30AA93D39D53}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {35577FBA-BEF5-43FB-8B2D-E6D10F0F62C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {35577FBA-BEF5-43FB-8B2D-E6D10F0F62C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {35577FBA-BEF5-43FB-8B2D-E6D10F0F62C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {35577FBA-BEF5-43FB-8B2D-E6D10F0F62C0}.Release|Any CPU.Build.0 = Release|Any CPU
18 | {DCA79475-B106-4055-85BB-30AA93D39D53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {DCA79475-B106-4055-85BB-30AA93D39D53}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {DCA79475-B106-4055-85BB-30AA93D39D53}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {DCA79475-B106-4055-85BB-30AA93D39D53}.Release|Any CPU.Build.0 = Release|Any CPU
22 | EndGlobalSection
23 | GlobalSection(SolutionProperties) = preSolution
24 | HideSolutionNode = FALSE
25 | EndGlobalSection
26 | EndGlobal
27 |
--------------------------------------------------------------------------------
/smali2java/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Smali2Java-v3")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Smali2Java-v3")]
13 | [assembly: AssemblyCopyright("Copyright © 2013")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("2f9b0ddb-db6e-432d-a2a6-e13ccabc9ddb")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Smali2Java-v4/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Smali2Java-v4")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Smali2Java-v4")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("567b9f16-70c0-4e45-8ff1-a2bac2a53407")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/smali2java/Smali/SmaliEngine.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace Smali2Java
8 | {
9 | public class SmaliEngine
10 | {
11 | public static SmaliVM VM = new SmaliVM();
12 | private List Lines = new List();
13 |
14 | public String Decompile(String sFilename)
15 | {
16 | String rv = String.Empty;
17 |
18 | foreach (String s in File.ReadAllLines(sFilename).Where(x => !String.IsNullOrEmpty(x)))
19 | {
20 | SmaliLine l = SmaliLine.Parse(s);
21 | if (l != null)
22 | Lines.Add(l);
23 | }
24 |
25 | SmaliClass c = new SmaliClass();
26 | c.Lines = Lines;
27 | c.LoadAttributes();
28 | c.LoadFields();
29 | c.LoadMethods();
30 |
31 | StringBuilder sb = new StringBuilder();
32 |
33 | sb.Append(c.ToJava());
34 |
35 | rv = sb.ToString();
36 | return rv;
37 | }
38 |
39 | public String Indent(String java)
40 | {
41 | int indentation = 0;
42 | String indenter = " ";
43 | StringBuilder sb = new StringBuilder();
44 |
45 | string[] lines = java.Split('\n');
46 | for (int i = 0; i < lines.Length; i++)
47 | {
48 | if (lines[i].TrimStart().Contains("}"))
49 | {
50 | indentation--;
51 | }
52 |
53 | for (int n = 0; n < indentation; n++)
54 | {
55 | sb.Append(indenter);
56 | }
57 | sb.AppendFormat("{0}\n", lines[i]);
58 |
59 | if (lines[i].TrimStart().Contains("{"))
60 | {
61 | indentation++;
62 | }
63 | }
64 |
65 | return sb.ToString();
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/smali2java/Smali/SmaliMethod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Smali2Java
7 | {
8 | public class SmaliMethod
9 | {
10 | [Flags]
11 | public enum EMethodFlags
12 | {
13 | p0IsSelf = 4
14 | }
15 |
16 | public List JavaOutput = new List();
17 | public List Lines = new List();
18 |
19 | //We can use this to generate variable names.
20 | public Dictionary varCount = new Dictionary();
21 |
22 | public SmaliClass ParentClass;
23 | public SmaliLine.EAccessMod AccessModifiers;
24 | public SmaliLine.ENonAccessMod NonAccessModifiers;
25 | public EMethodFlags MethodFlags = 0;
26 | public SmaliCall MethodCall;
27 |
28 | public bool bIsFirstParam = true;
29 | public bool bHasParameters= true;
30 | public bool bHasPrologue = true;
31 |
32 | public int IncrementTypeCount(SmaliLine.LineReturnType type)
33 | {
34 | if (varCount.ContainsKey(type))
35 | return varCount[type]++;
36 | else
37 | return varCount[type] = 1;
38 | }
39 | public int GetTypeCount(SmaliLine.LineReturnType type)
40 | {
41 | if (varCount.ContainsKey(type))
42 | return varCount[type];
43 | else
44 | return varCount[type] = 0;
45 | }
46 | public void Process()
47 | {
48 | bHasPrologue = Lines.Where(x => x.Instruction == SmaliLine.LineInstruction.Prologue).Count() > 0;
49 | bHasParameters = Lines.Where(x => x.Instruction == SmaliLine.LineInstruction.Parameter).Count() > 0;
50 | for (int i = 0; i < Lines.Count; i++)
51 | {
52 | SmaliLine l = Lines[i];
53 | if (l.bIsDirective)
54 | SmaliEngine.VM.ProcessDirective(this, l);
55 | else
56 | SmaliEngine.VM.ProcessInstruction(this, l);
57 |
58 | if (!String.IsNullOrEmpty(SmaliEngine.VM.Java))
59 | {
60 | JavaOutput.Add(SmaliEngine.VM.Java);
61 | SmaliEngine.VM.Java = String.Empty;
62 | }
63 | }
64 | }
65 |
66 | public String ToJava()
67 | {
68 | return (String.Join("\n", JavaOutput.ToArray()) + "\n");
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Smali2Java-v4/Smali2Java-v4.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {DCA79475-B106-4055-85BB-30AA93D39D53}
8 | Exe
9 | Properties
10 | Smali2Java_v4
11 | Smali2Java-v4
12 | v4.0
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | Always
54 |
55 |
56 |
57 |
58 | Always
59 |
60 |
61 |
62 |
69 |
--------------------------------------------------------------------------------
/Smali2Java-v4/Parser/Line.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Smali2Java_v4.Parser
7 | {
8 | public enum ELineType
9 | {
10 | Directive = 1,
11 | Instruction = 2,
12 | Label = 3,
13 | Comment = 4
14 | }
15 |
16 | public enum ELineDirective
17 | {
18 | Class = 1,
19 | Super,
20 | Source,
21 | Field,
22 | Method,
23 | EndMethod,
24 | Registers,
25 | Prologue,
26 | Line,
27 | Param,
28 |
29 | }
30 |
31 | public class Line
32 | {
33 | public ELineType Type;
34 | public ELineDirective Directive;
35 | public List Tokens = new List();
36 | public bool NewGroup = false;
37 | public String Raw;
38 |
39 | public Line(string s)
40 | {
41 | s = s.Trim();
42 | if(!String.IsNullOrEmpty(s))
43 | if (s.Length > 0)
44 | {
45 | Raw = s;
46 |
47 | switch (s[0])
48 | {
49 | case '.':
50 | Type = ELineType.Directive;
51 | break;
52 | case '#':
53 | Type = ELineType.Comment;
54 | break;
55 | case ':':
56 | Type = ELineType.Label;
57 | break;
58 | default:
59 | Type = ELineType.Instruction;
60 | break;
61 | }
62 | if (s.Contains(' '))
63 | {
64 | Tokens.AddRange(s.Split(new String[] { " " }, StringSplitOptions.RemoveEmptyEntries));
65 | if (Tokens.Count > 0)
66 | {
67 | switch (Tokens.First().ToLowerInvariant().Trim())
68 | {
69 | case ".class":
70 | Directive = ELineDirective.Class;
71 | break;
72 | case ".super":
73 | Directive = ELineDirective.Super;
74 | break;
75 | case ".source":
76 | Directive = ELineDirective.Source;
77 | break;
78 | case ".field":
79 | Directive = ELineDirective.Field;
80 | NewGroup = true;
81 | break;
82 | case ".method":
83 | Directive = ELineDirective.Method;
84 | NewGroup = true;
85 | break;
86 | case ".end":
87 | if(Tokens[1] == "method")
88 | Directive = ELineDirective.EndMethod;
89 | break;
90 | }
91 | }
92 | }
93 | }
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/smali2java/Smali2Java-v3.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {35577FBA-BEF5-43FB-8B2D-E6D10F0F62C0}
8 | Exe
9 | Properties
10 | Smali2Java
11 | Smali2Java
12 | v3.5
13 | 512
14 |
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | Always
62 |
63 |
64 |
65 |
66 | Always
67 |
68 |
69 |
70 |
77 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 |
46 | [Dd]ebug/
47 | [Rr]elease/
48 | x64/
49 | build/
50 | [Bb]in/
51 | [Oo]bj/
52 |
53 | # MSTest test Results
54 | [Tt]est[Rr]esult*/
55 | [Bb]uild[Ll]og.*
56 |
57 | *_i.c
58 | *_p.c
59 | *.ilk
60 | *.meta
61 | *.obj
62 | *.pch
63 | *.pdb
64 | *.pgc
65 | *.pgd
66 | *.rsp
67 | *.sbr
68 | *.tlb
69 | *.tli
70 | *.tlh
71 | *.tmp
72 | *.tmp_proj
73 | *.log
74 | *.vspscc
75 | *.vssscc
76 | .builds
77 | *.pidb
78 | *.log
79 | *.scc
80 |
81 | # Visual C++ cache files
82 | ipch/
83 | *.aps
84 | *.ncb
85 | *.opensdf
86 | *.sdf
87 | *.cachefile
88 |
89 | # Visual Studio profiler
90 | *.psess
91 | *.vsp
92 | *.vspx
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 |
101 | # TeamCity is a build add-in
102 | _TeamCity*
103 |
104 | # DotCover is a Code Coverage Tool
105 | *.dotCover
106 |
107 | # NCrunch
108 | *.ncrunch*
109 | .*crunch*.local.xml
110 |
111 | # Installshield output folder
112 | [Ee]xpress/
113 |
114 | # DocProject is a documentation generator add-in
115 | DocProject/buildhelp/
116 | DocProject/Help/*.HxT
117 | DocProject/Help/*.HxC
118 | DocProject/Help/*.hhc
119 | DocProject/Help/*.hhk
120 | DocProject/Help/*.hhp
121 | DocProject/Help/Html2
122 | DocProject/Help/html
123 |
124 | # Click-Once directory
125 | publish/
126 |
127 | # Publish Web Output
128 | *.Publish.xml
129 | *.pubxml
130 |
131 | # NuGet Packages Directory
132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
133 | #packages/
134 |
135 | # Windows Azure Build Output
136 | csx
137 | *.build.csdef
138 |
139 | # Windows Store app package directory
140 | AppPackages/
141 |
142 | # Others
143 | sql/
144 | *.Cache
145 | ClientBin/
146 | [Ss]tyle[Cc]op.*
147 | ~$*
148 | *~
149 | *.dbmdl
150 | *.[Pp]ublish.xml
151 | *.pfx
152 | *.publishsettings
153 |
154 | # RIA/Silverlight projects
155 | Generated_Code/
156 |
157 | # Backup & report files from converting an old project file to a newer
158 | # Visual Studio version. Backup files are not needed, because we have git ;-)
159 | _UpgradeReport_Files/
160 | Backup*/
161 | UpgradeLog*.XML
162 | UpgradeLog*.htm
163 |
164 | # SQL Server files
165 | App_Data/*.mdf
166 | App_Data/*.ldf
167 |
168 | #############
169 | ## Windows detritus
170 | #############
171 |
172 | # Windows image file caches
173 | Thumbs.db
174 | ehthumbs.db
175 |
176 | # Folder config file
177 | Desktop.ini
178 |
179 | # Recycle Bin used on file shares
180 | $RECYCLE.BIN/
181 |
182 | # Mac crap
183 | .DS_Store
184 |
185 |
186 | #############
187 | ## Python
188 | #############
189 |
190 | *.py[co]
191 |
192 | # Packages
193 | *.egg
194 | *.egg-info
195 | dist/
196 | build/
197 | eggs/
198 | parts/
199 | var/
200 | sdist/
201 | develop-eggs/
202 | .installed.cfg
203 |
204 | # Installer logs
205 | pip-log.txt
206 |
207 | # Unit test / coverage reports
208 | .coverage
209 | .tox
210 |
211 | #Translations
212 | *.mo
213 |
214 | #Mr Developer
215 | .mr.developer.cfg
216 |
--------------------------------------------------------------------------------
/Smali2Java-v4/Parser/LineGroup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Smali2Java_v4.Parser
7 | {
8 | public class LineGroup
9 | {
10 | public List Lines = new List();
11 |
12 | public void Add(Line l)
13 | {
14 | Lines.Add(l);
15 | }
16 |
17 | public String ToJava()
18 | {
19 | StringBuilder sb = new StringBuilder();
20 | if (Lines.Count > 0)
21 | {
22 | bool bIsClass = false;
23 | foreach (Line l in Lines)
24 | {
25 | if (l.Type == ELineType.Directive)
26 | {
27 | switch (l.Directive)
28 | {
29 | case ELineDirective.Class:
30 | bIsClass = true;
31 | sb.Append(ParseAccesors(l.Tokens.Skip(1).Take(l.Tokens.Count - 2)));
32 | sb.Append(" class ");
33 | sb.Append(ParseObject(l.Tokens.Last()));
34 | break;
35 | case ELineDirective.Super:
36 | sb.Append(" extends ");
37 | sb.Append(ParseObject(l.Tokens.Last()));
38 | break;
39 | case ELineDirective.Field:
40 | sb.Append(ParseAccesors(l.Tokens.Skip(1).Take(l.Tokens.Count - 2)));
41 | sb.Append(" " + ParseObject(l.Tokens.Last()) + ";");
42 | break;
43 | case ELineDirective.Method:
44 | sb.Append(ParseAccesors(l.Tokens.Skip(1).Take(l.Tokens.Count - 2)));
45 | sb.Append(" " + ParseMethod(l.Tokens.Last()));
46 | sb.AppendLine(" {");
47 | break;
48 | case ELineDirective.EndMethod:
49 | sb.Append("}");
50 | break;
51 | }
52 | }
53 | }
54 |
55 | if (bIsClass)
56 | sb.Append(" {");
57 | }
58 | return sb.ToString();
59 | }
60 |
61 | private String ParseMethod(String method)
62 | {
63 | StringBuilder sb = new StringBuilder();
64 | String rType = method.Substring(method.LastIndexOf(')') + 1);
65 | rType = ParseObject(rType);
66 |
67 | String mName = method.Substring(0, method.IndexOf('('));
68 |
69 | String mArgs = method.Substring(method.IndexOf('(') + 1);
70 | mArgs = mArgs.Substring(0, mArgs.LastIndexOf(')'));
71 |
72 | sb.Append(rType);
73 | sb.Append(" " + mName + "(");
74 | if (mArgs.Length > 0)
75 | {
76 | String[] args = mArgs.Split(new String[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
77 | for(int i = 0; i < args.Length; i++)
78 | sb.Append(ParseObject(args[i]) + " p" + i.ToString());
79 | }
80 | sb.Append(")");
81 |
82 | return sb.ToString();
83 | }
84 |
85 | private String ParseObject(string obj)
86 | {
87 | obj = obj.Trim();
88 | if(!String.IsNullOrEmpty(obj)) {
89 | if (obj.Contains(":"))
90 | {
91 | String[] split = obj.Split(':');
92 | split[1] = ParseObject(split[1]);
93 | return split[1] + " " + split[0];
94 | }
95 | else
96 | {
97 | if (obj[0] == 'L')
98 | obj = obj.Substring(1);
99 | }
100 | obj = obj.Replace('/', '.');
101 | obj = obj.Replace(";", "");
102 | }
103 | return obj;
104 | }
105 |
106 | public String ParseAccesors(IEnumerable acc)
107 | {
108 | return String.Join(" ", acc.ToArray());
109 | }
110 |
111 | public override string ToString()
112 | {
113 | return ToJava();
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/smali2java/Smali/SmaliClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Smali2Java
7 | {
8 | public class SmaliClass
9 | {
10 | public List Lines;
11 |
12 | public String PackageName;
13 | public String ClassName;
14 | public String SourceFile;
15 | public String Extends;
16 | public String Implements;
17 | public SmaliLine.EAccessMod AccessModifiers;
18 | public SmaliLine.ENonAccessMod NonAccessModifiers;
19 | public List Fields = new List();
20 | public List Methods = new List();
21 |
22 | public void LoadAttributes()
23 | {
24 | SmaliLine line = Lines.Where(x => x.Instruction == SmaliLine.LineInstruction.Class).Single();
25 | ClassName = line.aClassName.Substring(line.aClassName.LastIndexOf('/') + 1).Replace(";", "");
26 | AccessModifiers = line.AccessModifiers;
27 | NonAccessModifiers = line.NonAccessModifiers;
28 | if(line.aClassName.Contains("/"))
29 | PackageName = line.aClassName.Substring(0, line.aClassName.LastIndexOf('/'));
30 |
31 | line = Lines.Where(x => x.Instruction == SmaliLine.LineInstruction.Super).SingleOrDefault();
32 | if (line != null)
33 | Extends = line.aType;
34 |
35 | line = Lines.Where(x => x.Instruction == SmaliLine.LineInstruction.Implements).SingleOrDefault();
36 | if (line != null)
37 | Implements = line.aType;
38 |
39 | line = Lines.Where(x => x.Instruction == SmaliLine.LineInstruction.Source).SingleOrDefault();
40 | if(line != null)
41 | SourceFile = line.aExtra;
42 | }
43 | public void LoadFields()
44 | {
45 | foreach (SmaliLine l in Lines.Where(x => x.Instruction == SmaliLine.LineInstruction.Field))
46 | Fields.Add(new SmaliField()
47 | {
48 | AccessModifiers = l.AccessModifiers,
49 | NonAccessModifiers = l.NonAccessModifiers,
50 | Type = l.aType,
51 | Name = l.aName
52 | });
53 | }
54 | public void LoadMethods()
55 | {
56 | bool bAdd = false;
57 | SmaliMethod m = null;
58 |
59 | for (int i = 0; i < Lines.Count; i++)
60 | {
61 | SmaliLine l = Lines[i];
62 |
63 | if (bAdd)
64 | {
65 | m.Lines.Add(l);
66 | if (l.Instruction == SmaliLine.LineInstruction.EndMethod)
67 | {
68 | bAdd = false;
69 | //if(Methods.Count < 3)
70 | Methods.Add(m);
71 | }
72 | else
73 | continue;
74 | }
75 |
76 | if (l.Instruction == SmaliLine.LineInstruction.Method)
77 | {
78 | bAdd = true;
79 | m = new SmaliMethod();
80 | m.ParentClass = this;
81 | m.Lines.Add(l);
82 | }
83 | }
84 |
85 | foreach (SmaliMethod me in Methods)
86 | me.Process();
87 | }
88 |
89 | public String ToJava()
90 | {
91 | String rv = String.Empty;
92 | StringBuilder sb = new StringBuilder();
93 |
94 | if(!String.IsNullOrEmpty(PackageName))
95 | sb.AppendFormat("package {0};\n\n", SmaliUtils.General.Name2Java(PackageName));
96 |
97 | sb.AppendFormat("{0} {1} class {2} {3} {4} {5} {6} {{\n",
98 | AccessModifiers == 0 ? "" : AccessModifiers.ToString().ToLowerInvariant().Replace(",", ""),
99 | NonAccessModifiers == 0 ? "" : NonAccessModifiers.ToString().ToLowerInvariant().Replace(",", ""),
100 | SmaliUtils.General.Name2Java(ClassName),
101 | String.IsNullOrEmpty(Extends) ? "" : "extends",
102 | String.IsNullOrEmpty(Extends) ? "" : SmaliUtils.General.Name2Java(Extends),
103 | String.IsNullOrEmpty(Implements) ? "" : "implements",
104 | String.IsNullOrEmpty(Implements) ? "" : SmaliUtils.General.Name2Java(Implements)
105 | );
106 |
107 | foreach (SmaliField f in Fields)
108 | sb.Append(f.ToJava());
109 |
110 | foreach (SmaliMethod m in Methods)
111 | sb.Append(m.ToJava());
112 |
113 | sb.AppendLine("}");
114 |
115 | rv = sb.ToString();
116 | return rv;
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/smali2java/Smali/SmaliUtils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Smali2Java
7 | {
8 | public static class SmaliUtils
9 | {
10 | public static class General
11 | {
12 | public static String Eat(ref String s, String until, bool addLength = false)
13 | {
14 | String rv = s.Substring(0, s.IndexOf(until));
15 | s = s.Substring(rv.Length + (addLength ? until.Length : 0));
16 | return rv;
17 | }
18 |
19 | public static String Eat(ref String s, char until, bool addLength = false)
20 | {
21 | String rv = s.Substring(0, s.IndexOf(until));
22 | s = s.Substring(rv.Length + (addLength ? 1 : 0));
23 | return rv;
24 | }
25 |
26 | public static String Name2Java(String smaliName)
27 | {
28 | if (smaliName.StartsWith("L"))
29 | smaliName = smaliName.Substring(1);
30 | if (smaliName.EndsWith(";"))
31 | smaliName = smaliName.Remove(smaliName.Length - 1, 1);
32 | smaliName = smaliName.Replace("/", ".");
33 | return smaliName;
34 | }
35 |
36 | public static String Modifiers2Java(SmaliLine.EAccessMod eAccessMod, SmaliLine.ENonAccessMod eNonAccessMod)
37 | {
38 | return String.Join(" ", new String[] { eAccessMod == 0 ? "" : eAccessMod.ToString().ToLowerInvariant().Replace(",", ""), eNonAccessMod == 0 ? "" : eNonAccessMod.ToString().ToLowerInvariant().Replace(",", "") });
39 | }
40 |
41 | public static String ReturnType2Java(SmaliLine.LineReturnType rt, String customType)
42 | {
43 | if (rt.ToString().EndsWith("Array"))
44 | {
45 | if (rt == SmaliLine.LineReturnType.CustomArray)
46 | {
47 | if (customType != "")
48 | return customType.Substring(1) + "[] ";
49 | else
50 | return customType.Substring(1) + "[]";
51 | }
52 | else
53 | return Name2Java(rt.ToString().Replace("Array","").ToLowerInvariant().Trim()) + "[] ";
54 | }
55 | else
56 | {
57 | if (rt == SmaliLine.LineReturnType.Custom)
58 | {
59 | if (customType != "")
60 | return customType + ' ';
61 | else
62 | return customType;
63 | }
64 | else
65 | return Name2Java(rt.ToString().ToLowerInvariant().Trim()) + ' ';
66 | }
67 | }
68 |
69 | public static SmaliLine.LineReturnType GetReturnType(String s)
70 | {
71 | String rt = s.ToLowerInvariant().Trim();
72 | if (rt.StartsWith("[")) // This is an array
73 | {
74 | rt = rt.Substring(1);
75 | switch (rt)
76 | {
77 | case "v":
78 | return SmaliLine.LineReturnType.VoidArray;
79 | case "i":
80 | return SmaliLine.LineReturnType.IntArray;
81 | case "z":
82 | return SmaliLine.LineReturnType.BooleanArray;
83 | case "b":
84 | return SmaliLine.LineReturnType.ByteArray;
85 | case "s":
86 | return SmaliLine.LineReturnType.ShortArray;
87 | case "c":
88 | return SmaliLine.LineReturnType.CharArray;
89 | case "j":
90 | return SmaliLine.LineReturnType.LongArray;
91 | case "d":
92 | return SmaliLine.LineReturnType.DoubleArray;
93 | default:
94 | return SmaliLine.LineReturnType.CustomArray;
95 | }
96 | }
97 | switch(rt)
98 | {
99 | case "v":
100 | return SmaliLine.LineReturnType.Void;
101 | case "i":
102 | return SmaliLine.LineReturnType.Int;
103 | case "z":
104 | return SmaliLine.LineReturnType.Boolean;
105 | case "b":
106 | return SmaliLine.LineReturnType.Byte;
107 | case "s":
108 | return SmaliLine.LineReturnType.Short;
109 | case "c":
110 | return SmaliLine.LineReturnType.Char;
111 | case "j":
112 | return SmaliLine.LineReturnType.Long;
113 | case "d":
114 | return SmaliLine.LineReturnType.Double;
115 | default:
116 | return SmaliLine.LineReturnType.Custom;
117 | }
118 | }
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/smali2java/Smali/SmaliCall.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Smali2Java
7 | {
8 | public class SmaliCall
9 | {
10 | [Flags]
11 | public enum ECallFlags
12 | {
13 | ClassInit = 1,
14 | Constructor = 2
15 | }
16 |
17 | public String ClassName;
18 | public String Method;
19 | public String Variable;
20 | public String Return;
21 | public List Parameters = new List();
22 | public SmaliLine.LineReturnType SmaliReturnType;
23 | public ECallFlags CallFlags;
24 |
25 | public static SmaliCall Parse(String l)
26 | {
27 | SmaliCall rv = new SmaliCall();
28 | rv.Method = l;
29 |
30 | if (l.Contains("("))
31 | {
32 | // Function call
33 | rv.Method = rv.Method.Substring(0, rv.Method.IndexOf("("));
34 | rv.Return = l.Substring(l.LastIndexOf(")") + 1);
35 | if (rv.Return.Length > 0)
36 | rv.SmaliReturnType = SmaliUtils.General.GetReturnType(rv.Return);
37 |
38 | if(rv.Method.Contains("->"))
39 | {
40 | rv.ClassName = rv.Method.Substring(0, rv.Method.IndexOf(";"));
41 | rv.Method = rv.Method.Substring(rv.Method.IndexOf("->") + 2);
42 | }
43 | }
44 | else
45 | {
46 | if (l.Contains("/"))
47 | {
48 | rv.ClassName = l;
49 | if (l.Contains("->"))
50 | rv.ClassName = l.Substring(0, l.IndexOf("->"));
51 |
52 | // Get class name out
53 | rv.ClassName = rv.ClassName.Substring(0, rv.ClassName.LastIndexOf('/'));
54 | rv.Method = l.Substring(rv.ClassName.Length + 1);
55 | if (l.Contains(":"))
56 | {
57 | rv.Variable = rv.Method.Substring(rv.Method.IndexOf("->") + 2);
58 | rv.Variable = rv.Variable.Substring(0, rv.Variable.IndexOf(":"));
59 | }
60 | rv.Method = rv.Method.Substring(0, rv.Method.IndexOf(";"));
61 | }
62 | }
63 |
64 | if (rv.Method.EndsWith(";"))
65 | rv.Method = rv.Method.Remove(rv.Method.Length - 1, 1);
66 |
67 | if(l.Contains("("))
68 | {
69 | // Get parameters
70 | String sParameters = l.Substring(l.IndexOf("(") + 1);
71 | sParameters = sParameters.Substring(0, sParameters.IndexOf(")"));
72 | if (sParameters.Length > 0)
73 | {
74 | String[] aParm = sParameters.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
75 | foreach (String p in aParm)
76 | if (p.StartsWith("L"))
77 | {
78 | rv.Parameters.Add(new SmaliParameter()
79 | {
80 | Type = p,
81 | });
82 | }
83 | else
84 | {
85 | for (int i = 0 ; i < p.Length; i++)
86 | {
87 | if (!p[i].Equals('L'))
88 | {
89 | rv.Parameters.Add(new SmaliParameter()
90 | {
91 | Type = String.Empty + p[i],
92 | });
93 | }
94 | else if (p[i].Equals('[')) // This is an Array.
95 | {
96 | if (p[i+1].Equals('L'))
97 | {
98 | rv.Parameters.Add(new SmaliParameter()
99 | {
100 | Type = p.Substring(i),
101 | });
102 | break;
103 | }
104 | else
105 | {
106 | rv.Parameters.Add(new SmaliParameter()
107 | {
108 | Type = String.Empty + p[i] + p[i+1],
109 | });
110 | i++;
111 | }
112 | }
113 | else
114 | {
115 | rv.Parameters.Add(new SmaliParameter()
116 | {
117 | Type = p.Substring(i),
118 | });
119 | break;
120 | }
121 | }
122 | }
123 | }
124 | }
125 |
126 | // Set flags
127 | if (rv.Method == "")
128 | {
129 | rv.Method = String.Empty;
130 | rv.Return = String.Empty;
131 | rv.SmaliReturnType = SmaliLine.LineReturnType.Custom;
132 | rv.CallFlags |= ECallFlags.ClassInit;
133 | }
134 | if (rv.Method == "")
135 | {
136 | rv.Return = String.Empty;
137 | rv.SmaliReturnType = SmaliLine.LineReturnType.Custom;
138 | rv.CallFlags |= ECallFlags.Constructor;
139 | }
140 |
141 | return rv;
142 | }
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/smali2java/Samples/AndroidHandler.smali:
--------------------------------------------------------------------------------
1 | .class public Lcom/android/internal/logging/AndroidHandler;
2 | .super Ljava/util/logging/Handler;
3 | .source "AndroidHandler.java"
4 |
5 | # interfaces
6 | .implements Ldalvik/system/DalvikLogHandler;
7 |
8 |
9 | # static fields
10 | .field private static final THE_FORMATTER:Ljava/util/logging/Formatter;
11 |
12 |
13 | # direct methods
14 | .method static constructor ()V
15 | .registers 1
16 |
17 | .prologue
18 | .line 88
19 | new-instance v0, Lcom/android/internal/logging/AndroidHandler$1;
20 |
21 | invoke-direct {v0}, Lcom/android/internal/logging/AndroidHandler$1;->()V
22 |
23 | sput-object v0, Lcom/android/internal/logging/AndroidHandler;->THE_FORMATTER:Ljava/util/logging/Formatter;
24 |
25 | return-void
26 | .end method
27 |
28 | .method public constructor ()V
29 | .registers 2
30 |
31 | .prologue
32 | .line 109
33 | invoke-direct {p0}, Ljava/util/logging/Handler;->()V
34 |
35 | .line 110
36 | sget-object v0, Lcom/android/internal/logging/AndroidHandler;->THE_FORMATTER:Ljava/util/logging/Formatter;
37 |
38 | invoke-virtual {p0, v0}, Lcom/android/internal/logging/AndroidHandler;->setFormatter(Ljava/util/logging/Formatter;)V
39 |
40 | .line 111
41 | return-void
42 | .end method
43 |
44 | .method static getAndroidLevel(Ljava/util/logging/Level;)I
45 | .registers 3
46 | .param p0, "level" # Ljava/util/logging/Level;
47 |
48 | .prologue
49 | .line 161
50 | invoke-virtual {p0}, Ljava/util/logging/Level;->intValue()I
51 |
52 | move-result v0
53 |
54 | .line 162
55 | .local v0, "value":I
56 | const/16 v1, 0x3e8
57 |
58 | if-lt v0, v1, :cond_a
59 |
60 | .line 163
61 | const/4 v1, 0x6
62 |
63 | .line 169
64 | :goto_9
65 | return v1
66 |
67 | .line 164
68 | :cond_a
69 | const/16 v1, 0x384
70 |
71 | if-lt v0, v1, :cond_10
72 |
73 | .line 165
74 | const/4 v1, 0x5
75 |
76 | goto :goto_9
77 |
78 | .line 166
79 | :cond_10
80 | const/16 v1, 0x320
81 |
82 | if-lt v0, v1, :cond_16
83 |
84 | .line 167
85 | const/4 v1, 0x4
86 |
87 | goto :goto_9
88 |
89 | .line 169
90 | :cond_16
91 | const/4 v1, 0x3
92 |
93 | goto :goto_9
94 | .end method
95 |
96 |
97 | # virtual methods
98 | .method public close()V
99 | .registers 1
100 |
101 | .prologue
102 | .line 116
103 | return-void
104 | .end method
105 |
106 | .method public flush()V
107 | .registers 1
108 |
109 | .prologue
110 | .line 121
111 | return-void
112 | .end method
113 |
114 | .method public publish(Ljava/util/logging/LogRecord;)V
115 | .registers 8
116 | .param p1, "record" # Ljava/util/logging/LogRecord;
117 |
118 | .prologue
119 | .line 125
120 | invoke-virtual {p1}, Ljava/util/logging/LogRecord;->getLevel()Ljava/util/logging/Level;
121 |
122 | move-result-object v4
123 |
124 | invoke-static {v4}, Lcom/android/internal/logging/AndroidHandler;->getAndroidLevel(Ljava/util/logging/Level;)I
125 |
126 | move-result v1
127 |
128 | .line 126
129 | .local v1, "level":I
130 | invoke-virtual {p1}, Ljava/util/logging/LogRecord;->getLoggerName()Ljava/lang/String;
131 |
132 | move-result-object v4
133 |
134 | invoke-static {v4}, Ldalvik/system/DalvikLogging;->loggerNameToTag(Ljava/lang/String;)Ljava/lang/String;
135 |
136 | move-result-object v3
137 |
138 | .line 127
139 | .local v3, "tag":Ljava/lang/String;
140 | invoke-static {v3, v1}, Landroid/util/Log;->isLoggable(Ljava/lang/String;I)Z
141 |
142 | move-result v4
143 |
144 | if-nez v4, :cond_17
145 |
146 | .line 137
147 | :goto_16
148 | return-void
149 |
150 | .line 132
151 | :cond_17
152 | :try_start_17
153 | invoke-virtual {p0}, Lcom/android/internal/logging/AndroidHandler;->getFormatter()Ljava/util/logging/Formatter;
154 |
155 | move-result-object v4
156 |
157 | invoke-virtual {v4, p1}, Ljava/util/logging/Formatter;->format(Ljava/util/logging/LogRecord;)Ljava/lang/String;
158 |
159 | move-result-object v2
160 |
161 | .line 133
162 | .local v2, "message":Ljava/lang/String;
163 | invoke-static {v1, v3, v2}, Landroid/util/Log;->println(ILjava/lang/String;Ljava/lang/String;)I
164 | :try_end_22
165 | .catch Ljava/lang/RuntimeException; {:try_start_17 .. :try_end_22} :catch_23
166 |
167 | goto :goto_16
168 |
169 | .line 134
170 | .end local v2 # "message":Ljava/lang/String;
171 | :catch_23
172 | move-exception v0
173 |
174 | .line 135
175 | .local v0, "e":Ljava/lang/RuntimeException;
176 | const-string v4, "AndroidHandler"
177 |
178 | const-string v5, "Error logging message."
179 |
180 | invoke-static {v4, v5, v0}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
181 |
182 | goto :goto_16
183 | .end method
184 |
185 | .method public publish(Ljava/util/logging/Logger;Ljava/lang/String;Ljava/util/logging/Level;Ljava/lang/String;)V
186 | .registers 9
187 | .param p1, "source" # Ljava/util/logging/Logger;
188 | .param p2, "tag" # Ljava/lang/String;
189 | .param p3, "level" # Ljava/util/logging/Level;
190 | .param p4, "message" # Ljava/lang/String;
191 |
192 | .prologue
193 | .line 141
194 | invoke-static {p3}, Lcom/android/internal/logging/AndroidHandler;->getAndroidLevel(Ljava/util/logging/Level;)I
195 |
196 | move-result v1
197 |
198 | .line 142
199 | .local v1, "priority":I
200 | invoke-static {p2, v1}, Landroid/util/Log;->isLoggable(Ljava/lang/String;I)Z
201 |
202 | move-result v2
203 |
204 | if-nez v2, :cond_b
205 |
206 | .line 151
207 | :goto_a
208 | return-void
209 |
210 | .line 147
211 | :cond_b
212 | :try_start_b
213 | invoke-static {v1, p2, p4}, Landroid/util/Log;->println(ILjava/lang/String;Ljava/lang/String;)I
214 | :try_end_e
215 | .catch Ljava/lang/RuntimeException; {:try_start_b .. :try_end_e} :catch_f
216 |
217 | goto :goto_a
218 |
219 | .line 148
220 | :catch_f
221 | move-exception v0
222 |
223 | .line 149
224 | .local v0, "e":Ljava/lang/RuntimeException;
225 | const-string v2, "AndroidHandler"
226 |
227 | const-string v3, "Error logging message."
228 |
229 | invoke-static {v2, v3, v0}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
230 |
231 | goto :goto_a
232 | .end method
233 |
--------------------------------------------------------------------------------
/Smali2Java-v4/Samples/AndroidHandler.smali:
--------------------------------------------------------------------------------
1 | .class public Lcom/android/internal/logging/AndroidHandler;
2 | .super Ljava/util/logging/Handler;
3 | .source "AndroidHandler.java"
4 |
5 | # interfaces
6 | .implements Ldalvik/system/DalvikLogHandler;
7 |
8 |
9 | # static fields
10 | .field private static final THE_FORMATTER:Ljava/util/logging/Formatter;
11 |
12 |
13 | # direct methods
14 | .method static constructor ()V
15 | .registers 1
16 |
17 | .prologue
18 | .line 88
19 | new-instance v0, Lcom/android/internal/logging/AndroidHandler$1;
20 |
21 | invoke-direct {v0}, Lcom/android/internal/logging/AndroidHandler$1;->()V
22 |
23 | sput-object v0, Lcom/android/internal/logging/AndroidHandler;->THE_FORMATTER:Ljava/util/logging/Formatter;
24 |
25 | return-void
26 | .end method
27 |
28 | .method public constructor ()V
29 | .registers 2
30 |
31 | .prologue
32 | .line 109
33 | invoke-direct {p0}, Ljava/util/logging/Handler;->()V
34 |
35 | .line 110
36 | sget-object v0, Lcom/android/internal/logging/AndroidHandler;->THE_FORMATTER:Ljava/util/logging/Formatter;
37 |
38 | invoke-virtual {p0, v0}, Lcom/android/internal/logging/AndroidHandler;->setFormatter(Ljava/util/logging/Formatter;)V
39 |
40 | .line 111
41 | return-void
42 | .end method
43 |
44 | .method static getAndroidLevel(Ljava/util/logging/Level;)I
45 | .registers 3
46 | .param p0, "level" # Ljava/util/logging/Level;
47 |
48 | .prologue
49 | .line 161
50 | invoke-virtual {p0}, Ljava/util/logging/Level;->intValue()I
51 |
52 | move-result v0
53 |
54 | .line 162
55 | .local v0, "value":I
56 | const/16 v1, 0x3e8
57 |
58 | if-lt v0, v1, :cond_a
59 |
60 | .line 163
61 | const/4 v1, 0x6
62 |
63 | .line 169
64 | :goto_9
65 | return v1
66 |
67 | .line 164
68 | :cond_a
69 | const/16 v1, 0x384
70 |
71 | if-lt v0, v1, :cond_10
72 |
73 | .line 165
74 | const/4 v1, 0x5
75 |
76 | goto :goto_9
77 |
78 | .line 166
79 | :cond_10
80 | const/16 v1, 0x320
81 |
82 | if-lt v0, v1, :cond_16
83 |
84 | .line 167
85 | const/4 v1, 0x4
86 |
87 | goto :goto_9
88 |
89 | .line 169
90 | :cond_16
91 | const/4 v1, 0x3
92 |
93 | goto :goto_9
94 | .end method
95 |
96 |
97 | # virtual methods
98 | .method public close()V
99 | .registers 1
100 |
101 | .prologue
102 | .line 116
103 | return-void
104 | .end method
105 |
106 | .method public flush()V
107 | .registers 1
108 |
109 | .prologue
110 | .line 121
111 | return-void
112 | .end method
113 |
114 | .method public publish(Ljava/util/logging/LogRecord;)V
115 | .registers 8
116 | .param p1, "record" # Ljava/util/logging/LogRecord;
117 |
118 | .prologue
119 | .line 125
120 | invoke-virtual {p1}, Ljava/util/logging/LogRecord;->getLevel()Ljava/util/logging/Level;
121 |
122 | move-result-object v4
123 |
124 | invoke-static {v4}, Lcom/android/internal/logging/AndroidHandler;->getAndroidLevel(Ljava/util/logging/Level;)I
125 |
126 | move-result v1
127 |
128 | .line 126
129 | .local v1, "level":I
130 | invoke-virtual {p1}, Ljava/util/logging/LogRecord;->getLoggerName()Ljava/lang/String;
131 |
132 | move-result-object v4
133 |
134 | invoke-static {v4}, Ldalvik/system/DalvikLogging;->loggerNameToTag(Ljava/lang/String;)Ljava/lang/String;
135 |
136 | move-result-object v3
137 |
138 | .line 127
139 | .local v3, "tag":Ljava/lang/String;
140 | invoke-static {v3, v1}, Landroid/util/Log;->isLoggable(Ljava/lang/String;I)Z
141 |
142 | move-result v4
143 |
144 | if-nez v4, :cond_17
145 |
146 | .line 137
147 | :goto_16
148 | return-void
149 |
150 | .line 132
151 | :cond_17
152 | :try_start_17
153 | invoke-virtual {p0}, Lcom/android/internal/logging/AndroidHandler;->getFormatter()Ljava/util/logging/Formatter;
154 |
155 | move-result-object v4
156 |
157 | invoke-virtual {v4, p1}, Ljava/util/logging/Formatter;->format(Ljava/util/logging/LogRecord;)Ljava/lang/String;
158 |
159 | move-result-object v2
160 |
161 | .line 133
162 | .local v2, "message":Ljava/lang/String;
163 | invoke-static {v1, v3, v2}, Landroid/util/Log;->println(ILjava/lang/String;Ljava/lang/String;)I
164 | :try_end_22
165 | .catch Ljava/lang/RuntimeException; {:try_start_17 .. :try_end_22} :catch_23
166 |
167 | goto :goto_16
168 |
169 | .line 134
170 | .end local v2 # "message":Ljava/lang/String;
171 | :catch_23
172 | move-exception v0
173 |
174 | .line 135
175 | .local v0, "e":Ljava/lang/RuntimeException;
176 | const-string v4, "AndroidHandler"
177 |
178 | const-string v5, "Error logging message."
179 |
180 | invoke-static {v4, v5, v0}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
181 |
182 | goto :goto_16
183 | .end method
184 |
185 | .method public publish(Ljava/util/logging/Logger;Ljava/lang/String;Ljava/util/logging/Level;Ljava/lang/String;)V
186 | .registers 9
187 | .param p1, "source" # Ljava/util/logging/Logger;
188 | .param p2, "tag" # Ljava/lang/String;
189 | .param p3, "level" # Ljava/util/logging/Level;
190 | .param p4, "message" # Ljava/lang/String;
191 |
192 | .prologue
193 | .line 141
194 | invoke-static {p3}, Lcom/android/internal/logging/AndroidHandler;->getAndroidLevel(Ljava/util/logging/Level;)I
195 |
196 | move-result v1
197 |
198 | .line 142
199 | .local v1, "priority":I
200 | invoke-static {p2, v1}, Landroid/util/Log;->isLoggable(Ljava/lang/String;I)Z
201 |
202 | move-result v2
203 |
204 | if-nez v2, :cond_b
205 |
206 | .line 151
207 | :goto_a
208 | return-void
209 |
210 | .line 147
211 | :cond_b
212 | :try_start_b
213 | invoke-static {v1, p2, p4}, Landroid/util/Log;->println(ILjava/lang/String;Ljava/lang/String;)I
214 | :try_end_e
215 | .catch Ljava/lang/RuntimeException; {:try_start_b .. :try_end_e} :catch_f
216 |
217 | goto :goto_a
218 |
219 | .line 148
220 | :catch_f
221 | move-exception v0
222 |
223 | .line 149
224 | .local v0, "e":Ljava/lang/RuntimeException;
225 | const-string v2, "AndroidHandler"
226 |
227 | const-string v3, "Error logging message."
228 |
229 | invoke-static {v2, v3, v0}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
230 |
231 | goto :goto_a
232 | .end method
233 |
--------------------------------------------------------------------------------
/smali2java/Samples/NetqinSmsFilter.smali:
--------------------------------------------------------------------------------
1 | .class public Lcom/netqin/NqSmsFilter;
2 | .super Ljava/lang/Object;
3 | .source "NqSmsFilter.java"
4 |
5 |
6 | # static fields
7 | .field private static final CONTENT_URI:Landroid/net/Uri;
8 |
9 | .field private static filter:Lcom/netqin/NqSmsFilter;
10 |
11 |
12 | # instance fields
13 | .field private ctx:Landroid/content/Context;
14 |
15 |
16 | # direct methods
17 | .method static constructor ()V
18 | .registers 1
19 |
20 | .prologue
21 | .line 23
22 | const/4 v0, 0x0
23 |
24 | sput-object v0, Lcom/netqin/NqSmsFilter;->filter:Lcom/netqin/NqSmsFilter;
25 |
26 | .line 28
27 | const-string v0, "content://com.netqin.provider.SmsFilterProvider"
28 |
29 | invoke-static {v0}, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;
30 |
31 | move-result-object v0
32 |
33 | sput-object v0, Lcom/netqin/NqSmsFilter;->CONTENT_URI:Landroid/net/Uri;
34 |
35 | .line 22
36 | return-void
37 | .end method
38 |
39 | .method private constructor (Landroid/content/Context;)V
40 | .registers 2
41 | .param p1, "ctx" # Landroid/content/Context;
42 |
43 | .prologue
44 | .line 25
45 | invoke-direct {p0}, Ljava/lang/Object;->()V
46 |
47 | .line 26
48 | iput-object p1, p0, Lcom/netqin/NqSmsFilter;->ctx:Landroid/content/Context;
49 |
50 | .line 27
51 | return-void
52 | .end method
53 |
54 | .method public static declared-synchronized getInstance(Landroid/content/Context;)Lcom/netqin/NqSmsFilter;
55 | .registers 3
56 | .param p0, "context" # Landroid/content/Context;
57 |
58 | .prologue
59 | .line 36
60 | const-class v1, Lcom/netqin/NqSmsFilter;
61 |
62 | monitor-enter v1
63 |
64 | :try_start_3
65 | sget-object v0, Lcom/netqin/NqSmsFilter;->filter:Lcom/netqin/NqSmsFilter;
66 |
67 | if-nez v0, :cond_e
68 |
69 | .line 37
70 | new-instance v0, Lcom/netqin/NqSmsFilter;
71 |
72 | invoke-direct {v0, p0}, Lcom/netqin/NqSmsFilter;->(Landroid/content/Context;)V
73 |
74 | sput-object v0, Lcom/netqin/NqSmsFilter;->filter:Lcom/netqin/NqSmsFilter;
75 |
76 | .line 40
77 | :cond_e
78 | sget-object v0, Lcom/netqin/NqSmsFilter;->filter:Lcom/netqin/NqSmsFilter;
79 | :try_end_10
80 | .catchall {:try_start_3 .. :try_end_10} :catchall_12
81 |
82 | monitor-exit v1
83 |
84 | return-object v0
85 |
86 | .line 36
87 | :catchall_12
88 | move-exception v0
89 |
90 | monitor-exit v1
91 |
92 | throw v0
93 | .end method
94 |
95 |
96 | # virtual methods
97 | .method public nqGetNetQinLogo()Landroid/graphics/Bitmap;
98 | .registers 5
99 |
100 | .prologue
101 | .line 94
102 | const/4 v0, 0x0
103 |
104 | .line 96
105 | .local v0, "b":Landroid/graphics/Bitmap;
106 | :try_start_1
107 | iget-object v2, p0, Lcom/netqin/NqSmsFilter;->ctx:Landroid/content/Context;
108 |
109 | invoke-virtual {v2}, Landroid/content/Context;->getResources()Landroid/content/res/Resources;
110 |
111 | move-result-object v2
112 |
113 | invoke-virtual {v2}, Landroid/content/res/Resources;->getAssets()Landroid/content/res/AssetManager;
114 |
115 | move-result-object v2
116 |
117 | const-string/jumbo v3, "netqin_icon.png"
118 |
119 | invoke-virtual {v2, v3}, Landroid/content/res/AssetManager;->open(Ljava/lang/String;)Ljava/io/InputStream;
120 |
121 | move-result-object v2
122 |
123 | invoke-static {v2}, Landroid/graphics/BitmapFactory;->decodeStream(Ljava/io/InputStream;)Landroid/graphics/Bitmap;
124 | :try_end_15
125 | .catch Ljava/io/IOException; {:try_start_1 .. :try_end_15} :catch_17
126 |
127 | move-result-object v0
128 |
129 | .line 103
130 | :goto_16
131 | return-object v0
132 |
133 | .line 98
134 | :catch_17
135 | move-exception v1
136 |
137 | .line 100
138 | .local v1, "e":Ljava/io/IOException;
139 | invoke-virtual {v1}, Ljava/io/IOException;->printStackTrace()V
140 |
141 | goto :goto_16
142 | .end method
143 |
144 | .method public nqGetNetQinText()Ljava/lang/String;
145 | .registers 9
146 |
147 | .prologue
148 | const/4 v2, 0x0
149 |
150 | .line 77
151 | const-string v7, "Powered by NetQin"
152 |
153 | .line 78
154 | .local v7, "s":Ljava/lang/String;
155 | iget-object v1, p0, Lcom/netqin/NqSmsFilter;->ctx:Landroid/content/Context;
156 |
157 | invoke-virtual {v1}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;
158 |
159 | move-result-object v0
160 |
161 | .line 79
162 | .local v0, "cr":Landroid/content/ContentResolver;
163 | sget-object v1, Lcom/netqin/NqSmsFilter;->CONTENT_URI:Landroid/net/Uri;
164 |
165 | const-string v3, "NetqinText"
166 |
167 | move-object v4, v2
168 |
169 | move-object v5, v2
170 |
171 | invoke-virtual/range {v0 .. v5}, Landroid/content/ContentResolver;->query(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;
172 |
173 | move-result-object v6
174 |
175 | .line 80
176 | .local v6, "c":Landroid/database/Cursor;
177 | if-eqz v6, :cond_23
178 |
179 | .line 81
180 | invoke-interface {v6}, Landroid/database/Cursor;->moveToFirst()Z
181 |
182 | move-result v1
183 |
184 | if-eqz v1, :cond_20
185 |
186 | .line 82
187 | const/4 v1, 0x0
188 |
189 | invoke-interface {v6, v1}, Landroid/database/Cursor;->getString(I)Ljava/lang/String;
190 |
191 | move-result-object v7
192 |
193 | .line 84
194 | :cond_20
195 | invoke-interface {v6}, Landroid/database/Cursor;->close()V
196 |
197 | .line 86
198 | :cond_23
199 | return-object v7
200 | .end method
201 |
202 | .method public nqSmsFilter(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
203 | .registers 15
204 | .param p1, "smsNumber" # Ljava/lang/String;
205 | .param p2, "smsContent" # Ljava/lang/String;
206 | .param p3, "packageName" # Ljava/lang/String;
207 | .param p4, "appName" # Ljava/lang/String;
208 |
209 | .prologue
210 | const/4 v2, 0x0
211 |
212 | const/4 v8, 0x1
213 |
214 | const/4 v9, 0x0
215 |
216 | .line 52
217 | const/4 v6, 0x0
218 |
219 | .line 54
220 | .local v6, "b":I
221 | const/4 v1, 0x4
222 |
223 | new-array v4, v1, [Ljava/lang/String;
224 |
225 | aput-object p1, v4, v9
226 |
227 | aput-object p2, v4, v8
228 |
229 | const/4 v1, 0x2
230 |
231 | aput-object p3, v4, v1
232 |
233 | const/4 v1, 0x3
234 |
235 | aput-object p4, v4, v1
236 |
237 | .line 56
238 | .local v4, "args":[Ljava/lang/String;
239 | iget-object v1, p0, Lcom/netqin/NqSmsFilter;->ctx:Landroid/content/Context;
240 |
241 | invoke-virtual {v1}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;
242 |
243 | move-result-object v0
244 |
245 | .line 57
246 | .local v0, "cr":Landroid/content/ContentResolver;
247 | sget-object v1, Lcom/netqin/NqSmsFilter;->CONTENT_URI:Landroid/net/Uri;
248 |
249 | move-object v3, v2
250 |
251 | move-object v5, v2
252 |
253 | invoke-virtual/range {v0 .. v5}, Landroid/content/ContentResolver;->query(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;
254 |
255 | move-result-object v7
256 |
257 | .line 58
258 | .local v7, "c":Landroid/database/Cursor;
259 | if-eqz v7, :cond_2e
260 |
261 | .line 59
262 | invoke-interface {v7}, Landroid/database/Cursor;->moveToFirst()Z
263 |
264 | move-result v1
265 |
266 | if-eqz v1, :cond_2b
267 |
268 | .line 60
269 | invoke-interface {v7, v9}, Landroid/database/Cursor;->getInt(I)I
270 |
271 | move-result v6
272 |
273 | .line 62
274 | :cond_2b
275 | invoke-interface {v7}, Landroid/database/Cursor;->close()V
276 |
277 | .line 65
278 | :cond_2e
279 | if-ne v6, v8, :cond_32
280 |
281 | move v1, v8
282 |
283 | .line 68
284 | :goto_31
285 | return v1
286 |
287 | :cond_32
288 | move v1, v9
289 |
290 | goto :goto_31
291 | .end method
292 |
--------------------------------------------------------------------------------
/Smali2Java-v4/Samples/NetqinSmsFilter.smali:
--------------------------------------------------------------------------------
1 | .class public Lcom/netqin/NqSmsFilter;
2 | .super Ljava/lang/Object;
3 | .source "NqSmsFilter.java"
4 |
5 |
6 | # static fields
7 | .field private static final CONTENT_URI:Landroid/net/Uri;
8 |
9 | .field private static filter:Lcom/netqin/NqSmsFilter;
10 |
11 |
12 | # instance fields
13 | .field private ctx:Landroid/content/Context;
14 |
15 |
16 | # direct methods
17 | .method static constructor ()V
18 | .registers 1
19 |
20 | .prologue
21 | .line 23
22 | const/4 v0, 0x0
23 |
24 | sput-object v0, Lcom/netqin/NqSmsFilter;->filter:Lcom/netqin/NqSmsFilter;
25 |
26 | .line 28
27 | const-string v0, "content://com.netqin.provider.SmsFilterProvider"
28 |
29 | invoke-static {v0}, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;
30 |
31 | move-result-object v0
32 |
33 | sput-object v0, Lcom/netqin/NqSmsFilter;->CONTENT_URI:Landroid/net/Uri;
34 |
35 | .line 22
36 | return-void
37 | .end method
38 |
39 | .method private constructor (Landroid/content/Context;)V
40 | .registers 2
41 | .param p1, "ctx" # Landroid/content/Context;
42 |
43 | .prologue
44 | .line 25
45 | invoke-direct {p0}, Ljava/lang/Object;->()V
46 |
47 | .line 26
48 | iput-object p1, p0, Lcom/netqin/NqSmsFilter;->ctx:Landroid/content/Context;
49 |
50 | .line 27
51 | return-void
52 | .end method
53 |
54 | .method public static declared-synchronized getInstance(Landroid/content/Context;)Lcom/netqin/NqSmsFilter;
55 | .registers 3
56 | .param p0, "context" # Landroid/content/Context;
57 |
58 | .prologue
59 | .line 36
60 | const-class v1, Lcom/netqin/NqSmsFilter;
61 |
62 | monitor-enter v1
63 |
64 | :try_start_3
65 | sget-object v0, Lcom/netqin/NqSmsFilter;->filter:Lcom/netqin/NqSmsFilter;
66 |
67 | if-nez v0, :cond_e
68 |
69 | .line 37
70 | new-instance v0, Lcom/netqin/NqSmsFilter;
71 |
72 | invoke-direct {v0, p0}, Lcom/netqin/NqSmsFilter;->(Landroid/content/Context;)V
73 |
74 | sput-object v0, Lcom/netqin/NqSmsFilter;->filter:Lcom/netqin/NqSmsFilter;
75 |
76 | .line 40
77 | :cond_e
78 | sget-object v0, Lcom/netqin/NqSmsFilter;->filter:Lcom/netqin/NqSmsFilter;
79 | :try_end_10
80 | .catchall {:try_start_3 .. :try_end_10} :catchall_12
81 |
82 | monitor-exit v1
83 |
84 | return-object v0
85 |
86 | .line 36
87 | :catchall_12
88 | move-exception v0
89 |
90 | monitor-exit v1
91 |
92 | throw v0
93 | .end method
94 |
95 |
96 | # virtual methods
97 | .method public nqGetNetQinLogo()Landroid/graphics/Bitmap;
98 | .registers 5
99 |
100 | .prologue
101 | .line 94
102 | const/4 v0, 0x0
103 |
104 | .line 96
105 | .local v0, "b":Landroid/graphics/Bitmap;
106 | :try_start_1
107 | iget-object v2, p0, Lcom/netqin/NqSmsFilter;->ctx:Landroid/content/Context;
108 |
109 | invoke-virtual {v2}, Landroid/content/Context;->getResources()Landroid/content/res/Resources;
110 |
111 | move-result-object v2
112 |
113 | invoke-virtual {v2}, Landroid/content/res/Resources;->getAssets()Landroid/content/res/AssetManager;
114 |
115 | move-result-object v2
116 |
117 | const-string/jumbo v3, "netqin_icon.png"
118 |
119 | invoke-virtual {v2, v3}, Landroid/content/res/AssetManager;->open(Ljava/lang/String;)Ljava/io/InputStream;
120 |
121 | move-result-object v2
122 |
123 | invoke-static {v2}, Landroid/graphics/BitmapFactory;->decodeStream(Ljava/io/InputStream;)Landroid/graphics/Bitmap;
124 | :try_end_15
125 | .catch Ljava/io/IOException; {:try_start_1 .. :try_end_15} :catch_17
126 |
127 | move-result-object v0
128 |
129 | .line 103
130 | :goto_16
131 | return-object v0
132 |
133 | .line 98
134 | :catch_17
135 | move-exception v1
136 |
137 | .line 100
138 | .local v1, "e":Ljava/io/IOException;
139 | invoke-virtual {v1}, Ljava/io/IOException;->printStackTrace()V
140 |
141 | goto :goto_16
142 | .end method
143 |
144 | .method public nqGetNetQinText()Ljava/lang/String;
145 | .registers 9
146 |
147 | .prologue
148 | const/4 v2, 0x0
149 |
150 | .line 77
151 | const-string v7, "Powered by NetQin"
152 |
153 | .line 78
154 | .local v7, "s":Ljava/lang/String;
155 | iget-object v1, p0, Lcom/netqin/NqSmsFilter;->ctx:Landroid/content/Context;
156 |
157 | invoke-virtual {v1}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;
158 |
159 | move-result-object v0
160 |
161 | .line 79
162 | .local v0, "cr":Landroid/content/ContentResolver;
163 | sget-object v1, Lcom/netqin/NqSmsFilter;->CONTENT_URI:Landroid/net/Uri;
164 |
165 | const-string v3, "NetqinText"
166 |
167 | move-object v4, v2
168 |
169 | move-object v5, v2
170 |
171 | invoke-virtual/range {v0 .. v5}, Landroid/content/ContentResolver;->query(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;
172 |
173 | move-result-object v6
174 |
175 | .line 80
176 | .local v6, "c":Landroid/database/Cursor;
177 | if-eqz v6, :cond_23
178 |
179 | .line 81
180 | invoke-interface {v6}, Landroid/database/Cursor;->moveToFirst()Z
181 |
182 | move-result v1
183 |
184 | if-eqz v1, :cond_20
185 |
186 | .line 82
187 | const/4 v1, 0x0
188 |
189 | invoke-interface {v6, v1}, Landroid/database/Cursor;->getString(I)Ljava/lang/String;
190 |
191 | move-result-object v7
192 |
193 | .line 84
194 | :cond_20
195 | invoke-interface {v6}, Landroid/database/Cursor;->close()V
196 |
197 | .line 86
198 | :cond_23
199 | return-object v7
200 | .end method
201 |
202 | .method public nqSmsFilter(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
203 | .registers 15
204 | .param p1, "smsNumber" # Ljava/lang/String;
205 | .param p2, "smsContent" # Ljava/lang/String;
206 | .param p3, "packageName" # Ljava/lang/String;
207 | .param p4, "appName" # Ljava/lang/String;
208 |
209 | .prologue
210 | const/4 v2, 0x0
211 |
212 | const/4 v8, 0x1
213 |
214 | const/4 v9, 0x0
215 |
216 | .line 52
217 | const/4 v6, 0x0
218 |
219 | .line 54
220 | .local v6, "b":I
221 | const/4 v1, 0x4
222 |
223 | new-array v4, v1, [Ljava/lang/String;
224 |
225 | aput-object p1, v4, v9
226 |
227 | aput-object p2, v4, v8
228 |
229 | const/4 v1, 0x2
230 |
231 | aput-object p3, v4, v1
232 |
233 | const/4 v1, 0x3
234 |
235 | aput-object p4, v4, v1
236 |
237 | .line 56
238 | .local v4, "args":[Ljava/lang/String;
239 | iget-object v1, p0, Lcom/netqin/NqSmsFilter;->ctx:Landroid/content/Context;
240 |
241 | invoke-virtual {v1}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;
242 |
243 | move-result-object v0
244 |
245 | .line 57
246 | .local v0, "cr":Landroid/content/ContentResolver;
247 | sget-object v1, Lcom/netqin/NqSmsFilter;->CONTENT_URI:Landroid/net/Uri;
248 |
249 | move-object v3, v2
250 |
251 | move-object v5, v2
252 |
253 | invoke-virtual/range {v0 .. v5}, Landroid/content/ContentResolver;->query(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;
254 |
255 | move-result-object v7
256 |
257 | .line 58
258 | .local v7, "c":Landroid/database/Cursor;
259 | if-eqz v7, :cond_2e
260 |
261 | .line 59
262 | invoke-interface {v7}, Landroid/database/Cursor;->moveToFirst()Z
263 |
264 | move-result v1
265 |
266 | if-eqz v1, :cond_2b
267 |
268 | .line 60
269 | invoke-interface {v7, v9}, Landroid/database/Cursor;->getInt(I)I
270 |
271 | move-result v6
272 |
273 | .line 62
274 | :cond_2b
275 | invoke-interface {v7}, Landroid/database/Cursor;->close()V
276 |
277 | .line 65
278 | :cond_2e
279 | if-ne v6, v8, :cond_32
280 |
281 | move v1, v8
282 |
283 | .line 68
284 | :goto_31
285 | return v1
286 |
287 | :cond_32
288 | move v1, v9
289 |
290 | goto :goto_31
291 | .end method
292 |
--------------------------------------------------------------------------------
/smali2java/Smali/2SmaliMethod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Smali2Java
8 | {
9 | public class SmaliMethod
10 | {
11 | public SmaliClass ParentClass;
12 | public SmaliVM vm = new SmaliVM();
13 | public StringBuilder Buffer = new StringBuilder();
14 | public StringBuilder JavaBuffer = new StringBuilder();
15 |
16 | public List Java = new List();
17 | public List Lines = new List();
18 | public SmaliLine.EAccessMod AccessModifiers;
19 | public SmaliLine.ENonAccessMod NonAccessModifiers;
20 | public SmaliLine.LineReturnType ReturnType;
21 | public List Parameters = new List();
22 | public String Name;
23 | public String SmaliReturnType;
24 | public bool IsClinit = false;
25 | public bool IsConstructor = false;
26 | public bool IsFirstParam = true;
27 | public bool Isp0self = false;
28 |
29 | // MAIN TRANSLATION METHOD, FAKE VIRTUAL MACHINE
30 | public void Process()
31 | {
32 | for (int i = 0; i < Lines.Count; i++)
33 | {
34 | SmaliLine l = Lines[i];
35 | if (l.bIsDirective)
36 | {
37 | #region Directives
38 | switch (l.Instruction)
39 | {
40 | case SmaliLine.LineInstruction.Method:
41 | #region Method
42 | AccessModifiers = l.AccessModifiers;
43 | NonAccessModifiers = l.NonAccessModifiers;
44 | Name = l.aName;
45 | ReturnType = l.ReturnType;
46 | SmaliReturnType = l.aReturnType;
47 | IsConstructor = l.IsConstructor;
48 | #endregion
49 | break;
50 | case SmaliLine.LineInstruction.Parameter:
51 | #region Parameter
52 | if (l.aName != "p0" && IsFirstParam)
53 | {
54 | IsFirstParam = false;
55 | Isp0self = true;
56 | Parameters.Add(new SmaliParameter()
57 | {
58 | Name = "this",
59 | Register = "p0",
60 | Type = ParentClass.ClassName
61 | });
62 | }
63 |
64 | l.aName = char.ToUpper(l.aName[0]) + l.aName.Substring(1);
65 | Parameters.Add(new SmaliParameter()
66 | {
67 | Name = "param" + l.aName,
68 | Register = l.lRegisters.Keys.First(),
69 | Type = l.aType
70 | });
71 | #endregion
72 | break;
73 | case SmaliLine.LineInstruction.Prologue:
74 | #region Prologue (method declaration)
75 | StringBuilder sb = new StringBuilder();
76 |
77 | if (Name == "")
78 | IsClinit = true;
79 |
80 | if (IsClinit)
81 | {
82 | Name = "";
83 | ReturnType = SmaliLine.LineReturnType.Custom;
84 | SmaliReturnType = "";
85 | }
86 | else if (Name == "")
87 | {
88 | Name = ParentClass.ClassName.Replace(";", "");
89 | SmaliReturnType = "";
90 | ReturnType = SmaliLine.LineReturnType.Custom;
91 | }
92 |
93 | sb.AppendFormat("{0} {1} {2} {3}",
94 | AccessModifiers == 0 ? "" : AccessModifiers.ToString().ToLowerInvariant().Replace(",", ""),
95 | NonAccessModifiers == 0 ? "" : NonAccessModifiers.ToString().ToLowerInvariant().Replace(",", ""),
96 | ReturnType == SmaliLine.LineReturnType.Custom ? SmaliUtils.General.Name2Java(SmaliReturnType) : ReturnType.ToString().ToLowerInvariant(),
97 | Name
98 | );
99 |
100 | if (!IsClinit)
101 | sb.Append(" (");
102 |
103 | if (Parameters.Count > 0)
104 | {
105 | for(int j = Isp0self ? 1 : 0; j < Parameters.Count; j++)
106 | sb.Append(Parameters[j].ToJava() + ", ");
107 | sb.Remove(sb.Length - 2, 2);
108 |
109 | if (Isp0self)
110 | vm.Put("p0", "this");
111 | }
112 |
113 | if(!IsClinit)
114 | sb.Append(") ");
115 |
116 | sb.Append("{");
117 |
118 | Buffer.Append(sb.ToString());
119 | #endregion
120 | break;
121 | case SmaliLine.LineInstruction.EndMethod:
122 | Java.Add("}");
123 | break;
124 | case SmaliLine.LineInstruction.Line:
125 | if (!String.IsNullOrEmpty(Buffer.ToString()))
126 | {
127 | JavaBuffer.Append(Buffer.ToString());
128 | if (!String.IsNullOrEmpty(JavaBuffer.ToString()))
129 | {
130 | Java.Add(JavaBuffer.ToString());
131 | Buffer = new StringBuilder();
132 | JavaBuffer = new StringBuilder();
133 | }
134 | }
135 | break;
136 | }
137 | #endregion
138 | }
139 | else
140 | {
141 | #region Smali instructions
142 | String sReg;
143 | String sSrcValue;
144 | String sDstValue;
145 | switch (l.Smali)
146 | {
147 | case SmaliLine.LineSmali.Const4:
148 | case SmaliLine.LineSmali.ConstString:
149 | vm.Put(l.lRegisters.Keys.First(), l.aValue);
150 | break;
151 |
152 | case SmaliLine.LineSmali.SputObject:
153 | sReg = l.lRegisters.Keys.First();
154 |
155 | if (!vm.vmStack.ContainsKey(sReg))
156 | {
157 | // SKIP!
158 | break;
159 | }
160 |
161 | sSrcValue = vm.Get(sReg);
162 | sDstValue = l.lRegisters[sReg];
163 |
164 | Dictionary args = new Dictionary();
165 | args[sReg] = sSrcValue;
166 |
167 | Buffer.Append(ParseSmali(sDstValue, args));
168 | break;
169 |
170 | case SmaliLine.LineSmali.InvokeStatic:
171 | //case SmaliLine.LineSmali.InvokeDirect:
172 |
173 | args = new Dictionary();
174 | foreach (KeyValuePair kv in l.lRegisters)
175 | {
176 | if (!vm.vmStack.ContainsKey(kv.Key))
177 | {
178 | // SKIP!
179 | break;
180 | }
181 | args[kv.Key] = vm.Get(kv.Key);
182 | }
183 |
184 | Buffer.Append(SmaliUtils.General.Name2Java(l.aClassName));
185 | Buffer.Append("." + l.aName + "(");
186 |
187 | if (args.Count > 0)
188 | {
189 | foreach (KeyValuePair kv in args)
190 | Buffer.Append(kv.Value + ", ");
191 | Buffer.Remove(Buffer.Length - 2, 2);
192 | }
193 |
194 | Buffer.Append(")");
195 |
196 | break;
197 |
198 | case SmaliLine.LineSmali.MoveResultObject:
199 |
200 | if (Buffer.Length > 0)
201 | {
202 | sReg = l.lRegisters.Keys.First();
203 | vm.Put(sReg, Buffer.ToString());
204 | Buffer = new StringBuilder();
205 | }
206 |
207 | break;
208 | case SmaliLine.LineSmali.ReturnVoid:
209 | Buffer.Append("return");
210 | break;
211 | }
212 | #endregion
213 | }
214 | }
215 | }
216 |
217 | public string ParseSmali(string smaliLine, Dictionary args)
218 | {
219 | if (smaliLine.Contains('('))
220 | {
221 | // It's a function
222 | }
223 | else
224 | {
225 | // It's an assignment
226 | String sClass = SmaliUtils.General.Eat(ref smaliLine, "->", true);
227 | String sName = SmaliUtils.General.Eat(ref smaliLine, ":", true);
228 | String sType = smaliLine;
229 |
230 | sClass = sClass.Replace(ParentClass.PackageName, "");
231 | sClass = sClass.Substring(1);
232 |
233 | if (sClass == ParentClass.ClassName)
234 | sClass = "";
235 | else
236 | sClass = SmaliUtils.General.Name2Java(sClass) + ".";
237 |
238 | return sClass + sName + " = " + args[args.Keys.First()] + ";";
239 | }
240 |
241 | return ":D";
242 | }
243 |
244 | public String ToJava()
245 | {
246 | StringBuilder sb = new StringBuilder();
247 | foreach (String s in Java)
248 | sb.AppendLine(s);
249 | return sb.ToString();
250 | }
251 | }
252 | }
253 |
--------------------------------------------------------------------------------
/smali2java/Smali/SmaliVM.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Smali2Java
7 | {
8 | public class SmaliVM
9 | {
10 | #region VM Stack (variable holder)
11 | public Dictionary vmStack = new Dictionary();
12 |
13 | public void PutLastCall(SmaliCall value)
14 | {
15 | vmStack["lastCall"] = value;
16 | }
17 |
18 | public SmaliCall GetLastCall()
19 | {
20 | object result = null;
21 | vmStack.TryGetValue("lastCall", out result);
22 | return result as SmaliCall;
23 | }
24 |
25 | public void PutLastRegisters(Dictionary value)
26 | {
27 | vmStack["lastRegisters"] = value;
28 | }
29 |
30 | public Dictionary GetLastRegisters()
31 | {
32 | object result = null;
33 | vmStack.TryGetValue("lastRegisters", out result);
34 | return result as Dictionary;
35 | }
36 |
37 | public void Put(String register, String value)
38 | {
39 | vmStack[register] = value;
40 | }
41 |
42 | public String Get(String register)
43 | {
44 | return vmStack[register].ToString();
45 | }
46 | #endregion
47 |
48 | public Directives smaliDirectives = new Directives();
49 | public Instructions smaliInstructions = new Instructions();
50 | public String Java;
51 | public StringBuilder Buf = new StringBuilder();
52 | public void FlushBuffer()
53 | {
54 | Java = Buf.ToString();
55 | Buf = new StringBuilder("");
56 | }
57 |
58 | public int _idxParam = 0;
59 |
60 | public void ProcessDirective(SmaliMethod m, SmaliLine l)
61 | {
62 | smaliDirectives.m = m;
63 | smaliDirectives.l = l;
64 | switch (l.Instruction)
65 | {
66 | case SmaliLine.LineInstruction.Method:
67 | smaliDirectives.Method();
68 | if (!m.bHasParameters)
69 | {
70 | smaliDirectives.Special_NoParameters();
71 | if (!m.bHasPrologue)
72 | smaliDirectives.Prologue();
73 | }
74 | break;
75 | case SmaliLine.LineInstruction.Parameter:
76 | smaliDirectives.Parameter();
77 | break;
78 | case SmaliLine.LineInstruction.Prologue:
79 | smaliDirectives.Prologue();
80 | break;
81 | case SmaliLine.LineInstruction.Line:
82 | smaliDirectives.Line();
83 | break;
84 | case SmaliLine.LineInstruction.EndMethod:
85 | smaliDirectives.EndMethod();
86 | break;
87 | }
88 | }
89 |
90 | public void ProcessInstruction(SmaliMethod m, SmaliLine l)
91 | {
92 | smaliInstructions.m = m;
93 | smaliInstructions.l = l;
94 | switch (l.Smali)
95 | {
96 | case SmaliLine.LineSmali.Const4:
97 | case SmaliLine.LineSmali.Const:
98 | case SmaliLine.LineSmali.Const16:
99 | case SmaliLine.LineSmali.ConstHigh16: //TODO: these may end up needing seperate instruction handlers.
100 | case SmaliLine.LineSmali.ConstString:
101 | smaliInstructions.Const();
102 | break;
103 | case SmaliLine.LineSmali.SputObject:
104 | smaliInstructions.SputObject();
105 | break;
106 | case SmaliLine.LineSmali.Return:
107 | case SmaliLine.LineSmali.ReturnVoid:
108 | smaliInstructions.Return();
109 | break;
110 | case SmaliLine.LineSmali.SgetObject:
111 | smaliInstructions.SgetObject();
112 | break;
113 | case SmaliLine.LineSmali.NewInstance:
114 | smaliInstructions.NewInstance();
115 | break;
116 | case SmaliLine.LineSmali.InvokeVirtual:
117 | case SmaliLine.LineSmali.InvokeStatic:
118 | case SmaliLine.LineSmali.InvokeDirect: //TODO: These may need to be on their own functions, but for now the are all identical in implementation...
119 | smaliInstructions.Invoke();
120 | break;
121 | case SmaliLine.LineSmali.IputBoolean:
122 | smaliInstructions.IputBoolean();
123 | break;
124 | case SmaliLine.LineSmali.MoveResult:
125 | case SmaliLine.LineSmali.MoveResultObject:
126 | smaliInstructions.MoveResult();
127 | break;
128 | case SmaliLine.LineSmali.Unimplemented: //These will cover most of the instructions right now...
129 | case SmaliLine.LineSmali.Unknown:
130 | case SmaliLine.LineSmali.Conditional:
131 | case SmaliLine.LineSmali.Label:
132 | smaliInstructions.Unimplemented();
133 | break;
134 | }
135 | }
136 |
137 | public class Directives
138 | {
139 | public SmaliMethod m;
140 | public SmaliLine l;
141 |
142 | public void Method()
143 | {
144 | m.AccessModifiers = l.AccessModifiers;
145 | m.NonAccessModifiers = l.NonAccessModifiers;
146 | m.MethodCall = SmaliCall.Parse(l.aExtra);
147 | SmaliEngine.VM._idxParam = 0;
148 | }
149 |
150 | public void Special_NoParameters()
151 | {
152 | m.bIsFirstParam = false;
153 | m.MethodFlags |= SmaliMethod.EMethodFlags.p0IsSelf;
154 | m.MethodCall.Parameters.Insert(0, new SmaliParameter()
155 | {
156 | Name = "this",
157 | Register = "p0",
158 | Type = m.ParentClass.ClassName
159 | });
160 | SmaliEngine.VM._idxParam = 1;
161 | for (; SmaliEngine.VM._idxParam < m.MethodCall.Parameters.Count; SmaliEngine.VM._idxParam++)
162 | {
163 | m.MethodCall.Parameters[SmaliEngine.VM._idxParam].Name =
164 | m.MethodCall.Parameters[SmaliEngine.VM._idxParam].Register = "p" + SmaliEngine.VM._idxParam;
165 | SmaliEngine.VM.Put(m.MethodCall.Parameters[SmaliEngine.VM._idxParam].Register, m.MethodCall.Parameters[SmaliEngine.VM._idxParam].Name);
166 | }
167 | }
168 |
169 | public void Parameter()
170 | {
171 | if (l.lRegisters.Keys.First() != "p0" && m.bIsFirstParam)
172 | {
173 | m.bIsFirstParam = false;
174 | m.MethodFlags |= SmaliMethod.EMethodFlags.p0IsSelf;
175 | m.MethodCall.Parameters.Insert(0, new SmaliParameter()
176 | {
177 | Name = "this",
178 | Register = "p0",
179 | Type = m.ParentClass.ClassName
180 | });
181 | SmaliEngine.VM._idxParam = 1;
182 | }
183 |
184 | l.aName = char.ToUpper(l.aName[0]) + l.aName.Substring(1);
185 |
186 | // TODO: Check if this algorithm is right?
187 | m.MethodCall.Parameters[SmaliEngine.VM._idxParam].Name = "param" + l.aName;
188 | m.MethodCall.Parameters[SmaliEngine.VM._idxParam].Register = l.lRegisters.Keys.First();
189 | SmaliEngine.VM.Put(m.MethodCall.Parameters[SmaliEngine.VM._idxParam].Register, m.MethodCall.Parameters[SmaliEngine.VM._idxParam].Name);
190 | SmaliEngine.VM._idxParam++;
191 | }
192 |
193 | public void Prologue()
194 | {
195 | // TODO: Create extension method HasFlag because .NET 3.5 doesn't have it?
196 | if((m.MethodCall.CallFlags & SmaliCall.ECallFlags.Constructor) == SmaliCall.ECallFlags.Constructor)
197 | m.MethodCall.Method = m.ParentClass.ClassName.Replace(";", "");
198 |
199 | SmaliEngine.VM.Buf.AppendFormat("{0} {1}{2}",
200 | SmaliUtils.General.Modifiers2Java(m.AccessModifiers, m.NonAccessModifiers),
201 | SmaliUtils.General.ReturnType2Java(m.MethodCall.SmaliReturnType, m.MethodCall.Return),
202 | m.MethodCall.Method
203 | );
204 |
205 | if (((m.MethodCall.CallFlags & SmaliCall.ECallFlags.ClassInit) == SmaliCall.ECallFlags.ClassInit) == false)
206 | SmaliEngine.VM.Buf.Append(" (");
207 |
208 | if (m.MethodCall.Parameters.Count > 0)
209 | {
210 | // Let's save a couple of cycles and only calculate this once in this if block.
211 | bool p0isSelf = (m.MethodFlags & SmaliMethod.EMethodFlags.p0IsSelf) == SmaliMethod.EMethodFlags.p0IsSelf;
212 |
213 | for (int j = p0isSelf ? 1 : 0; j < m.MethodCall.Parameters.Count; j++)
214 | SmaliEngine.VM.Buf.Append(m.MethodCall.Parameters[j].ToJava() + ", ");
215 |
216 | // Only remove things from the buffer if we printed any args to remove.
217 | if (m.MethodCall.Parameters.Count > (p0isSelf ? 1 : 0) )
218 | SmaliEngine.VM.Buf.Remove(SmaliEngine.VM.Buf.Length - 2, 2);
219 |
220 | if (p0isSelf)
221 | SmaliEngine.VM.Put("p0", "this");
222 | }
223 |
224 | if (((m.MethodCall.CallFlags & SmaliCall.ECallFlags.ClassInit) == SmaliCall.ECallFlags.ClassInit) == false)
225 | SmaliEngine.VM.Buf.Append(") ");
226 |
227 | SmaliEngine.VM.Buf.Append("{");
228 | SmaliEngine.VM.FlushBuffer();
229 | }
230 |
231 | public void Line()
232 | {
233 | SmaliEngine.VM.FlushBuffer();
234 | }
235 |
236 | public void EndMethod()
237 | {
238 | SmaliEngine.VM.Buf.Append("}");
239 | SmaliEngine.VM.FlushBuffer();
240 | }
241 | }
242 | public class Instructions
243 | {
244 | public SmaliMethod m;
245 | public SmaliLine l;
246 |
247 | public void Const()
248 | {
249 | if (Program.Debug)
250 | {
251 | SmaliEngine.VM.Buf.AppendFormat("\\\\{0} = {1};\n\n",
252 | l.lRegisters.Keys.First(),
253 | l.aValue
254 | );
255 | }
256 | SmaliEngine.VM.Put(l.lRegisters.Keys.First(), l.aValue);
257 | //TODO: Figure out when these should be variable assignments, and when they should be constants...
258 | //Perhaps we can start from the return value, and work our way back from there, as well as looking at which methods are getting called by these.
259 | }
260 |
261 | public void SputObject()
262 | {
263 | String sReg = l.lRegisters.Keys.First();
264 |
265 | // SKIP! TODO: Should not skip, actually. If it skips, something IS wrong
266 | if (!SmaliEngine.VM.vmStack.ContainsKey(sReg))
267 | {
268 | Unimplemented();
269 | return;
270 | }
271 |
272 | String sSrcValue = SmaliEngine.VM.Get(sReg);
273 | String sDstValue = l.lRegisters[sReg];
274 |
275 | Dictionary args = new Dictionary();
276 | args[sReg] = sSrcValue;
277 |
278 | SmaliCall c = SmaliCall.Parse(sDstValue);
279 |
280 | SmaliEngine.VM.Buf = new StringBuilder();
281 |
282 | SmaliEngine.VM.Buf.AppendFormat("{0}{1}{2} = {3};\n",
283 | c.Variable,
284 | m.ParentClass.PackageName == c.ClassName ? "" : (c.ClassName + "."),
285 | m.ParentClass.ClassName == c.Method ? "" : (c.Method + "."),
286 | sSrcValue
287 | );
288 | }
289 |
290 | public void SgetObject()
291 | {
292 | String sReg = l.lRegisters.Keys.First();
293 | String sSrcValue = l.lRegisters[sReg];
294 | String sDstValue = sReg;
295 | SmaliCall c = SmaliCall.Parse(sSrcValue);
296 | string prepend = String.Empty;
297 | if (m.ParentClass.PackageName == c.ClassName && m.ParentClass.ClassName == c.Method)
298 | prepend = "this.";
299 | else // I don't think sget-object should ever hit this?
300 | prepend = SmaliUtils.General.Name2Java(c.ClassName) + '.' + c.Method + '.';
301 | SmaliEngine.VM.Put(sDstValue, prepend + c.Variable);
302 | }
303 |
304 | public void IputBoolean()
305 | {
306 | String sReg = l.lRegisters.Keys.First();
307 |
308 | // SKIP! TODO: Should not skip, actually. If it skips, something IS wrong
309 | if (!SmaliEngine.VM.vmStack.ContainsKey(sReg))
310 | {
311 | Unimplemented();
312 | return;
313 | }
314 |
315 | String sSrcValue = SmaliEngine.VM.Get(sReg);
316 | String sDstValue = l.aName;
317 |
318 | Dictionary args = new Dictionary();
319 | args[sReg] = sSrcValue;
320 |
321 | SmaliCall c = SmaliCall.Parse(sDstValue);
322 |
323 | SmaliEngine.VM.Buf = new StringBuilder();
324 |
325 | SmaliEngine.VM.Buf.AppendFormat("{0}{1} = {2};\n",
326 | (m.ParentClass.PackageName == c.ClassName && m.ParentClass.ClassName == c.Method ?
327 | "this." :
328 | (SmaliUtils.General.Name2Java(c.ClassName) + "." + c.Method + ".")),
329 | c.Variable,
330 | (sSrcValue == "0x1" ? "true" : "false")
331 | );
332 |
333 | //TODO: Well... todo. Lol.
334 | //Buffer.Append(ParseSmali(sDstValue, args));
335 | }
336 |
337 | public void Return()
338 | {
339 | String sSrcValue = String.Empty;
340 | if (l.lRegisters.Count > 0)
341 | {
342 | String sReg = l.lRegisters.Keys.First();
343 |
344 | // SKIP! TODO: Should not skip, actually. If it skips, something IS wrong
345 | if (!SmaliEngine.VM.vmStack.ContainsKey(sReg))
346 | {
347 | Unimplemented();
348 | return;
349 | }
350 |
351 | sSrcValue = ' ' + SmaliEngine.VM.Get(sReg);
352 | }
353 | // We don't wipe the buffer here... there may not have been a .line before return...
354 | SmaliEngine.VM.Buf.AppendFormat("return{0};\n",
355 | sSrcValue
356 | );
357 | }
358 |
359 | public void NewInstance()
360 | {
361 | SmaliCall c = SmaliCall.Parse(l.lRegisters[l.lRegisters.Keys.First()]);
362 | StringBuilder sb = new StringBuilder();
363 | sb.Append("new " + SmaliUtils.General.Name2Java(c.ClassName));
364 | sb.Append("." + c.Method + "()");
365 | SmaliEngine.VM.Put(l.lRegisters.Keys.First(), sb.ToString());
366 | }
367 |
368 | public void Invoke() //TODO: Move this out into more generic functions?
369 | {
370 | String sReg = l.lRegisters.Keys.First();
371 | // SKIP! TODO: Should not skip, actually. If it skips, something IS wrong
372 | if (!SmaliEngine.VM.vmStack.ContainsKey(sReg))
373 | {
374 | Unimplemented();
375 | return;
376 | }
377 |
378 | SmaliCall c = SmaliCall.Parse(l.lRegisters[l.lRegisters.Keys.First()]);
379 |
380 | // It's a constructor, skip method name
381 | if ((c.CallFlags & SmaliCall.ECallFlags.Constructor) == SmaliCall.ECallFlags.Constructor)
382 | SmaliEngine.VM.Buf.Append(SmaliEngine.VM.Get(sReg));
383 | else
384 | {
385 | string regs = null;
386 | try
387 | {
388 | regs = ParseRegistersAsArgs(l.lRegisters);
389 | }
390 | catch
391 | {
392 | Unimplemented();
393 | return;
394 | }
395 | SmaliEngine.VM.Buf.AppendFormat("{0}({1});\n",
396 | (m.ParentClass.PackageName == c.ClassName && m.ParentClass.ClassName == c.Method ?
397 | "this." :
398 | (SmaliUtils.General.Name2Java(c.ClassName) + "." + c.Method)),
399 | regs
400 | ); //We add this to the buffer one way or another, it just gets cleared if the next instruction is MoveResult.
401 | //TODO: Maybe we should simply prepend the buffer with the variable for move result?
402 | // We are actually returning something here, put this as the value of the last instruction to be acted on by move-result.
403 | if (c.SmaliReturnType != SmaliLine.LineReturnType.Void)
404 | {
405 | SmaliEngine.VM.PutLastCall(c);
406 | SmaliEngine.VM.PutLastRegisters(l.lRegisters);
407 | }
408 | }
409 | }
410 |
411 |
412 | /*
413 | * TODO: Figure out when these should be variable assignments, and when they should be constants...
414 | * Right now we spam variables like there is no tomorrow. Can we really rely on "end locals"?
415 | * Maybe we can count the usages, if it is never again assigned to, or it changes type we don't make a variable, and instead nest the calls...
416 | */
417 | public void MoveResult() //We *MIGHT* need to make a second one for objects...
418 | {
419 | SmaliEngine.VM.Buf = new StringBuilder(); // Clear the buffer We'll plug the instruction we are getting the result into in the buffer in case this never gets called, so now we need to clear it.
420 | String sReg = l.lRegisters.Keys.First();
421 | SmaliCall cOld = SmaliEngine.VM.GetLastCall();
422 | Dictionary registers = SmaliEngine.VM.GetLastRegisters();
423 | if (cOld != null && registers != null) //SKIP, again something is wrong if we skip here.
424 | {
425 | SmaliEngine.VM.Put(sReg, cOld.SmaliReturnType.ToString() + m.IncrementTypeCount(cOld.SmaliReturnType)); //TODO: generate variable names programatically here.
426 | SmaliEngine.VM.PutLastCall(null); // Wipe so we don't accidentally get something we missed again.
427 | SmaliEngine.VM.PutLastRegisters(null);
428 | string regs = null;
429 | try
430 | {
431 | regs = ParseRegistersAsArgs(registers);
432 | }
433 | catch
434 | {
435 | Unimplemented();
436 | return;
437 | }
438 | SmaliEngine.VM.Buf.AppendFormat("{0} = {1}({2});\n",
439 | SmaliUtils.General.Name2Java(SmaliUtils.General.ReturnType2Java(cOld.SmaliReturnType, cOld.Return)).Replace(";", String.Empty) + SmaliEngine.VM.Get(sReg),
440 | (m.ParentClass.PackageName == cOld.ClassName && m.ParentClass.ClassName == cOld.Method ?
441 | "this." :
442 | (SmaliUtils.General.Name2Java(cOld.ClassName) + "." + cOld.Method)),
443 | regs
444 | );
445 | SmaliEngine.VM.FlushBuffer();
446 | }
447 | }
448 |
449 | public void Unimplemented()
450 | {
451 | if (Program.Debug)
452 | SmaliEngine.VM.Buf.AppendFormat("\\*\n* Warning, {0} instruction was not processed: \n* {1}\n*\\\n",
453 | l.Smali,
454 | l.aName
455 | );
456 | else // Log Verbose comments only if the debug flag is enabled.
457 | SmaliEngine.VM.Buf.AppendFormat("\\\\{0}\n",
458 | l.aName
459 | );
460 | SmaliEngine.VM.FlushBuffer();
461 | }
462 |
463 | private String ParseRegistersAsArgs(Dictionary registers) //TODO: This should be elsewhere.
464 | {
465 | string regs = String.Empty;
466 | bool hadOne = false;
467 | foreach (string s in registers.Keys)
468 | {
469 | string reg = SmaliEngine.VM.Get(s);
470 | if (reg != "this" || hadOne)
471 | {
472 | regs += (reg != "this" ? SmaliEngine.VM.Get(s) + ", " : String.Empty);
473 | if (!hadOne)
474 | hadOne = true;
475 | }
476 | }
477 | if (hadOne)
478 | regs = regs.Substring(0, regs.Length - 2);
479 | return regs;
480 | }
481 | }
482 | }
483 | }
484 |
--------------------------------------------------------------------------------
/smali2java/Smali/SmaliLine.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Smali2Java
7 | {
8 | public class SmaliLine
9 | {
10 | #region Definitions
11 |
12 | [Flags]
13 | public enum EAccessMod
14 | {
15 | Private = 1,
16 | Public = 2,
17 | Protected = 4
18 | }
19 |
20 | [Flags]
21 | public enum ENonAccessMod
22 | {
23 | Static = 1,
24 | Final = 2,
25 | Abstract = 4,
26 | Synchronized = 8,
27 | Volatile = 16,
28 | }
29 |
30 | public static String[] Keywords = new String[]
31 | {
32 | "public",
33 | "private",
34 | "protected",
35 | "static",
36 | "final",
37 | "abstract",
38 | "synchronized",
39 | "volatile",
40 | "constructor"
41 | };
42 |
43 | public enum LineInstruction
44 | {
45 | Unknown = -1,
46 | Class = 1,
47 | Super,
48 | Implements,
49 | Source,
50 | Field,
51 | Method,
52 | Registers,
53 | Prologue,
54 | Line,
55 | EndMethod,
56 | Catch,
57 | Parameter
58 | }
59 |
60 | public enum LineBlock
61 | {
62 | None = 1,
63 | TryStart,
64 | TryCatch,
65 | TryEnd,
66 | IfStart,
67 | IfEnd
68 | }
69 |
70 | public enum LineSmali
71 | {
72 | Unknown = -1,
73 | Const4 = 1,
74 | Const,
75 | Const16,
76 | ConstHigh16,
77 | ConstString,
78 | SputObject,
79 | SgetObject,
80 | IputObject,
81 | IputBoolean,
82 | InvokeStatic,
83 | InvokeDirect,
84 | InvokeVirtual,
85 | MoveResultObject,
86 | MoveResult,
87 | NewInstance,
88 | ReturnVoid,
89 | Return,
90 | Unimplemented,
91 | Conditional,
92 | Label
93 | }
94 |
95 | public enum LineReturnType
96 | {
97 | Custom = 1,
98 | Void,
99 | Int,
100 | Boolean,
101 | Byte,
102 | Short,
103 | Char,
104 | Long,
105 | Double,
106 | CustomArray,
107 | VoidArray,
108 | IntArray,
109 | BooleanArray,
110 | ByteArray,
111 | ShortArray,
112 | CharArray,
113 | LongArray,
114 | DoubleArray
115 | }
116 | #endregion
117 |
118 | // Flags & identifiers
119 | public LineInstruction Instruction;
120 | public LineBlock Block;
121 | public LineSmali Smali;
122 | public EAccessMod AccessModifiers;
123 | public ENonAccessMod NonAccessModifiers;
124 | public LineReturnType ReturnType;
125 |
126 | // Simple flags
127 | public bool bIsDirective = false;
128 | public bool IsConstructor = false;
129 | public bool IsDestructor = false;
130 |
131 | // Attributes
132 | public String aType;
133 | public String aExtra;
134 | public String aName;
135 | public String aClassName;
136 | public String aReturnType;
137 | public String aValue;
138 | public Dictionary lRegisters = new Dictionary();
139 |
140 | public static SmaliLine Parse(String l)
141 | {
142 | SmaliLine rv = new SmaliLine();
143 |
144 | l = l.Trim();
145 | if (l.Length == 0)
146 | return null;
147 |
148 | if (l[0] == '#')
149 | return null;
150 |
151 | String sIdentifiers = l;
152 | String sRawText = String.Empty;
153 | bool bHasString = l.Contains('"');
154 |
155 | if (bHasString)
156 | sIdentifiers = SmaliUtils.General.Eat(ref l, '"', false);
157 | sRawText = l;
158 |
159 | String[] sWords = sIdentifiers.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
160 |
161 | if (sWords.Length == 0)
162 | return null;
163 |
164 | String sInst = sWords[0].ToLowerInvariant().Trim();
165 | sWords[0] = String.Empty;
166 |
167 | if (sInst[0] == '.')
168 | if (!ParseAsDirective(rv, sInst, ref sWords, ref sRawText))
169 | return null;
170 | else
171 | rv.bIsDirective = true;
172 |
173 | else if (sRawText[0] == ':') //We'll go with the idea that a label is still an instruction, but there is no need to waste cycles in the instruction parsing loop.
174 | {
175 | rv.Smali = LineSmali.Label; //TODO: add ParseAsLabel
176 | rv.aName = sRawText;
177 | }
178 |
179 | else if (sInst[0] != '.')
180 | if (!ParseAsInstruction(rv, sInst, ref sWords, ref sRawText))
181 | return null;
182 |
183 | return rv;
184 | }
185 |
186 | #region Directive Parsing
187 |
188 | public static bool ParseAsDirective(SmaliLine rv, String sInst, ref String[] sWords, ref String sRawText)
189 | {
190 | switch (sInst)
191 | {
192 | case ".class":
193 | rv.Instruction = LineInstruction.Class;
194 | SetModifiers(rv, ref sWords, 1, sWords.Length - 1);
195 | rv.aClassName = sWords[sWords.Length - 1];
196 | break;
197 | case ".super":
198 | rv.Instruction = LineInstruction.Super;
199 | rv.aType = sWords[1];
200 | break;
201 | case ".implements":
202 | rv.Instruction = LineInstruction.Implements;
203 | rv.aType = sWords[1];
204 | break;
205 | case ".source":
206 | rv.Instruction = LineInstruction.Source;
207 | rv.aExtra = sRawText;
208 | break;
209 | case ".field":
210 | rv.Instruction = LineInstruction.Field;
211 | SetModifiers(rv, ref sWords, 1, sWords.Length - 1);
212 | sRawText = String.Join(" ", sWords.Where(x => !String.IsNullOrEmpty(x)).ToArray()).Trim();
213 | rv.aName = sRawText.Split(':')[0];
214 | rv.aType = sRawText.Split(':')[1];
215 | break;
216 | case ".method":
217 | rv.Instruction = LineInstruction.Method;
218 | SetModifiers(rv, ref sWords, 1, sWords.Length - 1);
219 | sRawText = String.Join(" ", sWords.Where(x => !String.IsNullOrEmpty(x)).ToArray()).Trim();
220 | rv.aExtra = sRawText;
221 | break;
222 | case ".prologue":
223 | rv.Instruction = LineInstruction.Prologue;
224 | break;
225 | case ".registers":
226 | rv.Instruction = LineInstruction.Registers;
227 | break;
228 | case ".line":
229 | rv.Instruction = LineInstruction.Line;
230 | break;
231 | case ".end":
232 | switch (sRawText)
233 | {
234 | case ".end method":
235 | rv.Instruction = LineInstruction.EndMethod;
236 | break;
237 | }
238 | break;
239 | case ".param":
240 | rv.Instruction = LineInstruction.Parameter;
241 | sWords[1] = sWords[1].Replace(",", "");
242 | rv.lRegisters[sWords[1].Trim()] = String.Empty;
243 | rv.aName = sRawText.Substring(sRawText.IndexOf('"') + 1);
244 | rv.aName = rv.aName.Substring(0, rv.aName.IndexOf('"'));
245 | rv.aType = sRawText.Substring(sRawText.IndexOf('#') + 1).Trim();
246 | break;
247 | default:
248 | return false;
249 | }
250 | return true;
251 | }
252 |
253 | public static void SetModifiers(SmaliLine l, ref String[] ar, int start, int end)
254 | {
255 | for (int i = start; i < end; i++)
256 | if (Keywords.Contains(ar[i].ToLowerInvariant().Trim()))
257 | {
258 | if (!ParseNonAccess(l, ar[i].ToLowerInvariant().Trim()))
259 | if (!ParseAccess(l, ar[i].ToLowerInvariant().Trim()))
260 | ParseModifier(l, ar[i].ToLowerInvariant().Trim());
261 | ar[i] = String.Empty;
262 | }
263 | }
264 | public static bool ParseNonAccess(SmaliLine l, String s)
265 | {
266 | switch (s)
267 | {
268 | case "static":
269 | l.NonAccessModifiers |= ENonAccessMod.Static;
270 | break;
271 | case "final":
272 | l.NonAccessModifiers |= ENonAccessMod.Final;
273 | break;
274 | case "abstract":
275 | l.NonAccessModifiers |= ENonAccessMod.Abstract;
276 | break;
277 | case "synchronized":
278 | l.NonAccessModifiers |= ENonAccessMod.Synchronized;
279 | break;
280 | case "volatile":
281 | l.NonAccessModifiers |= ENonAccessMod.Volatile;
282 | break;
283 | default:
284 | return false;
285 | }
286 | return true;
287 | }
288 | public static bool ParseAccess(SmaliLine l, String s)
289 | {
290 | switch (s)
291 | {
292 | case "public":
293 | l.AccessModifiers |= EAccessMod.Public;
294 | break;
295 | case "private":
296 | l.AccessModifiers |= EAccessMod.Private;
297 | break;
298 | case "protected":
299 | l.AccessModifiers |= EAccessMod.Protected;
300 | break;
301 | default:
302 | return false;
303 | }
304 | return true;
305 | }
306 | public static bool ParseModifier(SmaliLine l, String s)
307 | {
308 | switch (s)
309 | {
310 | case "constructor":
311 | l.IsConstructor = true;
312 | break;
313 | default:
314 | return false;
315 | }
316 | return true;
317 | }
318 | #endregion
319 | #region Instruction Parsing
320 |
321 | public static bool ParseAsInstruction(SmaliLine rv, String sInst, ref String[] sWords, ref String sRawText)
322 | {
323 | switch (sInst)
324 | {
325 | case "const":
326 | rv.Smali = LineSmali.Const;
327 | sWords[1] = sWords[1].Replace(",", "");
328 | rv.lRegisters[sWords[1]] = String.Empty;
329 | rv.aValue = sWords[2];
330 | break;
331 | case "const/16":
332 | rv.Smali = LineSmali.Const16;
333 | sWords[1] = sWords[1].Replace(",", "");
334 | rv.lRegisters[sWords[1]] = String.Empty;
335 | rv.aValue = sWords[2];
336 | break;
337 | case "const/high16":
338 | rv.Smali = LineSmali.ConstHigh16;
339 | sWords[1] = sWords[1].Replace(",", "");
340 | rv.lRegisters[sWords[1]] = String.Empty;
341 | rv.aValue = sWords[2];
342 | break;
343 | case "const/4":
344 | rv.Smali = LineSmali.Const4;
345 | sWords[1] = sWords[1].Replace(",", "");
346 | rv.lRegisters[sWords[1]] = String.Empty;
347 | rv.aValue = sWords[2];
348 | break;
349 | case "const-string":
350 | rv.Smali = LineSmali.ConstString;
351 | sWords[1] = sWords[1].Replace(",", "");
352 | rv.lRegisters[sWords[1]] = String.Empty;
353 | rv.aValue = sRawText;
354 | break;
355 | case "invoke-static":
356 | rv.Smali = LineSmali.InvokeStatic;
357 | rv.aName = sWords[sWords.Length - 1];
358 | sWords[sWords.Length - 1] = String.Empty;
359 | String sp = String.Join(" ", sWords.Where(x => !String.IsNullOrEmpty(x)).ToArray()).Trim();
360 | if (sp.EndsWith(","))
361 | sp = sp.Substring(0, sp.Length - 1);
362 | ParseParameters(rv, sp);
363 | rv.lRegisters[rv.lRegisters.Keys.First()] = rv.aName;
364 | break;
365 | case "invoke-direct":
366 | rv.Smali = LineSmali.InvokeDirect;
367 | if (sWords[1].EndsWith(","))
368 | sWords[1] = sWords[1].Substring(0, sWords[1].Length - 1);
369 | ParseParameters(rv, sWords[1]);
370 | rv.lRegisters[rv.lRegisters.Keys.First()] = sWords[2];
371 | rv.aName = sWords[sWords.Length - 1];
372 | break;
373 | case "move-result-object":
374 | rv.Smali = LineSmali.MoveResultObject;
375 | rv.lRegisters[sWords[1]] = String.Empty;
376 | break;
377 | case "move-result":
378 | rv.Smali = LineSmali.MoveResult;
379 | rv.lRegisters[sWords[1]] = String.Empty;
380 | break;
381 | case "return":
382 | case "return-object":
383 | rv.Smali = LineSmali.Return;
384 | if (sWords[1].EndsWith(","))
385 | sWords[1] = sWords[1].Substring(0, sWords[1].Length - 1);
386 | ParseParameters(rv, sWords[1]);
387 | rv.lRegisters[rv.lRegisters.Keys.First()] = sWords[1];
388 | break;
389 | case "return-void":
390 | rv.Smali = LineSmali.ReturnVoid;
391 | break;
392 | case "sget-object":
393 | rv.Smali = LineSmali.SgetObject;
394 | if (sWords[1].EndsWith(","))
395 | sWords[1] = sWords[1].Substring(0, sWords[1].Length - 1);
396 | ParseParameters(rv, sWords[1]);
397 | rv.lRegisters[rv.lRegisters.Keys.First()] = sWords[2];
398 | break;
399 | case "sput-object":
400 | rv.Smali = LineSmali.SputObject;
401 | if (sWords[1].EndsWith(","))
402 | sWords[1] = sWords[1].Substring(0, sWords[1].Length - 1);
403 | ParseParameters(rv, sWords[1]);
404 | rv.lRegisters[rv.lRegisters.Keys.First()] = sWords[2];
405 | break;
406 | case "new-instance":
407 | rv.Smali = LineSmali.NewInstance;
408 | if (sWords[1].EndsWith(","))
409 | sWords[1] = sWords[1].Substring(0, sWords[1].Length - 1);
410 | ParseParameters(rv, sWords[1]);
411 | rv.lRegisters[rv.lRegisters.Keys.First()] = sWords[2];
412 | break;
413 | case "iput-object":
414 | rv.Smali = LineSmali.IputObject;
415 | rv.aValue = sWords[sWords.Length - 1];
416 | sWords[sWords.Length - 1] = String.Empty;
417 | sp = String.Join(" ", sWords.Where(x => !String.IsNullOrEmpty(x)).ToArray()).Trim();
418 | if (sp.EndsWith(","))
419 | sp = sp.Substring(0, sp.Length - 1);
420 | ParseParameters(rv, sp);
421 | break;
422 | case "iput-boolean":
423 | rv.Smali = LineSmali.IputBoolean;
424 | if (sWords[1].EndsWith(","))
425 | sWords[1] = sWords[1].Substring(0, sWords[1].Length - 1);
426 | ParseParameters(rv, sWords[1]);
427 | rv.lRegisters[rv.lRegisters.Keys.First()] = sWords[2];
428 | rv.aName = sWords[ sWords.Length - 1]; //Always the last entry.
429 | break;
430 | case "invoke-virtual":
431 | rv.Smali = LineSmali.InvokeVirtual;
432 | rv.aName = sWords[sWords.Length - 1];
433 | sWords[sWords.Length - 1] = String.Empty;
434 | sp = String.Join(" ", sWords.Where(x => !String.IsNullOrEmpty(x)).ToArray()).Trim();
435 | if (sp.EndsWith(","))
436 | sp = sp.Substring(0, sp.Length - 1);
437 | ParseParameters(rv, sp);
438 | rv.lRegisters[rv.lRegisters.Keys.First()] = rv.aName;
439 | break;
440 |
441 | #region Unimplemented Functions
442 |
443 | case "add-double":
444 | case "add-double/2addr":
445 | case "add-float":
446 | case "add-float/2addr":
447 | case "add-int":
448 | case "add-int/2addr":
449 | case "add-int/lit16":
450 | case "add-int/lit8":
451 | case "add-long":
452 | case "add-long/2addr":
453 | case "aget":
454 | case "aget-boolean":
455 | case "aget-byte":
456 | case "aget-char":
457 | case "aget-object":
458 | case "aget-short":
459 | case "aget-wide":
460 | case "and-int":
461 | case "and-int/2addr":
462 | case "and-int/lit16":
463 | case "and-int/lit8":
464 | case "and-long":
465 | case "and-long/2addr":
466 | case "aput":
467 | case "aput-boolean":
468 | case "aput-byte":
469 | case "aput-char":
470 | case "aput-object":
471 | case "aput-short":
472 | case "aput-wide":
473 | case "array-length":
474 | case "check-cast":
475 | case "cmpg-double":
476 | case "cmpg-float":
477 | case "cmpl-double":
478 | case "cmpl-float":
479 | case "cmp-long":
480 | case "const-class":
481 | case "const-string/jumbo":
482 | case "const-wide":
483 | case "const-wide/16":
484 | case "const-wide/32":
485 | case "const-wide/high16":
486 | case "div-double":
487 | case "div-float":
488 | case "div-float/2addr":
489 | case "div-int":
490 | case "div-int/2addr":
491 | case "div-int/lit16":
492 | case "div-int/lit8":
493 | case "div-long":
494 | case "div-long/2addr":
495 | case "double-to-int":
496 | case "double-to-long":
497 | case "execute-inline":
498 | case "execute-inline/range":
499 | case "fill-array-data":
500 | case "filled-new-array":
501 | case "filled-new-array/range":
502 | case "float-to-double":
503 | case "float-to-int":
504 | case "float-to-long":
505 | case "iget":
506 | case "iget-boolean":
507 | case "iget-byte":
508 | case "iget-char":
509 | case "iget-object":
510 | case "iget-object-quick":
511 | case "iget-object-volatile":
512 | case "iget-quick":
513 | case "iget-short":
514 | case "iget-volatile":
515 | case "iget-wide":
516 | case "iget-wide-quick":
517 | case "iget-wide-volatile":
518 | case "instance-of":
519 | case "int-to-double":
520 | case "int-to-float":
521 | case "int-to-long":
522 | case "invoke-direct/range":
523 | case "invoke-direct-empty":
524 | case "invoke-interface":
525 | case "invoke-interface/range":
526 | case "invoke-object-init/range":
527 | case "invoke-static/range":
528 | case "invoke-super":
529 | case "invoke-super/range":
530 | case "invoke-super-quick":
531 | case "invoke-super-quick/range":
532 | case "invoke-virtual/range":
533 | case "invoke-virtual-quick":
534 | case "invoke-virtual-quick/range":
535 | case "iput":
536 | case "iput-byte":
537 | case "iput-char":
538 | case "iput-object-quick":
539 | case "iput-object-volatile":
540 | case "iput-quick":
541 | case "iput-short":
542 | case "iput-volatile":
543 | case "iput-wide":
544 | case "iput-wide-quick":
545 | case "iput-wide-volatile":
546 | case "long-to-double":
547 | case "long-to-float":
548 | case "long-to-int":
549 | case "move":
550 | case "move/16":
551 | case "move/from16":
552 | case "move-exception":
553 | case "move-object":
554 | case "move-object/16":
555 | case "move-object/from16":
556 | case "move-result-wide":
557 | case "move-wide":
558 | case "move-wide/16":
559 | case "move-wide/from16":
560 | case "mul-double":
561 | case "mul-float":
562 | case "mul-float/2addr":
563 | case "mul-int":
564 | case "mul-int/2addr":
565 | case "mul-int/lit16":
566 | case "mul-int/lit8":
567 | case "mul-long":
568 | case "mul-long/2addr":
569 | case "neg-double":
570 | case "neg-float":
571 | case "neg-int":
572 | case "neg-long":
573 | case "new-array":
574 | case "nop":
575 | case "not-int":
576 | case "not-long":
577 | case "or-int":
578 | case "or-int/2addr":
579 | case "or-int/lit16":
580 | case "or-long":
581 | case "or-long/2addr":
582 | case "packed-switch":
583 | case "rem-float":
584 | case "rem-float/2addr":
585 | case "rem-int":
586 | case "rem-int/2addr":
587 | case "rem-int/lit16":
588 | case "rem-int/lit8":
589 | case "rem-long":
590 | case "rem-long/2addr":
591 | case "return-void-barrier":
592 | case "return-wide":
593 | case "rsub-int":
594 | case "rsub-int/lit8":
595 | case "sget":
596 | case "sget-boolean":
597 | case "sget-byte":
598 | case "sget-char":
599 | case "sget-object-volatile":
600 | case "sget-short":
601 | case "sget-volatile":
602 | case "sget-wide":
603 | case "sget-wide-volatile":
604 | case "shl-int":
605 | case "shl-int/2addr":
606 | case "shl-long":
607 | case "shl-long/2addr":
608 | case "shr-int":
609 | case "shr-int/2addr":
610 | case "shr-long":
611 | case "shr-long/2addr":
612 | case "sparse-switch":
613 | case "sput":
614 | case "sput-boolean":
615 | case "sput-byte":
616 | case "sput-char":
617 | case "sput-object-volatile":
618 | case "sput-short":
619 | case "sput-volatile":
620 | case "sput-wide":
621 | case "sput-wide-volatile":
622 | case "sub-double":
623 | case "sub-float":
624 | case "sub-float/2addr":
625 | case "sub-int":
626 | case "sub-int/2addr":
627 | case "sub-long":
628 | case "sub-long/2addr":
629 | case "throw-verification-error":
630 | case "ushr-int":
631 | case "ushr-int/2addr":
632 | case "ushr-long":
633 | case "ushr-long/2addr":
634 | case "xor-int":
635 | case "xor-int/2addr":
636 | case "xor-long":
637 | case "xor-long/2addr":
638 | rv.Smali = LineSmali.Unimplemented;
639 | rv.aName = sRawText;
640 | break;
641 | case "goto":
642 | case "goto/16":
643 | case "goto/32":
644 | case "if-eq":
645 | case "if-eqz":
646 | case "if-ge":
647 | case "if-gez":
648 | case "if-gt":
649 | case "if-gtz":
650 | case "if-le":
651 | case "if-lez":
652 | case "if-lt":
653 | case "if-ltz":
654 | case "if-ne":
655 | case "if-nez":
656 | rv.Smali = LineSmali.Conditional;
657 | rv.aName = sRawText;
658 | break;
659 | default:
660 | rv.Smali = LineSmali.Unknown;
661 | rv.aName = sRawText;
662 | break;
663 | #endregion
664 | }
665 | return true;
666 | }
667 |
668 | public static void ParseParameters(SmaliLine rv, String s)
669 | {
670 | if (s.EndsWith(","))
671 | s = s.Substring(0, s.Length - 1);
672 |
673 | if (s.Contains('{'))
674 | s = s.Substring(1, s.Length - 2);
675 |
676 | if(s.Contains(','))
677 | {
678 | String[] sp = s.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
679 | foreach (String p in sp)
680 | rv.lRegisters[p.Trim()] = String.Empty;
681 | }
682 | else
683 | rv.lRegisters[s] = String.Empty;
684 | }
685 |
686 | #endregion
687 |
688 | }
689 | }
690 |
--------------------------------------------------------------------------------