コード例 #1
0
 public bool HasAnyEffect(StackRelatedInstructionEffect effect) => (Effects & effect) != StackRelatedInstructionEffect.None;
コード例 #2
0
        StackRelatedInstructionEffects ClassifyInstruction(StackAnalyzerInstruction insn)
        {
            string remainingArgs = insn.Arguments;

            if (insn.Opcode == "push" || insn.Opcode == "pop")
            {
                int sign       = insn.Opcode == "push" ? 1 : -1;
                int listLength = GetRegisterListLength(insn.Arguments, out var hasPC);
                StackRelatedInstructionEffect extraEffects = StackRelatedInstructionEffect.None;
                if (hasPC)
                {
                    extraEffects |= StackRelatedInstructionEffect.ReturnFromCall;
                }

                return(new StackRelatedInstructionEffects {
                    Effects = StackRelatedInstructionEffect.MovesStackPointer | extraEffects, StackDelta = sign * WordSize * listLength
                });
            }
            else if (insn.Opcode.StartsWith("mov"))
            {
                string arg  = TakeFirstArgument(ref remainingArgs);
                string arg2 = TakeFirstArgument(ref remainingArgs);
                if (arg == "sp")
                {
                    if (arg2 == "r7")
                    {
                        return new StackRelatedInstructionEffects {
                                   Effects = StackRelatedInstructionEffect.RestoresStackPointer
                        }
                    }
                    ;
                    else
                    {
                        return new StackRelatedInstructionEffects {
                                   Effects = StackRelatedInstructionEffect.ChangesStackPointerUnpredictably
                        }
                    };
                }
                else if (arg == "r7" && arg2 == "sp")
                {
                    return(new StackRelatedInstructionEffects {
                        Effects = StackRelatedInstructionEffect.SavesStackPointerWithDelta
                    });
                }
            }
            else if (insn.Opcode == "ldr" || insn.Opcode.StartsWith("ldr.w") || insn.Opcode == "ldrd" || insn.Opcode.StartsWith("ldrd.") ||
                     insn.Opcode == "str" || insn.Opcode.StartsWith("str.w") || insn.Opcode == "strd" || insn.Opcode.StartsWith("strd."))
            {
                string arg = TakeFirstArgument(ref remainingArgs);
                if (insn.Opcode.StartsWith("ldr") && arg == "sp")
                {
                    return new StackRelatedInstructionEffects {
                               Effects = StackRelatedInstructionEffect.ChangesStackPointerUnpredictably
                    }
                }
                ;

                if (insn.Opcode.StartsWith("strd") || insn.Opcode.StartsWith("ldrd"))
                {
                    TakeFirstArgument(ref remainingArgs);   //Ignore the second loaded/stored register
                }
                Match m;

                if (remainingArgs.StartsWith("[sp,") && (m = rgSpRelativeAddressing.Match(remainingArgs)).Success)
                {
                    return(new StackRelatedInstructionEffects {
                        Effects = StackRelatedInstructionEffect.MovesStackPointer, StackDelta = -int.Parse(m.Groups[1].Value)
                    });
                }
                else
                {
                    string arg2 = TakeFirstArgument(ref remainingArgs);
                    if (arg2 == "[sp]")
                    {
                        if (int.TryParse(remainingArgs.Trim('#', '!'), out int offset))
                        {
                            return new StackRelatedInstructionEffects {
                                       Effects = StackRelatedInstructionEffect.MovesStackPointer, StackDelta = -offset
                            }
                        }
                        ;
                    }
                }
            }
            else if (insn.Opcode == "add" || insn.Opcode == "sub" || insn.Opcode == "adds" || insn.Opcode == "subs" || insn.Opcode == "addw" || insn.Opcode == "subw" || insn.Opcode == "add.w" || insn.Opcode == "sub.w")
            {
                int sign = insn.Opcode.StartsWith("sub") ? 1 : -1;

                string targetRegister = TakeFirstArgument(ref remainingArgs);
                string sourceRegister = TakeFirstArgument(ref remainingArgs);
                if (remainingArgs == "")
                {
                    remainingArgs  = sourceRegister;
                    sourceRegister = targetRegister;
                }

                if (targetRegister == "sp")
                {
                    var delta = ParseImmediateValue(remainingArgs);
                    if (delta.HasValue)
                    {
                        if (targetRegister == "sp")
                        {
                            return new StackRelatedInstructionEffects {
                                       Effects = StackRelatedInstructionEffect.MovesStackPointer, StackDelta = sign * delta.Value
                            }
                        }
                        ;
                        else if (targetRegister == "r7")
                        {
                            return new StackRelatedInstructionEffects {
                                       Effects = StackRelatedInstructionEffect.SavesStackPointerWithDelta, StackDelta = sign * delta.Value
                            }
                        }
                        ;
                    }
                    return(new StackRelatedInstructionEffects {
                        Effects = StackRelatedInstructionEffect.ChangesStackPointerUnpredictably
                    });
                }
                else if (targetRegister == "r7")
                {
                    if (sourceRegister == "sp")
                    {
                        var delta = ParseImmediateValue(remainingArgs);
                        if (delta.HasValue)
                        {
                            return new StackRelatedInstructionEffects {
                                       Effects = StackRelatedInstructionEffect.SavesStackPointerWithDelta, StackDelta = sign * delta.Value
                            }
                        }
                        ;
                    }
                    else
                    {
                        var delta = ParseImmediateValue(remainingArgs);
                        if (delta.HasValue)
                        {
                            return new StackRelatedInstructionEffects {
                                       Effects = StackRelatedInstructionEffect.MovesSavedStackPointer, StackDelta = sign * delta.Value
                            }
                        }
                        ;
                    }

                    return(new StackRelatedInstructionEffects {
                        Effects = StackRelatedInstructionEffect.ChangesFramePointerUnpredictably
                    });
                }
            }
            else if (insn.Opcode == "cbz" || insn.Opcode == "cbnz")
            {
                string arg1   = TakeFirstArgument(ref remainingArgs);
                var    target = ParseAddress(remainingArgs);
                if (target.HasValue)
                {
                    return new StackRelatedInstructionEffects {
                               Effects = StackRelatedInstructionEffect.ConditionalJump | StackRelatedInstructionEffect.JumpTargetKnown, JumpTarget = StripThumbBit(target.Value)
                    }
                }
                ;
                else
                {
                    return new StackRelatedInstructionEffects {
                               Effects = StackRelatedInstructionEffect.UnpredictableJump
                    }
                };
            }
            else if (insn.Opcode.StartsWith("b"))
            {
                string arg = TakeFirstArgument(ref remainingArgs, ' ');

                if (insn.Opcode == "bx" && arg == "lr")
                {
                    return new StackRelatedInstructionEffects {
                               Effects = StackRelatedInstructionEffect.ReturnFromCall | StackRelatedInstructionEffect.JumpsViaLinkRegister
                    }
                }
                ;

                StackRelatedInstructionEffect effect = StackRelatedInstructionEffect.None;

                foreach (var cc in ARMConditionCodes)
                {
                    if (insn.Opcode.StartsWith("bl" + cc))
                    {
                        effect = StackRelatedInstructionEffect.FunctionCall;
                        break;
                    }
                }

                if (effect == StackRelatedInstructionEffect.None)
                {
                    foreach (var cc in ARMConditionCodes)
                    {
                        if (insn.Opcode.StartsWith("b" + cc))
                        {
                            effect = StackRelatedInstructionEffect.ConditionalJump;

                            break;
                        }
                    }
                }

                if (effect == StackRelatedInstructionEffect.None)
                {
                    if (insn.Opcode.StartsWith("bl"))
                    {
                        effect = StackRelatedInstructionEffect.FunctionCall;
                    }
                    else if (insn.Opcode == "b" || insn.Opcode == "bx" || insn.Opcode.StartsWith("b.") || insn.Opcode.StartsWith("bx."))
                    {
                        effect = StackRelatedInstructionEffect.UnconditionalJump;
                    }
                }

                if (effect != StackRelatedInstructionEffect.None)
                {
                    var target = ParseAddress(arg);

                    if (target.HasValue)
                    {
                        return new StackRelatedInstructionEffects {
                                   Effects = effect | StackRelatedInstructionEffect.JumpTargetKnown, JumpTarget = StripThumbBit(target.Value)
                        }
                    }
                    ;
                    else
                    {
                        if (IsSingleRegister(arg) && remainingArgs == "")
                        {
                            return new StackRelatedInstructionEffects {
                                       Effects = effect | StackRelatedInstructionEffect.RegisterJump
                            }
                        }
                        ;
                        else
                        {
                            return new StackRelatedInstructionEffects {
                                       Effects = effect | StackRelatedInstructionEffect.UnpredictableJump
                            }
                        };
                    }
                }
            }
            else if (insn.Opcode.StartsWith("ldmia") || insn.Opcode.StartsWith("stmdb"))
            {
                int sign = insn.Opcode.StartsWith("stmdb") ? 1 : -1;

                string arg0 = TakeFirstArgument(ref remainingArgs);
                if (arg0 == "sp!")
                {
                    var result = new StackRelatedInstructionEffects
                    {
                        Effects    = StackRelatedInstructionEffect.MovesStackPointer,
                        StackDelta = sign * WordSize * GetRegisterListLength(remainingArgs, out var includesPC)
                    };

                    if (includesPC)
                    {
                        result.Effects |= StackRelatedInstructionEffect.ReturnFromCall;
                    }

                    return(result);
                }
            }

            return(default(StackRelatedInstructionEffects));
        }