Smali to Dalvik OpCode

Helper script to translate parts of the smali code of an application to the corresponding Dalvik opcodes, leaving wildcards for the variable parts of the code (variables, parameters, etc.). The output is formatted to be easily transformed in a LuckyPatcher patch.

Устаревшая версия за 09.04.2025. Перейдите к последней версии.

// ==UserScript==
// @name        Smali to Dalvik OpCode
// @namespace   StephenP
// @match       http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html*
// @grant       none
// @version     1.0
// @author      StephenP
// @contributionURL https://buymeacoffee.com/stephenp_greasyfork
// @description Helper script to translate parts of the smali code of an application to the corresponding Dalvik opcodes, leaving wildcards for the variable parts of the code (variables, parameters, etc.). The output is formatted to be easily transformed in a LuckyPatcher patch.
// ==/UserScript==
const table=document.getElementsByTagName("TABLE")[0]
const opcodesColumn=table.querySelectorAll("td:first-child")
var opcodes=[];
for(let i=1;i<opcodesColumn.length;i++){
  opcodes.push(opcodesColumn[i].textContent.slice(0,2));
}
const namesColumn=table.querySelectorAll("td:nth-child(2)")
var names=[];
for(let i=1;i<namesColumn.length;i++){
  names.push(namesColumn[i].textContent.split(" ")[0].trim());
}
const cmdLengthColumn=table.querySelectorAll("td:nth-child(4)")
var cmdLength=[];
for(let i=1;i<cmdLengthColumn.length;i++){
  if(i==84){cmdLength.push(4)}//the table doesn't have the right value here
  else{
    cmdLength.push(cmdLengthColumn[i].textContent.split("-")[0].trim().replaceAll(" ","").length/2);
  }
}
console.log(opcodes)
console.log(names)
console.log(cmdLength)
//horrible styling follows
var container=document.createElement("DIV");
container.style.display="flex";
container.style.flexDirection="row";
container.style.flexWrap="wrap";
table.parentNode.insertBefore(container,table)
var smali=document.createElement("TEXTAREA");
smali.style.minWidth="600px";
smali.style.width="50%"
smali.style.height="300px";
smali.id="smali";
smali.placeholder="Paste here the original smali code.";
container.appendChild(smali)
var dalvik=document.createElement("TEXTAREA");
dalvik.style.minWidth="600px";
dalvik.style.width="50%"
dalvik.style.height="300px";
dalvik.readOnly=true
dalvik.id="dalvik";
dalvik.placeholder="The dalvik bytecode will appear here.";
container.appendChild(dalvik)
var convert=document.createElement("BUTTON");
convert.innerText="CONVERT";
convert.addEventListener("click",smali2davik);
table.parentNode.insertBefore(convert,table)

function smali2davik(){
  var hasPreciseLength=true;
  var preciseLength=0;
  var output="";
  var lines=document.getElementById("smali").value.split("\n");
  var instructions=[];
  for(let i=0;i<lines.length;i++){
    let line=lines[i].trim().split(" ")[0];
    if(line.length>0){
      if((line[0]!==":")&&(line[0]!==".")){
        instructions.push(line);
      }
    }
  }
  console.log(instructions);
  for(let instr of instructions){
    let i=names.indexOf(instr);
    if(i>=0){
      let wholeInstr=" "+opcodes[i];
      for(let j=0;j<cmdLength[i]-1;j++){
        wholeInstr+=" ??";
      }
      if(cmdLength[i]==0){
        wholeInstr+=" ■Unknown bytecode length for instruction \'"+instr+"\'■";
        hasPreciseLength=false;
      }
      console.log(wholeInstr);
      output+=wholeInstr;
    }
    else{
      output+=(" ■Instruction \'"+instr+"\' not found■");
      hasPreciseLength=false;
    }
  }
  if(hasPreciseLength){
    preciseLength=output.length/3;
  }
  output="{\"original\":\""+output.trim()+"\"}";
  if(hasPreciseLength){
    dalvik.value=output+"\n\nTotal length: "+preciseLength+" bytes.";
  }
  else{
    dalvik.value=output;
  }
}