| skipped 284 lines |
285 | 285 | | writeMethodDef(smali, mth, line); |
286 | 286 | | ICodeReader codeReader = mth.getCodeReader(); |
287 | 287 | | if (codeReader != null) { |
| 288 | + | int regsCount = codeReader.getRegistersCount(); |
288 | 289 | | line.smaliMthNode.setParamRegStart(getParamStartRegNum(mth)); |
289 | | - | line.smaliMthNode.setRegCount(codeReader.getRegistersCount()); |
| 290 | + | line.smaliMthNode.setRegCount(regsCount); |
290 | 291 | | Map<Long, InsnNode> nodes = new HashMap<>(codeReader.getUnitsCount() / 2); |
291 | 292 | | line.smaliMthNode.setInsnNodes(nodes, codeReader.getUnitsCount()); |
292 | | - | line.smaliMthNode.initRegInfoList(codeReader.getRegistersCount(), codeReader.getUnitsCount()); |
| 293 | + | line.smaliMthNode.initRegInfoList(regsCount, codeReader.getUnitsCount()); |
293 | 294 | | |
294 | 295 | | smali.incIndent(); |
295 | | - | smali.startLine(".registers ") |
296 | | - | .add("" + codeReader.getRegistersCount()) |
297 | | - | .startLine(); |
| 296 | + | smali.startLine(".registers ").add(Integer.toString(regsCount)); |
| 297 | + | |
298 | 298 | | writeTries(codeReader, line); |
299 | | - | if (formatMthParamInfo(mth, smali, codeReader, line)) { |
300 | | - | smali.startLine(); |
| 299 | + | IDebugInfo debugInfo = codeReader.getDebugInfo(); |
| 300 | + | List<ILocalVar> localVars = debugInfo != null ? debugInfo.getLocalVars() : Collections.emptyList(); |
| 301 | + | formatMthParamInfo(mth, smali, line, regsCount, localVars); |
| 302 | + | if (debugInfo != null) { |
| 303 | + | formatDbgInfo(debugInfo, localVars, line); |
301 | 304 | | } |
| 305 | + | smali.newLine(); |
302 | 306 | | smali.startLine(); |
303 | | - | if (codeReader.getDebugInfo() != null) { |
304 | | - | formatDbgInfo(codeReader.getDebugInfo(), line); |
305 | | - | } |
306 | 307 | | // first pass to fill payload offsets for switch instructions |
307 | 308 | | codeReader.visitInstructions(insn -> { |
308 | 309 | | Opcode opcode = insn.getOpcode(); |
| skipped 149 lines |
458 | 459 | | } |
459 | 460 | | } |
460 | 461 | | |
461 | | - | private boolean formatMthParamInfo(IMethodData mth, SmaliWriter smali, ICodeReader codeReader, LineInfo line) { |
| 462 | + | private void formatMthParamInfo(IMethodData mth, SmaliWriter smali, LineInfo line, |
| 463 | + | int regsCount, List<ILocalVar> localVars) { |
462 | 464 | | List<String> types = mth.getMethodRef().getArgTypes(); |
463 | 465 | | if (types.isEmpty()) { |
464 | | - | return false; |
465 | | - | } |
466 | | - | ILocalVar[] params = new ILocalVar[codeReader.getRegistersCount()]; |
467 | | - | IDebugInfo dbgInfo = codeReader.getDebugInfo(); |
468 | | - | if (dbgInfo != null) { |
469 | | - | for (ILocalVar var : dbgInfo.getLocalVars()) { |
470 | | - | // collect only method parameters |
471 | | - | if (var.getStartOffset() <= 0) { |
472 | | - | params[var.getRegNum()] = var; |
473 | | - | } |
474 | | - | } |
| 466 | + | return; |
475 | 467 | | } |
476 | 468 | | int paramStart = 0; |
477 | 469 | | int regNum = line.smaliMthNode.getParamRegStart(); |
| skipped 4 lines |
482 | 474 | | regNum++; |
483 | 475 | | paramStart++; |
484 | 476 | | } |
| 477 | + | if (localVars.isEmpty()) { |
| 478 | + | return; |
| 479 | + | } |
| 480 | + | ILocalVar[] params = new ILocalVar[regsCount]; |
| 481 | + | for (ILocalVar var : localVars) { |
| 482 | + | if (var.isMarkedAsParameter()) { |
| 483 | + | params[var.getRegNum()] = var; |
| 484 | + | } |
| 485 | + | } |
| 486 | + | smali.newLine(); |
485 | 487 | | for (String paramType : types) { |
486 | | - | String name; |
487 | | - | String type; |
488 | 488 | | ILocalVar param = params[regNum]; |
489 | 489 | | if (param != null) { |
490 | | - | name = Utils.getOrElse(param.getName(), ""); |
491 | | - | type = Utils.getOrElse(param.getSignature(), paramType); |
492 | | - | } else { |
493 | | - | name = ""; |
494 | | - | type = paramType; |
| 490 | + | String name = Utils.getOrElse(param.getName(), ""); |
| 491 | + | String type = Utils.getOrElse(param.getSignature(), paramType); |
| 492 | + | String varName = "p" + paramStart; |
| 493 | + | smali.startLine(String.format(".param %s, \"%s\" # %s", varName, name, type)); |
| 494 | + | line.addRegName(regNum, varName); |
| 495 | + | line.smaliMthNode.setParamReg(regNum, varName); |
495 | 496 | | } |
496 | | - | String varName = "p" + paramStart; |
497 | | - | smali.startLine(String.format(".param %s, \"%s\" # %s", varName, name, type)); |
498 | | - | line.addRegName(regNum, varName); |
499 | | - | line.smaliMthNode.setParamReg(regNum, varName); |
500 | 497 | | int regSize = isWideType(paramType) ? 2 : 1; |
501 | 498 | | regNum += regSize; |
502 | 499 | | paramStart += regSize; |
503 | 500 | | } |
504 | | - | return true; |
505 | 501 | | } |
506 | 502 | | |
507 | 503 | | private static int getParamStartRegNum(IMethodData mth) { |
| skipped 50 lines |
558 | 554 | | smali.startLine(".end annotation"); |
559 | 555 | | } |
560 | 556 | | |
561 | | - | private void formatDbgInfo(IDebugInfo dbgInfo, LineInfo line) { |
| 557 | + | private void formatDbgInfo(IDebugInfo dbgInfo, List<ILocalVar> localVars, LineInfo line) { |
562 | 558 | | dbgInfo.getSourceLineMapping().forEach((codeOffset, srcLine) -> { |
563 | 559 | | if (codeOffset > -1) { |
564 | 560 | | line.addDebugLineTip(codeOffset, String.format(".line %d", srcLine), ""); |
565 | 561 | | } |
566 | 562 | | }); |
567 | | - | for (ILocalVar localVar : dbgInfo.getLocalVars()) { |
568 | | - | String type = localVar.getSignature(); |
569 | | - | if (type == null || type.trim().isEmpty()) { |
570 | | - | type = localVar.getType(); |
| 563 | + | for (ILocalVar localVar : localVars) { |
| 564 | + | if (localVar.isMarkedAsParameter()) { |
| 565 | + | continue; |
571 | 566 | | } |
572 | | - | if (localVar.getStartOffset() > -1) { |
573 | | - | line.addTip( |
574 | | - | localVar.getStartOffset(), |
575 | | - | String.format(".local v%d", localVar.getRegNum()), |
576 | | - | String.format(", \"%s\":%s", localVar.getName(), type)); |
| 567 | + | String type = localVar.getType(); |
| 568 | + | String sign = localVar.getSignature(); |
| 569 | + | String longTypeStr; |
| 570 | + | if (sign == null || sign.trim().isEmpty()) { |
| 571 | + | longTypeStr = String.format(", \"%s\":%s", localVar.getName(), type); |
| 572 | + | } else { |
| 573 | + | longTypeStr = String.format(", \"%s\":%s, \"%s\"", localVar.getName(), type, localVar.getSignature()); |
577 | 574 | | } |
578 | | - | if (localVar.getEndOffset() > -1) { |
579 | | - | line.addTip( |
580 | | - | localVar.getEndOffset(), |
581 | | - | String.format(".end local v%d", localVar.getRegNum()), |
582 | | - | String.format(" # \"%s\":%s", localVar.getName(), type)); |
583 | | - | } |
| 575 | + | line.addTip( |
| 576 | + | localVar.getStartOffset(), |
| 577 | + | ".local " + formatVarName(line.smaliMthNode, localVar), |
| 578 | + | longTypeStr); |
| 579 | + | line.addTip( |
| 580 | + | localVar.getEndOffset(), |
| 581 | + | ".end local " + formatVarName(line.smaliMthNode, localVar), |
| 582 | + | String.format(" # \"%s\":%s", localVar.getName(), type)); |
| 583 | + | } |
| 584 | + | } |
| 585 | + | |
| 586 | + | private String formatVarName(SmaliMethodNode smaliMthNode, ILocalVar localVar) { |
| 587 | + | int paramRegStart = smaliMthNode.getParamRegStart(); |
| 588 | + | int regNum = localVar.getRegNum(); |
| 589 | + | if (regNum < paramRegStart) { |
| 590 | + | return "v" + regNum; |
584 | 591 | | } |
| 592 | + | return "p" + (regNum - paramRegStart); |
585 | 593 | | } |
586 | 594 | | |
587 | 595 | | private void writeEncodedValue(SmaliWriter smali, EncodedValue value, boolean wrapArray) { |
| skipped 485 lines |