| 743 | |
| 744 | |
| 745 | bool Patch_VerifyLocation_CheckSignature(PatchSymbol * ps, |
| 746 | PatchSignature * psig, |
| 747 | u32 index) |
| 748 | { |
| 749 | OpCode op; |
| 750 | PatchCrossRef * pcr = psig->CrossRefs; |
| 751 | bool cross_ref_var_set( false ); |
| 752 | u32 crc; |
| 753 | u32 partial_crc; |
| 754 | |
| 755 | if ( ( index + psig->NumOps ) * 4 > gRamSize ) |
| 756 | { |
| 757 | return false; |
| 758 | } |
| 759 | |
| 760 | const u32 * code_base( g_pu32RamBase ); |
| 761 | |
| 762 | PatchCrossRef dummy_cr = {static_cast<u32>(~0), PX_JUMP, nullptr }; |
| 763 | |
| 764 | if (pcr == nullptr) |
| 765 | pcr = &dummy_cr; |
| 766 | |
| 767 | #ifdef DAEDALUS_DEBUG_CONSOLE |
| 768 | u32 last = pcr->Offset; |
| 769 | #endif |
| 770 | crc = 0; |
| 771 | partial_crc = 0; |
| 772 | for (u32 m = 0; m < psig->NumOps; m++) |
| 773 | { |
| 774 | // Get the actual opcode at this address, not patched/compiled code |
| 775 | op._u32 = code_base[index+m]; |
| 776 | op = GetCorrectOp( op ); |
| 777 | // This should be ok - so long as we patch all functions at once. |
| 778 | |
| 779 | // Check if a cross reference is in effect here |
| 780 | if (pcr->Offset == m) |
| 781 | { |
| 782 | // This is a cross reference. |
| 783 | switch (pcr->Type) |
| 784 | { |
| 785 | case PX_JUMP: |
| 786 | { |
| 787 | u32 TargetIndex = JumpTarget( op, (index+m)<<2 )>>2; |
| 788 | |
| 789 | // If the opcode at this address is not a Jump/Jal then |
| 790 | // this can't match |
| 791 | if ( op.op != OP_JAL && op.op != OP_J ) |
| 792 | goto fail_find; |
| 793 | |
| 794 | // This is a jump, the jump target must match the |
| 795 | // symbol pointed to by this function. Recurse |
| 796 | if (!Patch_VerifyLocation(pcr->Symbol, TargetIndex)) |
| 797 | goto fail_find; |
| 798 | |
| 799 | op.target = 0; // Mask out jump location |
| 800 | } |
| 801 | break; |
| 802 | case PX_VARIABLE_HI: |
no test coverage detected