private MethodBody BuildMethodBody( ModuleInfo moduleInfo, Method method ) { Debug.Assert( this.Debugger.DebugHost.CpuHook != null ); uint[] codes = this.Debugger.DebugHost.CpuHook.GetMethodBody( method ); uint instrAddress = method.Address; List<Instruction> instrs = new List<Instruction>( ( int )method.Length / 4 ); for( int n = 0; n < codes.Length; n++ ) { Instruction instr = new Instruction( instrAddress, codes[ n ] ); instrs.Add( instr ); instrAddress += 4; } MethodBody methodBody = new MethodBody( moduleInfo, method.Address, ( uint )method.Length, instrs.ToArray() ); if( method.Type == MethodType.Bios ) { if( method.Function.MethodName != null ) methodBody.Name = method.Function.MethodName; else methodBody.Name = method.Function.ModuleName + "::" + method.Function.NID.ToString( "X8" ); methodBody.Function = method.Function; } else { if( method.Name != null ) methodBody.Name = method.Name; } return methodBody; }
private void AddMemoryReference( List<MemoryReference> memRefs, Instruction instruction, uint target, bool isRead ) { //Debug.WriteLine( string.Format( "adding memory reference at {0:X8} ({1}) to {2:X8} for {3}", instruction.Address, instruction, target, isRead ? "read" : "write" ) ); foreach( MemoryReference memRef in memRefs ) { if( memRef.Address == target ) { memRef.References.Add( instruction ); if( isRead == true ) memRef.Reads++; else memRef.Writes++; instruction.Reference = memRef; return; } } MemoryReference newMemRef = new MemoryReference(); newMemRef.Address = target; newMemRef.References.Add( instruction ); if( isRead == true ) newMemRef.Reads++; else newMemRef.Writes++; instruction.Reference = newMemRef; memRefs.Add( newMemRef ); }
private void AddLabelReference( List<Label> labels, Instruction instruction, uint target ) { foreach( Label label in labels ) { if( label.Address == target ) { label.References.Add( instruction ); instruction.Reference = label; return; } } Label newLabel = new Label(); newLabel.Name = string.Format( "loc_{0:X8}", target ); newLabel.Address = target; newLabel.References.Add( instruction ); instruction.Reference = newLabel; labels.Add( newLabel ); }
private void AddCodeReference( List<CodeReference> codeRefs, Instruction instruction, uint target ) { if( target == 0 ) return; foreach( CodeReference codeRef in codeRefs ) { if( codeRef.Address == target ) { codeRef.References.Add( instruction ); instruction.Reference = codeRef; return; } } CodeReference newCodeRef = new CodeReference(); newCodeRef.Address = target; newCodeRef.References.Add( instruction ); instruction.Reference = newCodeRef; codeRefs.Add( newCodeRef ); }
public void Populate( Instruction[] instructions ) { this.Instructions = instructions; // - determine locals (loop for first addiu $sp, $sp, [size] // - find all labels (branch targets) bool foundSpMod = false; List<Label> labels = new List<Label>(); List<CodeReference> codeRefs = new List<CodeReference>(); List<MemoryReference> memRefs = new List<MemoryReference>(); uint[] currentRegisters = new uint[ 32 ]; uint validRegisters = 0; bool inDelay = false; foreach( Instruction instruction in instructions ) { //lui $n, NNN //addiu $n, $n, NNN //lui $n, NNN //ori $n, $n, NNN //lui $n, NNN //l* $m, NNN($n) //lui $n, NNN //s* $m, NNN($n) bool wasInDelay = inDelay; inDelay = false; if( instruction.Opcode != null ) { if( instruction.IsBranch == true ) { uint target = 0; foreach( Operand op in instruction.Operands ) { if( op.Type == OperandType.BranchTarget ) { target = ( uint )( ( int )instruction.Address + 4 + op.Immediate ); break; } } if( target > 0 ) this.AddLabelReference( labels, instruction, target ); inDelay = true; } else if( instruction.IsJump == true ) { uint target = 0; foreach( Operand op in instruction.Operands ) { if( op.Type == OperandType.JumpTarget ) { target = ( uint )op.Immediate; break; } } if( ( target >= this.Address ) && ( target < ( this.Address + this.Length ) ) ) this.AddLabelReference( labels, instruction, target ); else this.AddCodeReference( codeRefs, instruction, target ); inDelay = true; } else if( instruction.IsLoad == true ) { int reg1 = instruction.Operands[ 1 ].Register.Ordinal; if( ( validRegisters & ( 1 << reg1 ) ) > 0 ) { uint target = currentRegisters[ reg1 ]; target = ( uint )( ( int )target + instruction.Operands[ 1 ].Immediate ); this.AddMemoryReference( memRefs, instruction, target, true ); } } else if( instruction.IsStore == true ) { int reg1 = instruction.Operands[ 1 ].Register.Ordinal; if( ( validRegisters & ( 1 << reg1 ) ) > 0 ) { uint target = currentRegisters[ reg1 ]; target = ( uint )( ( int )target + instruction.Operands[ 1 ].Immediate ); this.AddMemoryReference( memRefs, instruction, target, false ); } } if( ( foundSpMod == false ) && ( instruction.Opcode.InstructionEntry.Name == "addiu" ) ) { foundSpMod = true; int adjustment = instruction.Operands[ 2 ].Immediate / 4; this.LocalsSize = -adjustment; } else { uint flags = instruction.Opcode.InstructionEntry.Flags; if( instruction.Opcode.InstructionEntry.Name == "lui" ) { int reg = instruction.Operands[ 0 ].Register.Ordinal; validRegisters |= ( uint )( 1 << reg ); currentRegisters[ reg ] = ( uint )instruction.Operands[ 1 ].Immediate << 16; } else if( ( flags & InstructionTables.OUT_RT ) > 0 ) { if( instruction.Opcode.InstructionEntry.Name == "addiu" ) { int reg1 = instruction.Operands[ 1 ].Register.Ordinal; if( ( validRegisters & ( 1 << reg1 ) ) > 0 ) { int reg2 = instruction.Operands[ 0 ].Register.Ordinal; validRegisters |= ( uint )( 1 << reg2 ); currentRegisters[ reg2 ] = ( uint )( ( int )currentRegisters[ reg1 ] + instruction.Operands[ 2 ].Immediate ); } } else if( instruction.Opcode.InstructionEntry.Name == "ori" ) { int reg1 = instruction.Operands[ 1 ].Register.Ordinal; if( ( validRegisters & ( 1 << reg1 ) ) > 0 ) { int reg2 = instruction.Operands[ 0 ].Register.Ordinal; validRegisters |= ( uint )( 1 << reg2 ); currentRegisters[ reg2 ] = currentRegisters[ reg1 ] | ( uint )instruction.Operands[ 2 ].Immediate; } } else { // Changed - no longer valid int reg = instruction.Operands[ 0 ].Register.Ordinal; validRegisters &= ~( uint )( 1 << reg ); } } } } if( wasInDelay == true ) validRegisters = 0; } // Sort all this.SortAndSet( labels, codeRefs, memRefs ); // Add labels to instructions foreach( Label label in this.Labels ) { foreach( Instruction instruction in this.Instructions ) { if( label.Address == instruction.Address ) { instruction.Label = label; break; } } } this.TotalLines = ( uint )( this.Instructions.Length + this.Labels.Length ); }
public MethodBody( ModuleInfo moduleInfo, uint address, uint length, Instruction[] instructions ) { this.Module = moduleInfo; this.Name = string.Format( "sub_{0:X8}", address ); this.TotalLines = length / 4; this.Address = address; this.Length = length; this.IncomingReferences = new List<ExternalReference>(); this.OutgoingReferences = new List<ExternalReference>(); if( instructions != null ) this.Populate( instructions ); }