/* * TODO: Figure out when these should be variable assignments, and when they should be constants... * Right now we spam variables like there is no tomorrow. Can we really rely on "end locals"? * 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... */ public void MoveResult() //We *MIGHT* need to make a second one for objects... { 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. String sReg = l.lRegisters.Keys.First(); SmaliCall cOld = SmaliEngine.VM.GetLastCall(); Dictionary <String, String> registers = SmaliEngine.VM.GetLastRegisters(); if (cOld != null && registers != null) //SKIP, again something is wrong if we skip here. { SmaliEngine.VM.Put(sReg, cOld.SmaliReturnType.ToString() + m.IncrementTypeCount(cOld.SmaliReturnType)); //TODO: generate variable names programatically here. SmaliEngine.VM.PutLastCall(null); // Wipe so we don't accidentally get something we missed again. SmaliEngine.VM.PutLastRegisters(null); string regs = null; try { regs = ParseRegistersAsArgs(registers); } catch { Unimplemented(); return; } SmaliEngine.VM.Buf.AppendFormat("{0} = {1}({2});\n", SmaliUtils.General.Name2Java(SmaliUtils.General.ReturnType2Java(cOld.SmaliReturnType, cOld.Return)).Replace(";", String.Empty) + SmaliEngine.VM.Get(sReg), (m.ParentClass.PackageName == cOld.ClassName && m.ParentClass.ClassName == cOld.Method ? "this." : (SmaliUtils.General.Name2Java(cOld.ClassName) + "." + cOld.Method)), regs ); SmaliEngine.VM.FlushBuffer(); } }
public void SputObject() { String sReg = l.lRegisters.Keys.First(); // SKIP! TODO: Should not skip, actually. If it skips, something IS wrong if (!SmaliEngine.VM.vmStack.ContainsKey(sReg)) { Unimplemented(); return; } String sSrcValue = SmaliEngine.VM.Get(sReg); String sDstValue = l.lRegisters[sReg]; Dictionary <String, String> args = new Dictionary <String, String>(); args[sReg] = sSrcValue; SmaliCall c = SmaliCall.Parse(sDstValue); SmaliEngine.VM.Buf = new StringBuilder(); SmaliEngine.VM.Buf.AppendFormat("{0}{1}{2} = {3};\n", c.Variable, m.ParentClass.PackageName == c.ClassName ? "" : (c.ClassName + "."), m.ParentClass.ClassName == c.Method ? "" : (c.Method + "."), sSrcValue ); }
public void IputBoolean() { String sReg = l.lRegisters.Keys.First(); // SKIP! TODO: Should not skip, actually. If it skips, something IS wrong if (!SmaliEngine.VM.vmStack.ContainsKey(sReg)) { Unimplemented(); return; } String sSrcValue = SmaliEngine.VM.Get(sReg); String sDstValue = l.aName; Dictionary <String, String> args = new Dictionary <String, String>(); args[sReg] = sSrcValue; SmaliCall c = SmaliCall.Parse(sDstValue); SmaliEngine.VM.Buf = new StringBuilder(); SmaliEngine.VM.Buf.AppendFormat("{0}{1} = {2};\n", (m.ParentClass.PackageName == c.ClassName && m.ParentClass.ClassName == c.Method ? "this." : (SmaliUtils.General.Name2Java(c.ClassName) + "." + c.Method + ".")), c.Variable, (sSrcValue == "0x1" ? "true" : "false") ); //TODO: Well... todo. Lol. //Buffer.Append(ParseSmali(sDstValue, args)); }
public void Method() { m.AccessModifiers = l.AccessModifiers; m.NonAccessModifiers = l.NonAccessModifiers; m.MethodCall = SmaliCall.Parse(l.aExtra); SmaliEngine.VM._idxParam = 0; }
public void NewInstance() { SmaliCall c = SmaliCall.Parse(l.lRegisters[l.lRegisters.Keys.First()]); StringBuilder sb = new StringBuilder(); sb.Append("new " + SmaliUtils.General.Name2Java(c.ClassName)); sb.Append("." + c.Method + "()"); SmaliEngine.VM.Put(l.lRegisters.Keys.First(), sb.ToString()); }
public void Invoke() //TODO: Move this out into more generic functions? { String sReg = l.lRegisters.Keys.First(); // SKIP! TODO: Should not skip, actually. If it skips, something IS wrong if (!SmaliEngine.VM.vmStack.ContainsKey(sReg)) { Unimplemented(); return; } SmaliCall c = SmaliCall.Parse(l.lRegisters[l.lRegisters.Keys.First()]); // It's a constructor, skip method name if ((c.CallFlags & SmaliCall.ECallFlags.Constructor) == SmaliCall.ECallFlags.Constructor) { SmaliEngine.VM.Buf.Append(SmaliEngine.VM.Get(sReg)); } else { string regs = null; try { regs = ParseRegistersAsArgs(l.lRegisters); } catch { Unimplemented(); return; } SmaliEngine.VM.Buf.AppendFormat("{0}({1});\n", (m.ParentClass.PackageName == c.ClassName && m.ParentClass.ClassName == c.Method ? "this." : (SmaliUtils.General.Name2Java(c.ClassName) + "." + c.Method)), regs ); //We add this to the buffer one way or another, it just gets cleared if the next instruction is MoveResult. //TODO: Maybe we should simply prepend the buffer with the variable for move result? // We are actually returning something here, put this as the value of the last instruction to be acted on by move-result. if (c.SmaliReturnType != SmaliLine.LineReturnType.Void) { SmaliEngine.VM.PutLastCall(c); SmaliEngine.VM.PutLastRegisters(l.lRegisters); } } }
public void SgetObject() { String sReg = l.lRegisters.Keys.First(); String sSrcValue = l.lRegisters[sReg]; String sDstValue = sReg; SmaliCall c = SmaliCall.Parse(sSrcValue); string prepend = String.Empty; if (m.ParentClass.PackageName == c.ClassName && m.ParentClass.ClassName == c.Method) { prepend = "this."; } else // I don't think sget-object should ever hit this? { prepend = SmaliUtils.General.Name2Java(c.ClassName) + '.' + c.Method + '.'; } SmaliEngine.VM.Put(sDstValue, prepend + c.Variable); }
public void PutLastCall(SmaliCall value) { vmStack["lastCall"] = value; }
public static SmaliCall Parse(String l) { SmaliCall rv = new SmaliCall(); rv.Method = l; if (l.Contains("(")) { // Function call rv.Method = rv.Method.Substring(0, rv.Method.IndexOf("(")); rv.Return = l.Substring(l.LastIndexOf(")") + 1); if (rv.Return.Length > 0) { rv.SmaliReturnType = SmaliUtils.General.GetReturnType(rv.Return); } if (rv.Method.Contains("->")) { rv.ClassName = rv.Method.Substring(0, rv.Method.IndexOf(";")); rv.Method = rv.Method.Substring(rv.Method.IndexOf("->") + 2); } } else { if (l.Contains("/")) { rv.ClassName = l; if (l.Contains("->")) { rv.ClassName = l.Substring(0, l.IndexOf("->")); } // Get class name out rv.ClassName = rv.ClassName.Substring(0, rv.ClassName.LastIndexOf('/')); rv.Method = l.Substring(rv.ClassName.Length + 1); if (l.Contains(":")) { rv.Variable = rv.Method.Substring(rv.Method.IndexOf("->") + 2); rv.Variable = rv.Variable.Substring(0, rv.Variable.IndexOf(":")); } rv.Method = rv.Method.Substring(0, rv.Method.IndexOf(";")); } } if (rv.Method.EndsWith(";")) { rv.Method = rv.Method.Remove(rv.Method.Length - 1, 1); } if (l.Contains("(")) { // Get parameters String sParameters = l.Substring(l.IndexOf("(") + 1); sParameters = sParameters.Substring(0, sParameters.IndexOf(")")); if (sParameters.Length > 0) { String[] aParm = sParameters.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (String p in aParm) { if (p.StartsWith("L")) { rv.Parameters.Add(new SmaliParameter() { Type = p, }); } else { for (int i = 0; i < p.Length; i++) { if (!p[i].Equals('L')) { rv.Parameters.Add(new SmaliParameter() { Type = String.Empty + p[i], }); } else if (p[i].Equals('[')) // This is an Array. { if (p[i + 1].Equals('L')) { rv.Parameters.Add(new SmaliParameter() { Type = p.Substring(i), }); break; } else { rv.Parameters.Add(new SmaliParameter() { Type = String.Empty + p[i] + p[i + 1], }); i++; } } else { rv.Parameters.Add(new SmaliParameter() { Type = p.Substring(i), }); break; } } } } } } // Set flags if (rv.Method == "<clinit>") { rv.Method = String.Empty; rv.Return = String.Empty; rv.SmaliReturnType = SmaliLine.LineReturnType.Custom; rv.CallFlags |= ECallFlags.ClassInit; } if (rv.Method == "<init>") { rv.Return = String.Empty; rv.SmaliReturnType = SmaliLine.LineReturnType.Custom; rv.CallFlags |= ECallFlags.Constructor; } return(rv); }
public static SmaliCall Parse(String l) { SmaliCall rv = new SmaliCall(); rv.Method = l; if (l.Contains("(")) { // Function call rv.Method = rv.Method.Substring(0, rv.Method.IndexOf("(")); rv.Return = l.Substring(l.LastIndexOf(")") + 1); if (rv.Return.Length > 0) rv.SmaliReturnType = SmaliUtils.General.GetReturnType(rv.Return); if(rv.Method.Contains("->")) { rv.ClassName = rv.Method.Substring(0, rv.Method.IndexOf(";")); rv.Method = rv.Method.Substring(rv.Method.IndexOf("->") + 2); } } else { if (l.Contains("/")) { rv.ClassName = l; if (l.Contains("->")) rv.ClassName = l.Substring(0, l.IndexOf("->")); // Get class name out rv.ClassName = rv.ClassName.Substring(0, rv.ClassName.LastIndexOf('/')); rv.Method = l.Substring(rv.ClassName.Length + 1); if (l.Contains(":")) { rv.Variable = rv.Method.Substring(rv.Method.IndexOf("->") + 2); rv.Variable = rv.Variable.Substring(0, rv.Variable.IndexOf(":")); } rv.Method = rv.Method.Substring(0, rv.Method.IndexOf(";")); } } if (rv.Method.EndsWith(";")) rv.Method = rv.Method.Remove(rv.Method.Length - 1, 1); if(l.Contains("(")) { // Get parameters String sParameters = l.Substring(l.IndexOf("(") + 1); sParameters = sParameters.Substring(0, sParameters.IndexOf(")")); if (sParameters.Length > 0) { String[] aParm = sParameters.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (String p in aParm) if (p.StartsWith("L")) { rv.Parameters.Add(new SmaliParameter() { Type = p, }); } else { for (int i = 0 ; i < p.Length; i++) { if (!p[i].Equals('L')) { rv.Parameters.Add(new SmaliParameter() { Type = String.Empty + p[i], }); } else if (p[i].Equals('[')) // This is an Array. { if (p[i+1].Equals('L')) { rv.Parameters.Add(new SmaliParameter() { Type = p.Substring(i), }); break; } else { rv.Parameters.Add(new SmaliParameter() { Type = String.Empty + p[i] + p[i+1], }); i++; } } else { rv.Parameters.Add(new SmaliParameter() { Type = p.Substring(i), }); break; } } } } } // Set flags if (rv.Method == "<clinit>") { rv.Method = String.Empty; rv.Return = String.Empty; rv.SmaliReturnType = SmaliLine.LineReturnType.Custom; rv.CallFlags |= ECallFlags.ClassInit; } if (rv.Method == "<init>") { rv.Return = String.Empty; rv.SmaliReturnType = SmaliLine.LineReturnType.Custom; rv.CallFlags |= ECallFlags.Constructor; } return rv; }