From c970898e43f165bc740c47d816d8c41266024cab Mon Sep 17 00:00:00 2001 From: Sang Kil Cha Date: Fri, 22 Oct 2021 19:47:34 +0900 Subject: [PATCH] Temporarily bump 0.5.0 We temporarily use MiddleEnd packages from NuGet: https://www.nuget.org/packages?q=B2R2.MiddleEnd --- .b2r2-ci.json | 4 + .config/dotnet-tools.json | 12 + .gitignore | 2 +- .gitlab-ci.yml | 17 +- AUTHORS.md | 6 + B2R2.sln | 1032 +-- CONTRIBUTING.md | 7 +- Directory.Build.props | 11 +- README.md | 85 +- .../Library => assets}/b2r2-240x240.png | Bin lib/libfpu/.gitignore | 1 - lib/libfpu/Makefile | 11 - lib/libfpu/fpu.c | 7 - samples/CSharp/b2r2.csx | 17 +- samples/FSharp/b2r2.fsx | 17 +- samples/Python/b2r2.py | 23 - samples/VB/B2R2.vbproj | 13 + samples/VB/Program.vb | 17 + .../B2R2.Assembler.Tests.fsproj | 30 - .../ARM32/B2R2.Assembler.ARM32.fsproj | 18 - src/Assembler/Core/B2R2.Assembler.Core.fsproj | 15 - .../Intel/B2R2.Assembler.Intel.fsproj | 22 - .../Interface/B2R2.Assembler.Interface.fsproj | 18 - .../LowUIR/B2R2.Assembler.LowUIR.fsproj | 22 - src/Assembler/LowUIR/LowUIRParser.fs | 237 - src/Assembler/LowUIR/LowUIRParserUtils.fs | 108 - src/Assembler/MIPS/B2R2.Assembler.MIPS.fsproj | 21 - src/BinEssence/B2R2.BinEssence.fsproj | 32 - src/BinEssence/BBLInfo.fs | 51 - src/BinEssence/BasicBlock.fs | 42 - src/BinEssence/BinEssence.fs | 784 -- src/BinEssence/CFGEdgeKind.fs | 73 - src/BinEssence/CFGElement.fs | 33 - src/BinEssence/CFGExport.fs | 74 - src/BinEssence/CalleeMap.fs | 156 - src/BinEssence/IRBasicBlock.fs | 90 - src/BinEssence/InstrMap.fs | 121 - src/BinEssence/InstructionInfo.fs | 50 - src/BinFile.Tests/B2R2.BinFile.Tests.fsproj | 23 - src/BinFile/ELFDwarfTypes.fs | 57 - src/BinFile/ELFExceptionFrames.fs | 213 - src/BinGraph.Tests/B2R2.BinGraph.Tests.fsproj | 25 - src/BinGraph.Tests/ImperativeGraph.Tests.fs | 473 - src/BinGraph.Tests/PersistentGraph.Tests.fs | 473 - src/BinGraph/B2R2.BinGraph.fsproj | 39 - src/BinGraph/DiGraph.fs | 283 - src/BinGraph/DiGraph.fsi | 217 - src/BinGraph/Dominator.fs | 327 - src/BinGraph/Dominator.fsi | 81 - src/BinGraph/DummyVertex.fs | 36 - src/BinGraph/Graph.fs | 114 - src/BinGraph/GraphCore.fs | 81 - src/BinGraph/Imperative.fs | 352 - src/BinGraph/Persistent.fs | 361 - src/BinGraph/RangedDiGraph.fs | 49 - src/BinGraph/SCC.fs | 130 - src/BinGraph/Traversal.fs | 105 - src/BinGraph/Vertices.fs | 109 - src/BinIR.Tests/B2R2.BinIR.Tests.fsproj | 25 + src/BinIR.Tests/Program.fs | 1 + src/BinIR.Tests/Tests.fs | 75 + src/BinIR/B2R2.BinIR.fsproj | 22 +- src/BinIR/BinOpType.fs | 29 +- src/BinIR/CastKind.fs | 15 +- src/BinIR/Expr.fs | 312 + src/BinIR/LowUIR.AST.fs | 1461 ++- src/BinIR/LowUIR.AST.fsi | 293 - src/BinIR/LowUIR.ASTHelper.fs | 147 + src/BinIR/LowUIR.Pp.fs | 132 +- src/BinIR/LowUIR.TypeCheck.fs | 120 + src/BinIR/LowUIR.fs | 261 - src/BinIR/README.md | 12 + src/BinIR/RelOpType.fs | 17 + src/BinIR/SSA.AST.fs | 40 +- src/BinIR/SSA.Pp.fs | 12 +- src/BinIR/SSA.fs | 27 +- src/BinIR/SideEffect.fs | 26 +- src/BinIR/Stmt.fs | 251 + src/BinIR/UnOpType.fs | 10 + src/BinIR/Utils.fs | 15 - src/ConcEval/B2R2.ConcEval.fsproj | 20 - src/ConcEval/EvalState.fs | 220 - src/ConcEval/Evaluator.fs | 217 - src/ConcEval/Variables.fs | 43 - src/Core.Tests/AddrRange.Tests.fs | 42 +- src/Core.Tests/B2R2.Core.Tests.fsproj | 14 +- src/Core.Tests/BitVector.Tests.fs | 172 +- src/Core.Tests/ByteArray.Tests.fs | 15 +- src/Core.Tests/IntervalTree.Tests.fs | 118 +- ...ncurrentLRU.Tests.fs => LRUCache.Tests.fs} | 68 +- src/Core.Tests/SortedList.Tests.fs | 67 + src/{FrontEnd/Core/Stack.fs => Core/Addr.fs} | 23 +- src/Core/AddrRange.fs | 21 +- src/Core/AddrRange.fsi | 34 +- src/Core/AddrRangeMap.fs | 74 +- src/Core/AddrRangeMap.fsi | 39 +- src/Core/B2R2.Core.fsproj | 34 +- src/Core/BaseRegisterSet.fs | 182 - src/Core/BinReader.fs | 19 +- src/Core/BitVector.fs | 2313 +++-- src/Core/BitVector.fsi | 484 - src/Core/ByteArray.fs | 37 +- src/Core/ByteArray.fsi | 6 + .../Memory.fs => Core/BytePattern.fs} | 68 +- src/Core/ColoredString.fs | 130 + src/Core/ConcurrentWeakReferenceTable.fs | 180 - src/Core/Errors.fs | 82 + src/Core/FileFormat.fs | 5 +- src/Core/FingerTree.fs | 24 +- src/Core/ISA.fs | 68 +- src/Core/IntervalMap.fs | 12 +- src/Core/IntervalSet.fs | 23 +- src/Core/LEB128.fs | 2 +- src/Core/{ConcurrentLRU.fs => LRUCache.fs} | 78 +- src/Core/Logger.fs | 19 +- src/Core/OS.fs | 11 +- src/{BinGraph/Edges.fs => Core/OutString.fs} | 38 +- .../PersistentQueue.fs} | 64 +- src/Core/Printer.fs | 364 + src/Core/ProgramPoint.fs | 17 +- src/Core/README.md | 12 + src/Core/RegType.fs | 35 +- src/Core/RegisterSet.fs | 189 +- src/Core/TypeExtensions.fs | 92 +- src/Core/Utils.fs | 18 +- src/Core/Utils.fsi | 10 +- src/Core/WordSize.fs | 25 +- src/DataFlow.Tests/B2R2.DataFlow.Tests.fsproj | 25 - src/DataFlow.Tests/DataFlow.Tests.fs | 171 - src/DataFlow/B2R2.DataFlow.fsproj | 25 - src/DataFlow/CPState.fs | 159 - src/DataFlow/CPTransfer.fs | 283 - src/DataFlow/CPValue.fs | 175 - src/DataFlow/Chains.fs | 117 - src/DataFlow/ConstantPropagation.fs | 80 - src/DataFlow/DataFlowAnalysis.fs | 123 - src/DataFlow/ReachingDefinitions.fs | 86 - src/FrontEnd.Tests/B2R2.FrontEnd.Tests.fsproj | 32 - src/FrontEnd/ARM64/B2R2.FrontEnd.ARM64.fsproj | 33 - .../B2R2.FrontEnd.BinFile.Tests.fsproj | 22 + .../BinFile.Tests/BinFile.Tests.fs | 28 +- .../BinFile.Tests/ELF/README.md | 0 .../BinFile.Tests/ELF/elf_aarch64_ls.zip | Bin .../ELF/elf_aarch64_ls_stripped.zip | Bin .../BinFile.Tests/ELF/elf_arm32_ls.zip | Bin .../ELF/elf_arm32_ls_stripped.zip | Bin .../ELF/elf_mips32_ls_stripped.zip | Bin .../ELF/elf_mips32_ls_stripped_le.zip | Bin .../ELF/elf_mips64_ls_stripped.zip | Bin .../BinFile.Tests/ELF/elf_thumb_ls.zip | Bin .../ELF/elf_thumb_ls_stripped.zip | Bin .../BinFile.Tests/ELF/elf_x64_ls.zip | Bin .../BinFile.Tests/ELF/elf_x64_ls_stripped.zip | Bin .../BinFile.Tests/ELF/elf_x86_ls.zip | Bin .../BinFile.Tests/ELF/elf_x86_ls_stripped.zip | Bin .../BinFile.Tests/Mach/README.md | 0 .../BinFile.Tests/Mach/mach_x64_wc.zip | Bin .../Mach/mach_x64_wc_stripped.zip | Bin .../Mach/mach_x86_rm_stripped.zip | Bin src/{ => FrontEnd}/BinFile.Tests/PE/README.md | 0 .../BinFile.Tests/PE/pe_x64.zip | Bin .../BinFile.Tests/PE/pe_x64_without_pdb.zip | Bin .../BinFile.Tests/PE/pe_x86.zip | Bin .../BinFile.Tests/PE/pe_x86_without_pdb.zip | Bin .../BinFile.Tests/Wasm/wasm_basic.zip | Bin .../BinFile/B2R2.FrontEnd.BinFile.fsproj} | 30 +- src/FrontEnd/BinFile/BinaryPointer.fs | 73 + src/{ => FrontEnd}/BinFile/ELF.fs | 33 +- src/FrontEnd/BinFile/ELFDwarfTypes.fs | 514 ++ src/FrontEnd/BinFile/ELFExceptionFrames.fs | 715 ++ src/FrontEnd/BinFile/ELFGccExceptTable.fs | 159 + src/{ => FrontEnd}/BinFile/ELFHeader.fs | 20 +- src/{ => FrontEnd}/BinFile/ELFHelper.fs | 75 +- src/FrontEnd/BinFile/ELFPLT.fs | 371 + src/{ => FrontEnd}/BinFile/ELFParser.fs | 118 +- src/{ => FrontEnd}/BinFile/ELFProgHeader.fs | 6 +- src/{ => FrontEnd}/BinFile/ELFRelocs.fs | 4 +- src/{ => FrontEnd}/BinFile/ELFSection.fs | 6 +- src/{ => FrontEnd}/BinFile/ELFSymbol.fs | 47 +- src/{ => FrontEnd}/BinFile/ELFTypes.fs | 83 +- src/{ => FrontEnd}/BinFile/FileHelper.fs | 18 +- src/{ => FrontEnd}/BinFile/FileInfo.fs | 89 +- src/{ => FrontEnd}/BinFile/FileTypes.fs | 29 +- src/{ => FrontEnd}/BinFile/FormatDetector.fs | 68 +- src/{ => FrontEnd}/BinFile/Mach.fs | 24 +- src/{ => FrontEnd}/BinFile/MachFat.fs | 2 +- src/{ => FrontEnd}/BinFile/MachHeader.fs | 4 +- src/{ => FrontEnd}/BinFile/MachHelper.fs | 38 +- .../BinFile/MachLoadCommands.fs | 67 +- src/{ => FrontEnd}/BinFile/MachParser.fs | 15 +- src/{ => FrontEnd}/BinFile/MachReloc.fs | 7 +- src/{ => FrontEnd}/BinFile/MachSection.fs | 6 +- src/{ => FrontEnd}/BinFile/MachSegment.fs | 6 +- src/{ => FrontEnd}/BinFile/MachSymbol.fs | 8 +- src/{ => FrontEnd}/BinFile/MachTypes.fs | 22 +- src/{ => FrontEnd}/BinFile/PE.fs | 26 +- src/{ => FrontEnd}/BinFile/PECoff.fs | 4 +- src/{ => FrontEnd}/BinFile/PEHelper.fs | 123 +- src/{ => FrontEnd}/BinFile/PEPDB.fs | 4 +- src/{ => FrontEnd}/BinFile/PEParser.fs | 54 +- src/{ => FrontEnd}/BinFile/PETypes.fs | 8 +- src/FrontEnd/BinFile/README.md | 12 + src/{ => FrontEnd}/BinFile/RawBinary.fs | 60 +- src/{ => FrontEnd}/BinFile/Wasm.fs | 23 +- src/{ => FrontEnd}/BinFile/WasmExpression.fs | 4 +- src/{ => FrontEnd}/BinFile/WasmHeader.fs | 2 +- src/{ => FrontEnd}/BinFile/WasmHelper.fs | 42 +- src/{ => FrontEnd}/BinFile/WasmParser.fs | 6 +- src/{ => FrontEnd}/BinFile/WasmSection.fs | 6 +- src/{ => FrontEnd}/BinFile/WasmTypes.fs | 4 +- .../B2R2.FrontEnd.BinInterface.fsproj | 37 + src/FrontEnd/BinInterface/BinHandle.fs | 285 + src/FrontEnd/BinInterface/BinHandle.fsi | 630 ++ .../CallingConvention.fs | 127 +- .../CallingConvention.fsi | 21 +- src/FrontEnd/BinInterface/Helper.fs | 229 + src/FrontEnd/BinInterface/README.md | 13 + .../BinLifter.Tests/AVR.Lifter.Tests.fs | 86 + .../BinLifter.Tests/AVR.Parser.Tests.fs | 78 + .../B2R2.FrontEnd.BinLifter.Tests.fsproj | 26 + .../BinLifter.Tests}/Lifter.Tests.fs | 10 +- .../BinLifter.Tests}/Parser.Tests.fs | 71 +- .../BinLifter.Tests}/TMS320.Parser.Tests.fs | 8 +- src/FrontEnd/BinLifter/ARM32/ARM32.fs | 66 + .../{ => BinLifter}/ARM32/ARM32Disasm.fs | 392 +- .../{ => BinLifter}/ARM32/ARM32Exceptions.fs | 2 +- .../{ => BinLifter}/ARM32/ARM32IRHelper.fs | 94 +- .../{ => BinLifter}/ARM32/ARM32Instruction.fs | 94 +- .../{ => BinLifter}/ARM32/ARM32Lifter.fs | 1929 ++-- .../ARM32/ARM32OperandHelper.fs | 67 +- .../{ => BinLifter}/ARM32/ARM32ParseUtils.fs | 10 +- .../{ => BinLifter}/ARM32/ARM32Parser.fs | 30 +- .../{ => BinLifter}/ARM32/ARM32ParserV7.fs | 321 +- .../{ => BinLifter}/ARM32/ARM32ParserV8.fs | 10 +- .../{ => BinLifter}/ARM32/ARM32RegExprs.fs | 135 +- .../{ => BinLifter}/ARM32/ARM32Register.fs | 2 +- .../{ => BinLifter}/ARM32/ARM32RegisterBay.fs | 13 +- .../{ => BinLifter}/ARM32/ARM32RegisterSet.fs | 70 +- .../ARM32/ARM32SupportedOpcode.txt | 0 .../{ => BinLifter}/ARM32/ARM32Types.fs | 4 +- .../B2R2.FrontEnd.BinLifter.ARM32.fsproj} | 21 +- src/FrontEnd/BinLifter/ARM32/README.md | 11 + src/FrontEnd/{ => BinLifter}/ARM64/ARM64.fs | 21 +- .../{ => BinLifter}/ARM64/ARM64Disasm.fs | 308 +- .../{ => BinLifter}/ARM64/ARM64Exceptions.fs | 2 +- .../{ => BinLifter}/ARM64/ARM64Instruction.fs | 88 +- .../{ => BinLifter}/ARM64/ARM64Lifter.fs | 1070 +-- .../ARM64/ARM64OperandHelper.fs | 8 +- .../{ => BinLifter}/ARM64/ARM64Parser.fs | 6 +- .../{ => BinLifter}/ARM64/ARM64Parser.fsi | 2 +- .../{ => BinLifter}/ARM64/ARM64RegExprs.fs | 329 +- .../{ => BinLifter}/ARM64/ARM64Register.fs | 2 +- .../{ => BinLifter}/ARM64/ARM64RegisterBay.fs | 13 +- .../{ => BinLifter}/ARM64/ARM64RegisterSet.fs | 103 +- .../ARM64/ARM64SupportedOpcode.txt | 0 .../{ => BinLifter}/ARM64/ARM64Types.fs | 4 +- .../{ => BinLifter}/ARM64/ARM64Utils.fs | 4 +- .../B2R2.FrontEnd.BinLifter.ARM64.fsproj | 37 + src/FrontEnd/BinLifter/ARM64/README.md | 11 + src/FrontEnd/BinLifter/AVR/AVR.fs | 55 + src/FrontEnd/BinLifter/AVR/AVRDisasm.fs | 244 + .../BinLifter/AVR/AVRGeneralLifter.fs | 942 ++ src/FrontEnd/BinLifter/AVR/AVRInstruction.fs | 107 + src/FrontEnd/BinLifter/AVR/AVRLifter.fs | 115 + .../BinLifter/AVR/AVROperandHelper.fs | 179 + src/FrontEnd/BinLifter/AVR/AVRParser.fs | 299 + src/FrontEnd/BinLifter/AVR/AVRRegExprs.fs | 142 + src/FrontEnd/BinLifter/AVR/AVRRegister.fs | 173 + .../AVR/AVRRegisterBay.fs} | 24 +- src/FrontEnd/BinLifter/AVR/AVRRegisterSet.fs | 151 + src/FrontEnd/BinLifter/AVR/AVRTypes.fs | 319 + .../AVR/B2R2.FrontEnd.BinLifter.AVR.fsproj | 35 + src/FrontEnd/BinLifter/AVR/README.md | 11 + .../CIL/B2R2.FrontEnd.BinLifter.CIL.fsproj | 29 + .../{ARM32/ARM32.fs => BinLifter/CIL/CIL.fs} | 37 +- src/FrontEnd/BinLifter/CIL/CILInstruction.fs | 59 + .../BinLifter/CIL/CILRegExprs.fs} | 24 +- src/FrontEnd/BinLifter/CIL/CILRegisterBay.fs | 76 + .../BinLifter/CIL/CILRegisterSet.fs} | 38 +- .../BinLifter/CIL/CILTypes.fs} | 59 +- src/FrontEnd/BinLifter/CIL/README.md | 11 + src/FrontEnd/{ => BinLifter}/Core/AsmWord.fs | 2 +- .../Core/B2R2.FrontEnd.BinLifter.Core.fsproj | 32 + src/FrontEnd/BinLifter/Core/DisasmHelper.fs | 77 + .../{ => BinLifter}/Core/Exceptions.fs | 2 +- .../Core/IRBuilder.fs} | 28 +- .../{ => BinLifter}/Core/Instruction.fs | 74 +- .../BinLifter/Core/LiftingOperators.fs} | 59 +- .../{ => BinLifter}/Core/ParseUtils.fs | 2 +- src/FrontEnd/{ => BinLifter}/Core/Parser.fs | 9 +- src/FrontEnd/BinLifter/Core/README.md | 11 + .../{ => BinLifter}/Core/RegisterBay.fs | 19 +- .../Core/TranslationContext.fs} | 43 +- .../EVM/B2R2.FrontEnd.BinLifter.EVM.fsproj | 32 + src/FrontEnd/{ => BinLifter}/EVM/EVM.fs | 27 +- src/FrontEnd/BinLifter/EVM/EVMDisasm.fs | 184 + .../{ => BinLifter}/EVM/EVMInstruction.fs | 61 +- src/FrontEnd/{ => BinLifter}/EVM/EVMLifter.fs | 395 +- src/FrontEnd/{ => BinLifter}/EVM/EVMParser.fs | 21 +- .../{ => BinLifter}/EVM/EVMRegExprs.fs | 8 +- src/FrontEnd/BinLifter/EVM/EVMRegisterBay.fs | 76 + .../{ => BinLifter}/EVM/EVMRegisterSet.fs | 34 +- src/FrontEnd/{ => BinLifter}/EVM/EVMTypes.fs | 48 +- src/FrontEnd/BinLifter/EVM/README.md | 11 + .../B2R2.FrontEnd.BinLifter.Intel.fsproj | 44 + src/FrontEnd/{ => BinLifter}/Intel/Intel.fs | 26 +- .../BinLifter/Intel/IntelAVXLifter.fs | 2313 +++++ .../{ => BinLifter}/Intel/IntelDisasm.fs | 391 +- .../BinLifter/Intel/IntelGeneralLifter.fs | 1989 +++++ src/FrontEnd/BinLifter/Intel/IntelHelper.fs | 1098 +++ .../{ => BinLifter}/Intel/IntelInstruction.fs | 129 +- src/FrontEnd/BinLifter/Intel/IntelLifter.fs | 640 ++ .../BinLifter/Intel/IntelLiftingUtils.fs | 376 + .../BinLifter/Intel/IntelMMXLifter.fs | 527 ++ .../Intel/IntelOpcodes.fs} | 1540 ++-- src/FrontEnd/BinLifter/Intel/IntelOperands.fs | 1211 +++ src/FrontEnd/BinLifter/Intel/IntelParser.fs | 542 ++ .../BinLifter/Intel/IntelParsingHelper.fs | 4556 ++++++++++ .../BinLifter/Intel/IntelParsingJob.fs | 2074 +++++ .../{ => BinLifter}/Intel/IntelRegExprs.fs | 1055 ++- .../{ => BinLifter}/Intel/IntelRegister.fs | 975 +- .../BinLifter/Intel/IntelRegisterBay.fs | 430 + .../BinLifter/Intel/IntelRegisterSet.fs | 481 + .../BinLifter/Intel/IntelSSELifter.fs | 1814 ++++ .../Intel/IntelSupportedOpcodes.txt | 176 +- src/FrontEnd/BinLifter/Intel/IntelTypes.fs | 316 + .../BinLifter/Intel/IntelX87Lifter.fs | 1505 ++++ src/FrontEnd/BinLifter/Intel/README.md | 11 + .../MIPS/B2R2.FrontEnd.BinLifter.MIPS.fsproj | 36 + src/FrontEnd/{ => BinLifter}/MIPS/MIPS.fs | 21 +- .../{ => BinLifter}/MIPS/MIPSDisasm.fs | 72 +- .../{ => BinLifter}/MIPS/MIPSHelper.fs | 6 +- .../{ => BinLifter}/MIPS/MIPSInstruction.fs | 67 +- .../{ => BinLifter}/MIPS/MIPSLifter.fs | 886 +- .../{ => BinLifter}/MIPS/MIPSParser.fs | 6 +- .../{ => BinLifter}/MIPS/MIPSParser.fsi | 2 +- .../{ => BinLifter}/MIPS/MIPSRegExprs.fs | 6 +- .../{ => BinLifter}/MIPS/MIPSRegister.fs | 2 +- .../{ => BinLifter}/MIPS/MIPSRegisterBay.fs | 13 +- .../{ => BinLifter}/MIPS/MIPSRegisterSet.fs | 101 +- .../MIPS/MIPSSupportedOpcode.txt | 0 .../{ => BinLifter}/MIPS/MIPSTypes.fs | 4 +- .../{ => BinLifter}/MIPS/MIPSUtils.fs | 2 +- src/FrontEnd/BinLifter/MIPS/README.md | 11 + .../B2R2.FrontEnd.BinLifter.Optimizer.fsproj | 25 + .../BinLifter/Optimizer/ConstantFolding.fs | 240 + .../Optimizer/DeadCodeElimination.fs | 149 + .../BinLifter/Optimizer/LocalOptimizer.fs | 65 + src/FrontEnd/BinLifter/Optimizer/README.md | 12 + ...B2R2.FrontEnd.BinLifter.TMS320C6000.fsproj | 33 + src/FrontEnd/BinLifter/TMS320C6000/README.md | 11 + .../TMS320C6000/TMS320C6000.fs | 24 +- .../TMS320C6000/TMS320C6000Disasm.fs | 122 +- .../TMS320C6000/TMS320C6000Instruction.fs | 57 +- .../TMS320C6000/TMS320C6000Parser.fs | 14 +- .../TMS320C6000/TMS320C6000RegExprs.fs | 4 +- .../TMS320C6000/TMS320C6000Register.fs | 2 +- .../TMS320C6000/TMS320C6000RegisterBay.fs | 7 +- .../TMS320C6000/TMS320C6000RegisterSet.fs | 35 +- .../TMS320C6000/TMS320C6000Types.fs | 4 +- .../TMS320C6000/TMS320C6000Utils.fs | 2 +- src/FrontEnd/Core/B2R2.FrontEnd.Core.fsproj | 28 - src/FrontEnd/Core/DisasmUtils.fs | 34 - src/FrontEnd/EVM/B2R2.FrontEnd.EVM.fsproj | 29 - src/FrontEnd/EVM/EVMDisasm.fs | 198 - src/FrontEnd/EVM/EVMParser.fsi | 40 - src/FrontEnd/Intel/B2R2.FrontEnd.Intel.fsproj | 32 - src/FrontEnd/Intel/IntelConstants.fs | 1095 --- src/FrontEnd/Intel/IntelHelper.fs | 112 - src/FrontEnd/Intel/IntelLifter.fs | 7827 ----------------- src/FrontEnd/Intel/IntelParser.fs | 2528 ------ src/FrontEnd/Intel/IntelParser.fsi | 34 - src/FrontEnd/Intel/IntelRegisterBay.fs | 268 - src/FrontEnd/Intel/IntelRegisterSet.fs | 249 - .../Library/B2R2.FrontEnd.Library.fsproj | 95 - src/FrontEnd/Library/BinHandler.fs | 220 - src/FrontEnd/Library/BinHandler.fsi | 420 - src/FrontEnd/Library/BinHandlerHelper.fs | 115 - src/FrontEnd/MIPS/B2R2.FrontEnd.MIPS.fsproj | 32 - .../B2R2.FrontEnd.NameMangling.Tests.fsproj | 24 + .../NameMangling.Tests/ItaniumTests.fs | 4 +- .../NameMangling.Tests/MSTests.fs | 4 +- .../NameMangling.Tests/TestLib.fs | 10 +- .../B2R2.FrontEnd.NameMangling.fsproj} | 15 +- src/{ => FrontEnd}/NameMangling/Demangle.fs | 31 +- .../NameMangling/DemangleTypes.fs | 17 +- .../NameMangling/ItaniumDemangler.fs} | 24 +- .../NameMangling/ItaniumFunctionPointer.fs | 2 +- .../NameMangling/ItaniumInterpreter.fs | 4 +- .../NameMangling/ItaniumTables.fs | 2 +- .../NameMangling/ItaniumTypes.fs | 5 +- .../NameMangling/ItaniumUtils.fs | 4 +- .../NameMangling/MSDemangler.fs} | 25 +- .../NameMangling/MSInterpreter.fs | 4 +- src/{ => FrontEnd}/NameMangling/MSTypes.fs | 4 +- src/{ => FrontEnd}/NameMangling/MSUtils.fs | 2 +- src/FrontEnd/NameMangling/README.md | 11 + .../Optimizer/B2R2.FrontEnd.Optimizer.fsproj | 19 - src/FrontEnd/Optimizer/ExprWalker.fs | 81 - src/FrontEnd/Optimizer/LocalOptimizer.fs | 233 - .../B2R2.FrontEnd.TMS320C6000.fsproj | 30 - .../TMS320C6000/TMS320C6000Parser.fsi | 35 - src/Lens/B2R2.Lens.fsproj | 23 - src/Lens/CallGraphLens.fs | 133 - src/Lens/DisasmLens.fs | 177 - src/Lens/ILens.fs | 48 - src/Lens/SSABlock.fs | 159 - src/Lens/SSAEdges.fs | 94 - src/Lens/SSALens.fs | 99 - src/Lens/SSATypes.fs | 78 - src/Lens/SSAUtils.fs | 193 - .../B2R2.MiddleEnd.Tests.fsproj | 24 - src/MiddleEnd.Tests/CFG.Tests.fs | 347 - src/MiddleEnd/Analyzer.fs | 43 - src/MiddleEnd/B2R2.MiddleEnd.fsproj | 26 - src/MiddleEnd/BranchRecovery.fs | 407 - src/MiddleEnd/ConditionRetriever.fs | 217 - src/MiddleEnd/EVMCodeCopyAnalysis.fs | 67 - src/MiddleEnd/EmulationHelper.fs | 83 - src/MiddleEnd/IAnalysis.fs | 37 - src/MiddleEnd/LibcAnalysis.fs | 116 - src/MiddleEnd/NoAnalysis.fs | 30 - src/MiddleEnd/NoReturn.fs | 279 - src/MiddleEnd/SpeculativeGapCompletion.fs | 114 - .../B2R2.NameMangling.Tests.fsproj | 25 - src/NameMangling/ItaniumDemangler.fs | 38 - src/NameMangling/MSDemangler.fs | 39 - .../B2R2.Peripheral.Assembly.Tests.fsproj | 30 + .../Assembly.Tests}/Intel.Tests.fs | 8 +- .../Assembly.Tests}/LowUIR.Tests.fs | 31 +- .../Assembly.Tests}/MIPS.Tests.fs | 6 +- .../Assembly}/ARM32/ARM32AsmParser.fs | 6 +- .../Assembly}/ARM32/ARM32ParserHelper.fs | 4 +- .../Assembly}/ARM32/ARM32SecondPass.fs | 6 +- .../B2R2.Peripheral.Assembly.ARM32.fsproj | 24 + src/Peripheral/Assembly/ARM32/README.md | 11 + .../Assembly/AsmInterface/AsmInterface.fs} | 48 +- ...R2.Peripheral.Assembly.AsmInterface.fsproj | 26 + .../Assembly/AsmInterface/README.md | 12 + .../Assembly}/Core/AsmParser.fs | 25 +- .../Core/B2R2.Peripheral.Assembly.Core.fsproj | 27 + src/Peripheral/Assembly/Core/README.md | 12 + .../Assembly/Core/Utils.fs} | 31 +- .../B2R2.Peripheral.Assembly.Intel.fsproj | 29 + .../Assembly}/Intel/IntelAsmMain.fs | 11 +- .../Assembly}/Intel/IntelAsmOpcode.fs | 503 +- .../Assembly}/Intel/IntelAsmOperands.fs | 4 +- .../Assembly}/Intel/IntelAsmParser.fs | 29 +- .../Assembly}/Intel/IntelAsmPrefix.fs | 5 +- .../Assembly}/Intel/IntelAsmTypes.fs | 4 +- .../Assembly}/Intel/IntelParserHelper.fs | 32 +- src/Peripheral/Assembly/Intel/README.md | 11 + .../B2R2.Peripheral.Assembly.LowUIR.fsproj | 30 + .../Assembly/LowUIR/LowUIRParser.fs | 364 + .../Assembly/LowUIR/LowUIRParserHelper.fs} | 16 +- src/Peripheral/Assembly/LowUIR/README.md | 11 + .../MIPS/B2R2.Peripheral.Assembly.MIPS.fsproj | 28 + .../Assembly}/MIPS/MIPSAsmParser.fs | 6 +- .../Assembly}/MIPS/MIPSParserHelper.fs | 4 +- .../Assembly}/MIPS/MIPSSecondPass.fs | 4 +- src/Peripheral/Assembly/MIPS/README.md | 11 + src/ROP/B2R2.ROP.fsproj | 30 - src/ROP/Simplify.fs | 231 - .../Assembler/B2R2.RearEnd.Assembler.fsproj | 26 + .../Assembler/Cmd.fs} | 67 +- src/RearEnd/Assembler/Program.fs | 107 + .../BinDump/B2R2.RearEnd.BinDump.fsproj | 20 + src/RearEnd/BinDump/Cmd.fs | 233 + src/RearEnd/BinDump/DisasmLiftHelper.fs | 247 + src/RearEnd/BinDump/Program.fs | 221 + .../B2R2.RearEnd.BinExplorer.fsproj} | 24 +- .../BinExplorer/BinInfo.fs | 14 +- src/{Utilities => RearEnd}/BinExplorer/CLI.fs | 11 +- .../BinExplorer/CmdSpec.fs | 2 +- .../BinExplorer/CmdTypes.fs | 9 +- .../BinExplorer/CmdUtils.fs | 6 +- .../BinExplorer/Credits.fs | 4 +- .../BinExplorer/Demangle.fs | 12 +- .../BinExplorer/Disasm.fs | 28 +- .../BinExplorer/EvalExpr.fs | 5 +- .../BinExplorer/HTTPServer.fs | 112 +- .../BinExplorer/Help.fs | 6 +- .../BinExplorer/HexDump.fs | 52 +- .../BinExplorer/List.fs | 23 +- .../BinExplorer/Print.fs | 25 +- .../BinExplorer/Program.fs} | 76 +- .../BinExplorer/Protocol.fs | 8 +- src/{Utilities => RearEnd}/BinExplorer/ROP.fs | 12 +- .../BinExplorer/Search.fs | 13 +- .../BinExplorer/Show.fs | 57 +- .../BinExplorer/SimpleArithConverter.fs | 2 +- .../BinExplorer/SimpleArithHelper.fs | 2 +- .../BinExplorer/SimpleArithOperator.fs | 4 +- .../BinExplorer/SimpleArithParser.fs | 4 +- .../BinExplorer/SimpleArithReference.fs | 2 +- .../BinExplorer/SimpleArithTypes.fs | 2 +- .../BinExplorer/WebUI/b2r2.png | Bin .../BinExplorer/WebUI/css/b2r2.base.css | 0 .../BinExplorer/WebUI/css/b2r2.css | 0 .../BinExplorer/WebUI/css/b2r2.footer.css | 0 .../BinExplorer/WebUI/css/b2r2.graph.css | 8 + .../BinExplorer/WebUI/css/b2r2.header.css | 0 .../BinExplorer/WebUI/css/b2r2.main.css | 0 .../BinExplorer/WebUI/css/b2r2.modal.css | 0 .../BinExplorer/WebUI/css/b2r2.rotating.css | 0 .../BinExplorer/WebUI/css/b2r2.toast.css | 0 .../BinExplorer/WebUI/css/bootstrap.min.css | 0 .../BinExplorer/WebUI/css/fontawesome.min.css | 0 .../css/images/ui-icons_444444_256x240.png | Bin .../css/images/ui-icons_555555_256x240.png | Bin .../css/images/ui-icons_777620_256x240.png | Bin .../css/images/ui-icons_777777_256x240.png | Bin .../css/images/ui-icons_cc0000_256x240.png | Bin .../css/images/ui-icons_ffffff_256x240.png | Bin .../BinExplorer/WebUI/css/jquery-ui.min.css | 0 .../WebUI/css/jquery.contextMenu.min.css | 0 .../BinExplorer/WebUI/favicon.ico | Bin .../WebUI/fonts/Inconsolata-Bold.ttf | Bin .../WebUI/fonts/Inconsolata-Regular.ttf | Bin .../WebUI/fonts/context-menu-icons.woff2 | Bin .../WebUI/fonts/fa-brands-400.woff2 | Bin .../WebUI/fonts/fa-regular-400.woff2 | Bin .../WebUI/fonts/fa-solid-900.woff2 | Bin .../fonts/glyphicons-halflings-regular.eot | Bin .../fonts/glyphicons-halflings-regular.svg | 0 .../fonts/glyphicons-halflings-regular.ttf | Bin .../fonts/glyphicons-halflings-regular.woff | Bin .../fonts/glyphicons-halflings-regular.woff2 | Bin .../BinExplorer/WebUI/index.html | 0 .../BinExplorer/WebUI/js/b2r2.consts.js | 0 .../BinExplorer/WebUI/js/b2r2.flowgraph.js | 6 +- .../BinExplorer/WebUI/js/b2r2.graph.js | 0 .../BinExplorer/WebUI/js/b2r2.header.js | 0 .../BinExplorer/WebUI/js/b2r2.hexgraph.js | 0 .../BinExplorer/WebUI/js/b2r2.js | 0 .../BinExplorer/WebUI/js/b2r2.keyhandler.js | 0 .../BinExplorer/WebUI/js/b2r2.minimap.js | 0 .../BinExplorer/WebUI/js/b2r2.navbar.js | 0 .../BinExplorer/WebUI/js/b2r2.search.js | 0 .../BinExplorer/WebUI/js/b2r2.side.js | 0 .../BinExplorer/WebUI/js/b2r2.svgdefs.js | 1 + .../BinExplorer/WebUI/js/b2r2.termgraph.js | 0 .../BinExplorer/WebUI/js/b2r2.toast.js | 0 .../BinExplorer/WebUI/js/b2r2.utils.js | 0 .../BinExplorer/WebUI/js/b2r2.window.js | 0 .../BinExplorer/WebUI/js/bootstrap.min.js | 0 .../BinExplorer/WebUI/js/d3.min.js | 0 .../BinExplorer/WebUI/js/jquery-ui.min.js | 0 .../WebUI/js/jquery.contextMenu.min.js | 0 .../BinExplorer/WebUI/js/jquery.mark.min.js | 0 .../BinExplorer/WebUI/js/jquery.min.js | 0 .../Core/B2R2.RearEnd.Core.fsproj} | 8 +- src/RearEnd/Core/CmdOpts.fs | 123 + src/RearEnd/Core/HexDumper.fs | 75 + .../FileViewer/B2R2.RearEnd.FileViewer.fsproj | 24 + src/RearEnd/FileViewer/Cmd.fs | 272 + .../FileViewer/DisplayItem.fs} | 83 +- src/RearEnd/FileViewer/ELFViewer.fs | 323 + .../FileViewer/Helper.fs} | 36 +- src/RearEnd/FileViewer/MachViewer.fs | 386 + src/RearEnd/FileViewer/PEViewer.fs | 509 ++ src/RearEnd/FileViewer/Program.fs | 232 + .../Launcher/B2R2.RearEnd.Launcher.fsproj | 31 + src/RearEnd/Launcher/Program.fs | 115 + src/RearEnd/Launcher/README.md | 12 + src/RearEnd/ROP/B2R2.RearEnd.ROP.fsproj | 23 + src/{ => RearEnd}/ROP/Chain.fs | 19 +- src/{ => RearEnd}/ROP/Gadget.fs | 7 +- src/{ => RearEnd}/ROP/Galileo.fs | 18 +- src/{ => RearEnd}/ROP/ROPPayload.fs | 2 +- src/{ => RearEnd}/ROP/ROPValue.fs | 6 +- src/RearEnd/ROP/Simplify.fs | 234 + src/{ => RearEnd}/ROP/State.fs | 77 +- src/{ => RearEnd}/ROP/Summary.fs | 114 +- src/RearEnd/Repl/B2R2.RearEnd.Repl.fsproj | 28 + .../Repl/Main.fs => RearEnd/Repl/Program.fs} | 22 +- .../Repl/ReplCommand.fs | 2 +- .../Repl/ReplDisplay.fs | 2 +- src/{Utilities => RearEnd}/Repl/ReplOpts.fs | 4 +- src/{Utilities => RearEnd}/Repl/ReplState.fs | 38 +- .../B2R2.RearEnd.Visualization.fsproj} | 12 +- .../Visualization/CoordAssignment.fs | 4 +- .../Visualization/CrossMinimization.fs | 4 +- .../Visualization/CycleRemoval.fs | 29 +- src/RearEnd/Visualization/EdgeDrawing.fs | 604 ++ src/{ => RearEnd}/Visualization/JSONExport.fs | 8 +- src/RearEnd/Visualization/LayerAssignment.fs | 98 + src/{ => RearEnd}/Visualization/VisBBlock.fs | 4 +- src/{ => RearEnd}/Visualization/VisDebug.fs | 4 +- src/{ => RearEnd}/Visualization/VisEdge.fs | 4 +- src/{ => RearEnd}/Visualization/VisGraph.fs | 6 +- .../Visualization/VisPosition.fs | 2 +- src/{ => RearEnd}/Visualization/Visualizer.fs | 2 +- .../Assembler/B2R2.Utilities.Assembler.fsproj | 26 - src/Utilities/Assembler/Main.fs | 133 - .../BinDump/B2R2.Utilities.BinDump.fsproj | 21 - src/Utilities/BinDump/Main.fs | 338 - src/Utilities/Core/Utilities.fs | 93 - .../B2R2.Utilities.FileViewer.fsproj | 23 - src/Utilities/FileViewer/Main.fs | 146 - src/Utilities/Repl/B2R2.Utilities.Repl.fsproj | 35 - src/Visualization/EdgeDrawing.fs | 227 - src/Visualization/LayerAssignment.fs | 166 - 603 files changed, 46290 insertions(+), 36383 deletions(-) create mode 100644 .b2r2-ci.json create mode 100644 .config/dotnet-tools.json rename {src/FrontEnd/Library => assets}/b2r2-240x240.png (100%) delete mode 100644 lib/libfpu/.gitignore delete mode 100644 lib/libfpu/Makefile delete mode 100644 lib/libfpu/fpu.c delete mode 100644 samples/Python/b2r2.py create mode 100644 samples/VB/B2R2.vbproj create mode 100644 samples/VB/Program.vb delete mode 100644 src/Assembler.Tests/B2R2.Assembler.Tests.fsproj delete mode 100644 src/Assembler/ARM32/B2R2.Assembler.ARM32.fsproj delete mode 100644 src/Assembler/Core/B2R2.Assembler.Core.fsproj delete mode 100644 src/Assembler/Intel/B2R2.Assembler.Intel.fsproj delete mode 100644 src/Assembler/Interface/B2R2.Assembler.Interface.fsproj delete mode 100644 src/Assembler/LowUIR/B2R2.Assembler.LowUIR.fsproj delete mode 100644 src/Assembler/LowUIR/LowUIRParser.fs delete mode 100644 src/Assembler/LowUIR/LowUIRParserUtils.fs delete mode 100644 src/Assembler/MIPS/B2R2.Assembler.MIPS.fsproj delete mode 100644 src/BinEssence/B2R2.BinEssence.fsproj delete mode 100644 src/BinEssence/BBLInfo.fs delete mode 100644 src/BinEssence/BasicBlock.fs delete mode 100644 src/BinEssence/BinEssence.fs delete mode 100644 src/BinEssence/CFGEdgeKind.fs delete mode 100644 src/BinEssence/CFGElement.fs delete mode 100644 src/BinEssence/CFGExport.fs delete mode 100644 src/BinEssence/CalleeMap.fs delete mode 100644 src/BinEssence/IRBasicBlock.fs delete mode 100644 src/BinEssence/InstrMap.fs delete mode 100644 src/BinEssence/InstructionInfo.fs delete mode 100644 src/BinFile.Tests/B2R2.BinFile.Tests.fsproj delete mode 100644 src/BinFile/ELFDwarfTypes.fs delete mode 100644 src/BinFile/ELFExceptionFrames.fs delete mode 100644 src/BinGraph.Tests/B2R2.BinGraph.Tests.fsproj delete mode 100644 src/BinGraph.Tests/ImperativeGraph.Tests.fs delete mode 100644 src/BinGraph.Tests/PersistentGraph.Tests.fs delete mode 100644 src/BinGraph/B2R2.BinGraph.fsproj delete mode 100644 src/BinGraph/DiGraph.fs delete mode 100644 src/BinGraph/DiGraph.fsi delete mode 100644 src/BinGraph/Dominator.fs delete mode 100644 src/BinGraph/Dominator.fsi delete mode 100644 src/BinGraph/DummyVertex.fs delete mode 100644 src/BinGraph/Graph.fs delete mode 100644 src/BinGraph/GraphCore.fs delete mode 100644 src/BinGraph/Imperative.fs delete mode 100644 src/BinGraph/Persistent.fs delete mode 100644 src/BinGraph/RangedDiGraph.fs delete mode 100644 src/BinGraph/SCC.fs delete mode 100644 src/BinGraph/Traversal.fs delete mode 100644 src/BinGraph/Vertices.fs create mode 100644 src/BinIR.Tests/B2R2.BinIR.Tests.fsproj create mode 100644 src/BinIR.Tests/Program.fs create mode 100644 src/BinIR.Tests/Tests.fs create mode 100644 src/BinIR/Expr.fs delete mode 100644 src/BinIR/LowUIR.AST.fsi create mode 100644 src/BinIR/LowUIR.ASTHelper.fs create mode 100644 src/BinIR/LowUIR.TypeCheck.fs delete mode 100644 src/BinIR/LowUIR.fs create mode 100644 src/BinIR/README.md create mode 100644 src/BinIR/Stmt.fs delete mode 100644 src/ConcEval/B2R2.ConcEval.fsproj delete mode 100644 src/ConcEval/EvalState.fs delete mode 100644 src/ConcEval/Evaluator.fs delete mode 100644 src/ConcEval/Variables.fs rename src/Core.Tests/{ConcurrentLRU.Tests.fs => LRUCache.Tests.fs} (54%) create mode 100644 src/Core.Tests/SortedList.Tests.fs rename src/{FrontEnd/Core/Stack.fs => Core/Addr.fs} (75%) delete mode 100644 src/Core/BaseRegisterSet.fs delete mode 100644 src/Core/BitVector.fsi rename src/{ConcEval/Memory.fs => Core/BytePattern.fs} (50%) create mode 100644 src/Core/ColoredString.fs delete mode 100644 src/Core/ConcurrentWeakReferenceTable.fs create mode 100644 src/Core/Errors.fs rename src/Core/{ConcurrentLRU.fs => LRUCache.fs} (52%) rename src/{BinGraph/Edges.fs => Core/OutString.fs} (64%) rename src/{BinEssence/ControlFlowGraph.fs => Core/PersistentQueue.fs} (53%) create mode 100644 src/Core/Printer.fs create mode 100644 src/Core/README.md delete mode 100644 src/DataFlow.Tests/B2R2.DataFlow.Tests.fsproj delete mode 100644 src/DataFlow.Tests/DataFlow.Tests.fs delete mode 100644 src/DataFlow/B2R2.DataFlow.fsproj delete mode 100644 src/DataFlow/CPState.fs delete mode 100644 src/DataFlow/CPTransfer.fs delete mode 100644 src/DataFlow/CPValue.fs delete mode 100644 src/DataFlow/Chains.fs delete mode 100644 src/DataFlow/ConstantPropagation.fs delete mode 100644 src/DataFlow/DataFlowAnalysis.fs delete mode 100644 src/DataFlow/ReachingDefinitions.fs delete mode 100644 src/FrontEnd.Tests/B2R2.FrontEnd.Tests.fsproj delete mode 100644 src/FrontEnd/ARM64/B2R2.FrontEnd.ARM64.fsproj create mode 100644 src/FrontEnd/BinFile.Tests/B2R2.FrontEnd.BinFile.Tests.fsproj rename src/{ => FrontEnd}/BinFile.Tests/BinFile.Tests.fs (97%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/README.md (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_aarch64_ls.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_aarch64_ls_stripped.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_arm32_ls.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_arm32_ls_stripped.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_mips32_ls_stripped.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_mips32_ls_stripped_le.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_mips64_ls_stripped.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_thumb_ls.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_thumb_ls_stripped.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_x64_ls.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_x64_ls_stripped.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_x86_ls.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/ELF/elf_x86_ls_stripped.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/Mach/README.md (100%) rename src/{ => FrontEnd}/BinFile.Tests/Mach/mach_x64_wc.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/Mach/mach_x64_wc_stripped.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/Mach/mach_x86_rm_stripped.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/PE/README.md (100%) rename src/{ => FrontEnd}/BinFile.Tests/PE/pe_x64.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/PE/pe_x64_without_pdb.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/PE/pe_x86.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/PE/pe_x86_without_pdb.zip (100%) rename src/{ => FrontEnd}/BinFile.Tests/Wasm/wasm_basic.zip (100%) rename src/{BinFile/B2R2.BinFile.fsproj => FrontEnd/BinFile/B2R2.FrontEnd.BinFile.fsproj} (60%) create mode 100644 src/FrontEnd/BinFile/BinaryPointer.fs rename src/{ => FrontEnd}/BinFile/ELF.fs (73%) create mode 100644 src/FrontEnd/BinFile/ELFDwarfTypes.fs create mode 100644 src/FrontEnd/BinFile/ELFExceptionFrames.fs create mode 100644 src/FrontEnd/BinFile/ELFGccExceptTable.fs rename src/{ => FrontEnd}/BinFile/ELFHeader.fs (88%) rename src/{ => FrontEnd}/BinFile/ELFHelper.fs (77%) create mode 100644 src/FrontEnd/BinFile/ELFPLT.fs rename src/{ => FrontEnd}/BinFile/ELFParser.fs (55%) rename src/{ => FrontEnd}/BinFile/ELFProgHeader.fs (96%) rename src/{ => FrontEnd}/BinFile/ELFRelocs.fs (97%) rename src/{ => FrontEnd}/BinFile/ELFSection.fs (97%) rename src/{ => FrontEnd}/BinFile/ELFSymbol.fs (86%) rename src/{ => FrontEnd}/BinFile/ELFTypes.fs (92%) rename src/{ => FrontEnd}/BinFile/FileHelper.fs (80%) rename src/{ => FrontEnd}/BinFile/FileInfo.fs (81%) rename src/{ => FrontEnd}/BinFile/FileTypes.fs (89%) rename src/{ => FrontEnd}/BinFile/FormatDetector.fs (50%) rename src/{ => FrontEnd}/BinFile/Mach.fs (80%) rename src/{ => FrontEnd}/BinFile/MachFat.fs (97%) rename src/{ => FrontEnd}/BinFile/MachHeader.fs (97%) rename src/{ => FrontEnd}/BinFile/MachHelper.fs (87%) rename src/{ => FrontEnd}/BinFile/MachLoadCommands.fs (70%) rename src/{ => FrontEnd}/BinFile/MachParser.fs (90%) rename src/{ => FrontEnd}/BinFile/MachReloc.fs (94%) rename src/{ => FrontEnd}/BinFile/MachSection.fs (95%) rename src/{ => FrontEnd}/BinFile/MachSegment.fs (91%) rename src/{ => FrontEnd}/BinFile/MachSymbol.fs (98%) rename src/{ => FrontEnd}/BinFile/MachTypes.fs (98%) rename src/{ => FrontEnd}/BinFile/PE.fs (79%) rename src/{ => FrontEnd}/BinFile/PECoff.fs (98%) rename src/{ => FrontEnd}/BinFile/PEHelper.fs (76%) rename src/{ => FrontEnd}/BinFile/PEPDB.fs (99%) rename src/{ => FrontEnd}/BinFile/PEParser.fs (87%) rename src/{ => FrontEnd}/BinFile/PETypes.fs (96%) create mode 100644 src/FrontEnd/BinFile/README.md rename src/{ => FrontEnd}/BinFile/RawBinary.fs (68%) rename src/{ => FrontEnd}/BinFile/Wasm.fs (79%) rename src/{ => FrontEnd}/BinFile/WasmExpression.fs (95%) rename src/{ => FrontEnd}/BinFile/WasmHeader.fs (96%) rename src/{ => FrontEnd}/BinFile/WasmHelper.fs (84%) rename src/{ => FrontEnd}/BinFile/WasmParser.fs (98%) rename src/{ => FrontEnd}/BinFile/WasmSection.fs (98%) rename src/{ => FrontEnd}/BinFile/WasmTypes.fs (98%) create mode 100644 src/FrontEnd/BinInterface/B2R2.FrontEnd.BinInterface.fsproj create mode 100644 src/FrontEnd/BinInterface/BinHandle.fs create mode 100644 src/FrontEnd/BinInterface/BinHandle.fsi rename src/FrontEnd/{Library => BinInterface}/CallingConvention.fs (70%) rename src/FrontEnd/{Library => BinInterface}/CallingConvention.fsi (69%) create mode 100644 src/FrontEnd/BinInterface/Helper.fs create mode 100644 src/FrontEnd/BinInterface/README.md create mode 100644 src/FrontEnd/BinLifter.Tests/AVR.Lifter.Tests.fs create mode 100644 src/FrontEnd/BinLifter.Tests/AVR.Parser.Tests.fs create mode 100644 src/FrontEnd/BinLifter.Tests/B2R2.FrontEnd.BinLifter.Tests.fsproj rename src/{FrontEnd.Tests => FrontEnd/BinLifter.Tests}/Lifter.Tests.fs (88%) rename src/{FrontEnd.Tests => FrontEnd/BinLifter.Tests}/Parser.Tests.fs (99%) rename src/{FrontEnd.Tests => FrontEnd/BinLifter.Tests}/TMS320.Parser.Tests.fs (96%) create mode 100644 src/FrontEnd/BinLifter/ARM32/ARM32.fs rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32Disasm.fs (65%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32Exceptions.fs (97%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32IRHelper.fs (63%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32Instruction.fs (67%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32Lifter.fs (72%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32OperandHelper.fs (98%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32ParseUtils.fs (93%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32Parser.fs (76%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32ParserV7.fs (94%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32ParserV8.fs (99%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32RegExprs.fs (79%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32Register.fs (99%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32RegisterBay.fs (96%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32RegisterSet.fs (64%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32SupportedOpcode.txt (100%) rename src/FrontEnd/{ => BinLifter}/ARM32/ARM32Types.fs (99%) rename src/FrontEnd/{ARM32/B2R2.FrontEnd.ARM32.fsproj => BinLifter/ARM32/B2R2.FrontEnd.BinLifter.ARM32.fsproj} (52%) create mode 100644 src/FrontEnd/BinLifter/ARM32/README.md rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64.fs (76%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64Disasm.fs (72%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64Exceptions.fs (97%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64Instruction.fs (63%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64Lifter.fs (61%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64OperandHelper.fs (99%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64Parser.fs (99%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64Parser.fsi (97%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64RegExprs.fs (78%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64Register.fs (99%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64RegisterBay.fs (97%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64RegisterSet.fs (61%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64SupportedOpcode.txt (100%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64Types.fs (99%) rename src/FrontEnd/{ => BinLifter}/ARM64/ARM64Utils.fs (99%) create mode 100644 src/FrontEnd/BinLifter/ARM64/B2R2.FrontEnd.BinLifter.ARM64.fsproj create mode 100644 src/FrontEnd/BinLifter/ARM64/README.md create mode 100644 src/FrontEnd/BinLifter/AVR/AVR.fs create mode 100644 src/FrontEnd/BinLifter/AVR/AVRDisasm.fs create mode 100644 src/FrontEnd/BinLifter/AVR/AVRGeneralLifter.fs create mode 100644 src/FrontEnd/BinLifter/AVR/AVRInstruction.fs create mode 100644 src/FrontEnd/BinLifter/AVR/AVRLifter.fs create mode 100644 src/FrontEnd/BinLifter/AVR/AVROperandHelper.fs create mode 100644 src/FrontEnd/BinLifter/AVR/AVRParser.fs create mode 100644 src/FrontEnd/BinLifter/AVR/AVRRegExprs.fs create mode 100644 src/FrontEnd/BinLifter/AVR/AVRRegister.fs rename src/FrontEnd/{EVM/EVMRegisterBay.fs => BinLifter/AVR/AVRRegisterBay.fs} (78%) create mode 100644 src/FrontEnd/BinLifter/AVR/AVRRegisterSet.fs create mode 100644 src/FrontEnd/BinLifter/AVR/AVRTypes.fs create mode 100644 src/FrontEnd/BinLifter/AVR/B2R2.FrontEnd.BinLifter.AVR.fsproj create mode 100644 src/FrontEnd/BinLifter/AVR/README.md create mode 100644 src/FrontEnd/BinLifter/CIL/B2R2.FrontEnd.BinLifter.CIL.fsproj rename src/FrontEnd/{ARM32/ARM32.fs => BinLifter/CIL/CIL.fs} (67%) create mode 100644 src/FrontEnd/BinLifter/CIL/CILInstruction.fs rename src/{ConcEval/Labels.fs => FrontEnd/BinLifter/CIL/CILRegExprs.fs} (71%) create mode 100644 src/FrontEnd/BinLifter/CIL/CILRegisterBay.fs rename src/{BinEssence/VisualBlock.fs => FrontEnd/BinLifter/CIL/CILRegisterSet.fs} (60%) rename src/{Core/RegisterSet.fsi => FrontEnd/BinLifter/CIL/CILTypes.fs} (57%) create mode 100644 src/FrontEnd/BinLifter/CIL/README.md rename src/FrontEnd/{ => BinLifter}/Core/AsmWord.fs (98%) create mode 100644 src/FrontEnd/BinLifter/Core/B2R2.FrontEnd.BinLifter.Core.fsproj create mode 100644 src/FrontEnd/BinLifter/Core/DisasmHelper.fs rename src/FrontEnd/{ => BinLifter}/Core/Exceptions.fs (98%) rename src/FrontEnd/{Core/StmtBuilder.fs => BinLifter/Core/IRBuilder.fs} (73%) rename src/FrontEnd/{ => BinLifter}/Core/Instruction.fs (83%) rename src/{DataFlow/Utils.fs => FrontEnd/BinLifter/Core/LiftingOperators.fs} (51%) rename src/FrontEnd/{ => BinLifter}/Core/ParseUtils.fs (97%) rename src/FrontEnd/{ => BinLifter}/Core/Parser.fs (86%) create mode 100644 src/FrontEnd/BinLifter/Core/README.md rename src/FrontEnd/{ => BinLifter}/Core/RegisterBay.fs (86%) rename src/FrontEnd/{Core/Context.fs => BinLifter/Core/TranslationContext.fs} (56%) create mode 100644 src/FrontEnd/BinLifter/EVM/B2R2.FrontEnd.BinLifter.EVM.fsproj rename src/FrontEnd/{ => BinLifter}/EVM/EVM.fs (70%) create mode 100644 src/FrontEnd/BinLifter/EVM/EVMDisasm.fs rename src/FrontEnd/{ => BinLifter}/EVM/EVMInstruction.fs (73%) rename src/FrontEnd/{ => BinLifter}/EVM/EVMLifter.fs (53%) rename src/FrontEnd/{ => BinLifter}/EVM/EVMParser.fs (91%) rename src/FrontEnd/{ => BinLifter}/EVM/EVMRegExprs.fs (89%) create mode 100644 src/FrontEnd/BinLifter/EVM/EVMRegisterBay.fs rename src/FrontEnd/{ => BinLifter}/EVM/EVMRegisterSet.fs (71%) rename src/FrontEnd/{ => BinLifter}/EVM/EVMTypes.fs (93%) create mode 100644 src/FrontEnd/BinLifter/EVM/README.md create mode 100644 src/FrontEnd/BinLifter/Intel/B2R2.FrontEnd.BinLifter.Intel.fsproj rename src/FrontEnd/{ => BinLifter}/Intel/Intel.fs (73%) create mode 100644 src/FrontEnd/BinLifter/Intel/IntelAVXLifter.fs rename src/FrontEnd/{ => BinLifter}/Intel/IntelDisasm.fs (72%) create mode 100644 src/FrontEnd/BinLifter/Intel/IntelGeneralLifter.fs create mode 100644 src/FrontEnd/BinLifter/Intel/IntelHelper.fs rename src/FrontEnd/{ => BinLifter}/Intel/IntelInstruction.fs (61%) create mode 100644 src/FrontEnd/BinLifter/Intel/IntelLifter.fs create mode 100644 src/FrontEnd/BinLifter/Intel/IntelLiftingUtils.fs create mode 100644 src/FrontEnd/BinLifter/Intel/IntelMMXLifter.fs rename src/FrontEnd/{Intel/IntelTypes.fs => BinLifter/Intel/IntelOpcodes.fs} (74%) create mode 100644 src/FrontEnd/BinLifter/Intel/IntelOperands.fs create mode 100644 src/FrontEnd/BinLifter/Intel/IntelParser.fs create mode 100644 src/FrontEnd/BinLifter/Intel/IntelParsingHelper.fs create mode 100644 src/FrontEnd/BinLifter/Intel/IntelParsingJob.fs rename src/FrontEnd/{ => BinLifter}/Intel/IntelRegExprs.fs (66%) rename src/FrontEnd/{ => BinLifter}/Intel/IntelRegister.fs (80%) create mode 100644 src/FrontEnd/BinLifter/Intel/IntelRegisterBay.fs create mode 100644 src/FrontEnd/BinLifter/Intel/IntelRegisterSet.fs create mode 100644 src/FrontEnd/BinLifter/Intel/IntelSSELifter.fs rename src/FrontEnd/{ => BinLifter}/Intel/IntelSupportedOpcodes.txt (93%) create mode 100644 src/FrontEnd/BinLifter/Intel/IntelTypes.fs create mode 100644 src/FrontEnd/BinLifter/Intel/IntelX87Lifter.fs create mode 100644 src/FrontEnd/BinLifter/Intel/README.md create mode 100644 src/FrontEnd/BinLifter/MIPS/B2R2.FrontEnd.BinLifter.MIPS.fsproj rename src/FrontEnd/{ => BinLifter}/MIPS/MIPS.fs (75%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSDisasm.fs (75%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSHelper.fs (98%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSInstruction.fs (69%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSLifter.fs (61%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSParser.fs (99%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSParser.fsi (97%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSRegExprs.fs (98%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSRegister.fs (99%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSRegisterBay.fs (95%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSRegisterSet.fs (60%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSSupportedOpcode.txt (100%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSTypes.fs (98%) rename src/FrontEnd/{ => BinLifter}/MIPS/MIPSUtils.fs (97%) create mode 100644 src/FrontEnd/BinLifter/MIPS/README.md create mode 100644 src/FrontEnd/BinLifter/Optimizer/B2R2.FrontEnd.BinLifter.Optimizer.fsproj create mode 100644 src/FrontEnd/BinLifter/Optimizer/ConstantFolding.fs create mode 100644 src/FrontEnd/BinLifter/Optimizer/DeadCodeElimination.fs create mode 100644 src/FrontEnd/BinLifter/Optimizer/LocalOptimizer.fs create mode 100644 src/FrontEnd/BinLifter/Optimizer/README.md create mode 100644 src/FrontEnd/BinLifter/TMS320C6000/B2R2.FrontEnd.BinLifter.TMS320C6000.fsproj create mode 100644 src/FrontEnd/BinLifter/TMS320C6000/README.md rename src/FrontEnd/{ => BinLifter}/TMS320C6000/TMS320C6000.fs (71%) rename src/FrontEnd/{ => BinLifter}/TMS320C6000/TMS320C6000Disasm.fs (72%) rename src/FrontEnd/{ => BinLifter}/TMS320C6000/TMS320C6000Instruction.fs (66%) rename src/FrontEnd/{ => BinLifter}/TMS320C6000/TMS320C6000Parser.fs (99%) rename src/FrontEnd/{ => BinLifter}/TMS320C6000/TMS320C6000RegExprs.fs (92%) rename src/FrontEnd/{ => BinLifter}/TMS320C6000/TMS320C6000Register.fs (99%) rename src/FrontEnd/{ => BinLifter}/TMS320C6000/TMS320C6000RegisterBay.fs (93%) rename src/FrontEnd/{ => BinLifter}/TMS320C6000/TMS320C6000RegisterSet.fs (70%) rename src/FrontEnd/{ => BinLifter}/TMS320C6000/TMS320C6000Types.fs (98%) rename src/FrontEnd/{ => BinLifter}/TMS320C6000/TMS320C6000Utils.fs (95%) delete mode 100644 src/FrontEnd/Core/B2R2.FrontEnd.Core.fsproj delete mode 100644 src/FrontEnd/Core/DisasmUtils.fs delete mode 100644 src/FrontEnd/EVM/B2R2.FrontEnd.EVM.fsproj delete mode 100644 src/FrontEnd/EVM/EVMDisasm.fs delete mode 100644 src/FrontEnd/EVM/EVMParser.fsi delete mode 100644 src/FrontEnd/Intel/B2R2.FrontEnd.Intel.fsproj delete mode 100644 src/FrontEnd/Intel/IntelConstants.fs delete mode 100644 src/FrontEnd/Intel/IntelHelper.fs delete mode 100644 src/FrontEnd/Intel/IntelLifter.fs delete mode 100644 src/FrontEnd/Intel/IntelParser.fs delete mode 100644 src/FrontEnd/Intel/IntelParser.fsi delete mode 100644 src/FrontEnd/Intel/IntelRegisterBay.fs delete mode 100644 src/FrontEnd/Intel/IntelRegisterSet.fs delete mode 100644 src/FrontEnd/Library/B2R2.FrontEnd.Library.fsproj delete mode 100644 src/FrontEnd/Library/BinHandler.fs delete mode 100644 src/FrontEnd/Library/BinHandler.fsi delete mode 100644 src/FrontEnd/Library/BinHandlerHelper.fs delete mode 100644 src/FrontEnd/MIPS/B2R2.FrontEnd.MIPS.fsproj create mode 100644 src/FrontEnd/NameMangling.Tests/B2R2.FrontEnd.NameMangling.Tests.fsproj rename src/{ => FrontEnd}/NameMangling.Tests/ItaniumTests.fs (99%) rename src/{ => FrontEnd}/NameMangling.Tests/MSTests.fs (99%) rename src/{ => FrontEnd}/NameMangling.Tests/TestLib.fs (84%) rename src/{NameMangling/B2R2.NameMangling.fsproj => FrontEnd/NameMangling/B2R2.FrontEnd.NameMangling.fsproj} (52%) rename src/{ => FrontEnd}/NameMangling/Demangle.fs (67%) rename src/{ => FrontEnd}/NameMangling/DemangleTypes.fs (73%) rename src/{NameMangling/ItaniumParser.fs => FrontEnd/NameMangling/ItaniumDemangler.fs} (96%) rename src/{ => FrontEnd}/NameMangling/ItaniumFunctionPointer.fs (99%) rename src/{ => FrontEnd}/NameMangling/ItaniumInterpreter.fs (99%) rename src/{ => FrontEnd}/NameMangling/ItaniumTables.fs (97%) rename src/{ => FrontEnd}/NameMangling/ItaniumTypes.fs (99%) rename src/{ => FrontEnd}/NameMangling/ItaniumUtils.fs (98%) rename src/{NameMangling/MSParser.fs => FrontEnd/NameMangling/MSDemangler.fs} (96%) rename src/{ => FrontEnd}/NameMangling/MSInterpreter.fs (98%) rename src/{ => FrontEnd}/NameMangling/MSTypes.fs (99%) rename src/{ => FrontEnd}/NameMangling/MSUtils.fs (99%) create mode 100644 src/FrontEnd/NameMangling/README.md delete mode 100644 src/FrontEnd/Optimizer/B2R2.FrontEnd.Optimizer.fsproj delete mode 100644 src/FrontEnd/Optimizer/ExprWalker.fs delete mode 100644 src/FrontEnd/Optimizer/LocalOptimizer.fs delete mode 100644 src/FrontEnd/TMS320C6000/B2R2.FrontEnd.TMS320C6000.fsproj delete mode 100644 src/FrontEnd/TMS320C6000/TMS320C6000Parser.fsi delete mode 100644 src/Lens/B2R2.Lens.fsproj delete mode 100644 src/Lens/CallGraphLens.fs delete mode 100644 src/Lens/DisasmLens.fs delete mode 100644 src/Lens/ILens.fs delete mode 100644 src/Lens/SSABlock.fs delete mode 100644 src/Lens/SSAEdges.fs delete mode 100644 src/Lens/SSALens.fs delete mode 100644 src/Lens/SSATypes.fs delete mode 100644 src/Lens/SSAUtils.fs delete mode 100644 src/MiddleEnd.Tests/B2R2.MiddleEnd.Tests.fsproj delete mode 100644 src/MiddleEnd.Tests/CFG.Tests.fs delete mode 100644 src/MiddleEnd/Analyzer.fs delete mode 100644 src/MiddleEnd/B2R2.MiddleEnd.fsproj delete mode 100644 src/MiddleEnd/BranchRecovery.fs delete mode 100644 src/MiddleEnd/ConditionRetriever.fs delete mode 100644 src/MiddleEnd/EVMCodeCopyAnalysis.fs delete mode 100644 src/MiddleEnd/EmulationHelper.fs delete mode 100644 src/MiddleEnd/IAnalysis.fs delete mode 100644 src/MiddleEnd/LibcAnalysis.fs delete mode 100644 src/MiddleEnd/NoAnalysis.fs delete mode 100644 src/MiddleEnd/NoReturn.fs delete mode 100644 src/MiddleEnd/SpeculativeGapCompletion.fs delete mode 100644 src/NameMangling.Tests/B2R2.NameMangling.Tests.fsproj delete mode 100644 src/NameMangling/ItaniumDemangler.fs delete mode 100644 src/NameMangling/MSDemangler.fs create mode 100644 src/Peripheral/Assembly.Tests/B2R2.Peripheral.Assembly.Tests.fsproj rename src/{Assembler.Tests => Peripheral/Assembly.Tests}/Intel.Tests.fs (91%) rename src/{Assembler.Tests => Peripheral/Assembly.Tests}/LowUIR.Tests.fs (70%) rename src/{Assembler.Tests => Peripheral/Assembly.Tests}/MIPS.Tests.fs (96%) rename src/{Assembler => Peripheral/Assembly}/ARM32/ARM32AsmParser.fs (98%) rename src/{Assembler => Peripheral/Assembly}/ARM32/ARM32ParserHelper.fs (98%) rename src/{Assembler => Peripheral/Assembly}/ARM32/ARM32SecondPass.fs (95%) create mode 100644 src/Peripheral/Assembly/ARM32/B2R2.Peripheral.Assembly.ARM32.fsproj create mode 100644 src/Peripheral/Assembly/ARM32/README.md rename src/{Assembler/Interface/Library.fs => Peripheral/Assembly/AsmInterface/AsmInterface.fs} (59%) create mode 100644 src/Peripheral/Assembly/AsmInterface/B2R2.Peripheral.Assembly.AsmInterface.fsproj create mode 100644 src/Peripheral/Assembly/AsmInterface/README.md rename src/{Assembler => Peripheral/Assembly}/Core/AsmParser.fs (64%) create mode 100644 src/Peripheral/Assembly/Core/B2R2.Peripheral.Assembly.Core.fsproj create mode 100644 src/Peripheral/Assembly/Core/README.md rename src/{ConcEval/Types.fs => Peripheral/Assembly/Core/Utils.fs} (69%) create mode 100644 src/Peripheral/Assembly/Intel/B2R2.Peripheral.Assembly.Intel.fsproj rename src/{Assembler => Peripheral/Assembly}/Intel/IntelAsmMain.fs (97%) rename src/{Assembler => Peripheral/Assembly}/Intel/IntelAsmOpcode.fs (88%) rename src/{Assembler => Peripheral/Assembly}/Intel/IntelAsmOperands.fs (98%) rename src/{Assembler => Peripheral/Assembly}/Intel/IntelAsmParser.fs (89%) rename src/{Assembler => Peripheral/Assembly}/Intel/IntelAsmPrefix.fs (98%) rename src/{Assembler => Peripheral/Assembly}/Intel/IntelAsmTypes.fs (98%) rename src/{Assembler => Peripheral/Assembly}/Intel/IntelParserHelper.fs (85%) create mode 100644 src/Peripheral/Assembly/Intel/README.md create mode 100644 src/Peripheral/Assembly/LowUIR/B2R2.Peripheral.Assembly.LowUIR.fsproj create mode 100644 src/Peripheral/Assembly/LowUIR/LowUIRParser.fs rename src/{BinGraph.Tests/Types.fs => Peripheral/Assembly/LowUIR/LowUIRParserHelper.fs} (81%) create mode 100644 src/Peripheral/Assembly/LowUIR/README.md create mode 100644 src/Peripheral/Assembly/MIPS/B2R2.Peripheral.Assembly.MIPS.fsproj rename src/{Assembler => Peripheral/Assembly}/MIPS/MIPSAsmParser.fs (97%) rename src/{Assembler => Peripheral/Assembly}/MIPS/MIPSParserHelper.fs (97%) rename src/{Assembler => Peripheral/Assembly}/MIPS/MIPSSecondPass.fs (96%) create mode 100644 src/Peripheral/Assembly/MIPS/README.md delete mode 100644 src/ROP/B2R2.ROP.fsproj delete mode 100644 src/ROP/Simplify.fs create mode 100644 src/RearEnd/Assembler/B2R2.RearEnd.Assembler.fsproj rename src/{Utilities/FileViewer/CmdOptions.fs => RearEnd/Assembler/Cmd.fs} (53%) create mode 100644 src/RearEnd/Assembler/Program.fs create mode 100644 src/RearEnd/BinDump/B2R2.RearEnd.BinDump.fsproj create mode 100644 src/RearEnd/BinDump/Cmd.fs create mode 100644 src/RearEnd/BinDump/DisasmLiftHelper.fs create mode 100644 src/RearEnd/BinDump/Program.fs rename src/{Utilities/BinExplorer/B2R2.Utilities.BinExplorer.fsproj => RearEnd/BinExplorer/B2R2.RearEnd.BinExplorer.fsproj} (59%) rename src/{Utilities => RearEnd}/BinExplorer/BinInfo.fs (89%) rename src/{Utilities => RearEnd}/BinExplorer/CLI.fs (89%) rename src/{Utilities => RearEnd}/BinExplorer/CmdSpec.fs (97%) rename src/{Utilities => RearEnd}/BinExplorer/CmdTypes.fs (95%) rename src/{Utilities => RearEnd}/BinExplorer/CmdUtils.fs (91%) rename src/{Utilities => RearEnd}/BinExplorer/Credits.fs (94%) rename src/{Utilities => RearEnd}/BinExplorer/Demangle.fs (87%) rename src/{Utilities => RearEnd}/BinExplorer/Disasm.fs (78%) rename src/{Utilities => RearEnd}/BinExplorer/EvalExpr.fs (98%) rename src/{Utilities => RearEnd}/BinExplorer/HTTPServer.fs (71%) rename src/{Utilities => RearEnd}/BinExplorer/Help.fs (97%) rename src/{Utilities => RearEnd}/BinExplorer/HexDump.fs (65%) rename src/{Utilities => RearEnd}/BinExplorer/List.fs (85%) rename src/{Utilities => RearEnd}/BinExplorer/Print.fs (89%) rename src/{Utilities/BinExplorer/Main.fs => RearEnd/BinExplorer/Program.fs} (82%) rename src/{Utilities => RearEnd}/BinExplorer/Protocol.fs (95%) rename src/{Utilities => RearEnd}/BinExplorer/ROP.fs (93%) rename src/{Utilities => RearEnd}/BinExplorer/Search.fs (90%) rename src/{Utilities => RearEnd}/BinExplorer/Show.fs (65%) rename src/{Utilities => RearEnd}/BinExplorer/SimpleArithConverter.fs (98%) rename src/{Utilities => RearEnd}/BinExplorer/SimpleArithHelper.fs (99%) rename src/{Utilities => RearEnd}/BinExplorer/SimpleArithOperator.fs (99%) rename src/{Utilities => RearEnd}/BinExplorer/SimpleArithParser.fs (99%) rename src/{Utilities => RearEnd}/BinExplorer/SimpleArithReference.fs (97%) rename src/{Utilities => RearEnd}/BinExplorer/SimpleArithTypes.fs (99%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/b2r2.png (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/b2r2.base.css (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/b2r2.css (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/b2r2.footer.css (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/b2r2.graph.css (97%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/b2r2.header.css (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/b2r2.main.css (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/b2r2.modal.css (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/b2r2.rotating.css (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/b2r2.toast.css (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/bootstrap.min.css (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/fontawesome.min.css (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/images/ui-icons_444444_256x240.png (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/images/ui-icons_555555_256x240.png (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/images/ui-icons_777620_256x240.png (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/images/ui-icons_777777_256x240.png (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/images/ui-icons_cc0000_256x240.png (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/images/ui-icons_ffffff_256x240.png (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/jquery-ui.min.css (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/css/jquery.contextMenu.min.css (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/favicon.ico (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/fonts/Inconsolata-Bold.ttf (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/fonts/Inconsolata-Regular.ttf (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/fonts/context-menu-icons.woff2 (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/fonts/fa-brands-400.woff2 (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/fonts/fa-regular-400.woff2 (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/fonts/fa-solid-900.woff2 (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.eot (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.svg (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.ttf (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.woff (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.woff2 (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/index.html (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.consts.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.flowgraph.js (98%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.graph.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.header.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.hexgraph.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.keyhandler.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.minimap.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.navbar.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.search.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.side.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.svgdefs.js (97%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.termgraph.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.toast.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.utils.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/b2r2.window.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/bootstrap.min.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/d3.min.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/jquery-ui.min.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/jquery.contextMenu.min.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/jquery.mark.min.js (100%) rename src/{Utilities => RearEnd}/BinExplorer/WebUI/js/jquery.min.js (100%) rename src/{Utilities/Core/B2R2.Utilities.Core.fsproj => RearEnd/Core/B2R2.RearEnd.Core.fsproj} (64%) create mode 100644 src/RearEnd/Core/CmdOpts.fs create mode 100644 src/RearEnd/Core/HexDumper.fs create mode 100644 src/RearEnd/FileViewer/B2R2.RearEnd.FileViewer.fsproj create mode 100644 src/RearEnd/FileViewer/Cmd.fs rename src/{BinEssence/RecoveredInfo.fs => RearEnd/FileViewer/DisplayItem.fs} (51%) create mode 100644 src/RearEnd/FileViewer/ELFViewer.fs rename src/{FrontEnd/ARM32/ARM32Parser.fsi => RearEnd/FileViewer/Helper.fs} (67%) create mode 100644 src/RearEnd/FileViewer/MachViewer.fs create mode 100644 src/RearEnd/FileViewer/PEViewer.fs create mode 100644 src/RearEnd/FileViewer/Program.fs create mode 100644 src/RearEnd/Launcher/B2R2.RearEnd.Launcher.fsproj create mode 100644 src/RearEnd/Launcher/Program.fs create mode 100644 src/RearEnd/Launcher/README.md create mode 100644 src/RearEnd/ROP/B2R2.RearEnd.ROP.fsproj rename src/{ => RearEnd}/ROP/Chain.fs (96%) rename src/{ => RearEnd}/ROP/Gadget.fs (95%) rename src/{ => RearEnd}/ROP/Galileo.fs (91%) rename src/{ => RearEnd}/ROP/ROPPayload.fs (99%) rename src/{ => RearEnd}/ROP/ROPValue.fs (95%) create mode 100644 src/RearEnd/ROP/Simplify.fs rename src/{ => RearEnd}/ROP/State.fs (67%) rename src/{ => RearEnd}/ROP/Summary.fs (74%) create mode 100644 src/RearEnd/Repl/B2R2.RearEnd.Repl.fsproj rename src/{Utilities/Repl/Main.fs => RearEnd/Repl/Program.fs} (84%) rename src/{Utilities => RearEnd}/Repl/ReplCommand.fs (98%) rename src/{Utilities => RearEnd}/Repl/ReplDisplay.fs (98%) rename src/{Utilities => RearEnd}/Repl/ReplOpts.fs (97%) rename src/{Utilities => RearEnd}/Repl/ReplState.fs (78%) rename src/{Visualization/B2R2.Visualization.fsproj => RearEnd/Visualization/B2R2.RearEnd.Visualization.fsproj} (68%) rename src/{ => RearEnd}/Visualization/CoordAssignment.fs (99%) rename src/{ => RearEnd}/Visualization/CrossMinimization.fs (98%) rename src/{ => RearEnd}/Visualization/CycleRemoval.fs (72%) create mode 100644 src/RearEnd/Visualization/EdgeDrawing.fs rename src/{ => RearEnd}/Visualization/JSONExport.fs (95%) create mode 100644 src/RearEnd/Visualization/LayerAssignment.fs rename src/{ => RearEnd}/Visualization/VisBBlock.fs (97%) rename src/{ => RearEnd}/Visualization/VisDebug.fs (96%) rename src/{ => RearEnd}/Visualization/VisEdge.fs (95%) rename src/{ => RearEnd}/Visualization/VisGraph.fs (96%) rename src/{ => RearEnd}/Visualization/VisPosition.fs (97%) rename src/{ => RearEnd}/Visualization/Visualizer.fs (97%) delete mode 100644 src/Utilities/Assembler/B2R2.Utilities.Assembler.fsproj delete mode 100644 src/Utilities/Assembler/Main.fs delete mode 100644 src/Utilities/BinDump/B2R2.Utilities.BinDump.fsproj delete mode 100644 src/Utilities/BinDump/Main.fs delete mode 100644 src/Utilities/Core/Utilities.fs delete mode 100644 src/Utilities/FileViewer/B2R2.Utilities.FileViewer.fsproj delete mode 100644 src/Utilities/FileViewer/Main.fs delete mode 100644 src/Utilities/Repl/B2R2.Utilities.Repl.fsproj delete mode 100644 src/Visualization/EdgeDrawing.fs delete mode 100644 src/Visualization/LayerAssignment.fs diff --git a/.b2r2-ci.json b/.b2r2-ci.json new file mode 100644 index 00000000..f5cb28ae --- /dev/null +++ b/.b2r2-ci.json @@ -0,0 +1,4 @@ +{ + "evaltest": "41af9961df3c75106aedefef2be91a0c96092604", + "switchtest": "fb9e2a0f94ed7cdf0dbd44e618ffdbb5cf153989" +} diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 00000000..9c48f5a2 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "b2r2.rearend.launcher": { + "version": "0.4.0", + "commands": [ + "b2r2" + ] + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index bee2136e..a688a416 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,4 @@ build/ -B2R2.log +B2R2.log \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3c675e35..73236302 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,8 +1,8 @@ -image: mcr.microsoft.com/dotnet/core/sdk:3.1 +image: mcr.microsoft.com/dotnet/sdk:5.0-focal stages: - build - - evaltest + - extra build: stage: build @@ -14,18 +14,15 @@ build: artifacts: paths: - build/ - expire_in: 1 day + expire_in: 3 hrs tags: - b2r2 -evaltest: - stage: evaltest +extra: + stage: extra script: - - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@softsec.kaist.ac.kr:8888/B2R2/evaltest - - dotnet nuget locals all --clear - - | - dotnet run -c Release --project evaltest/B2R2.TestDriver -- \ - $TRACE_URL $CI_COMMIT_REF_NAME $CI_COMMIT_SHA "$GITLAB_USER_NAME" + - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@softsec.kaist.ac.kr:8000/B2R2/ci-runner + - dotnet run -p ci-runner/CIStarter -- $CI_URL $CI_COMMIT_SHA $CI_COMMIT_REF_NAME "$GITLAB_USER_NAME" dependencies: - build tags: diff --git a/AUTHORS.md b/AUTHORS.md index 9afd6640..efc4ced0 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -12,16 +12,22 @@ B2R2 would not have been possible without the help of contributors. Below is a list of contributors in alphabetic order. +- Anar Abbas - Mehdi Aghakishiyev - TA Thanh Dinh - HyungSeok Han +- Cheonhoo Jeon - Subin Jeong - Minkyu Jung - Dohyeok Kim - Dongkwan Kim - Doyeon Kim - Hongsik Kim +- Jaemin Kim +- JungHyun Kim - Kangsu Kim +- Junoh Lee - Minsu Lee - DongYeop Oh +- MyeongGeun Shin - Michael Tegegn diff --git a/B2R2.sln b/B2R2.sln index 4a5ee9ec..bf04a45f 100644 --- a/B2R2.sln +++ b/B2R2.sln @@ -1,96 +1,90 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26124.0 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30804.86 MinimumVisualStudioVersion = 15.0.26124.0 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{96279848-CA27-42C6-9488-498A8E696F67}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Core", "src\Core\B2R2.Core.fsproj", "{92A41F1C-8B77-4479-8CD3-FB8987269C60}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Core", "src\Core\B2R2.Core.fsproj", "{92A41F1C-8B77-4479-8CD3-FB8987269C60}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Core.Tests", "src\Core.Tests\B2R2.Core.Tests.fsproj", "{29FF59AD-E83D-4084-9DE5-564CA5687981}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Core.Tests", "src\Core.Tests\B2R2.Core.Tests.fsproj", "{29FF59AD-E83D-4084-9DE5-564CA5687981}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.BinIR", "src\BinIR\B2R2.BinIR.fsproj", "{7AE36E18-182E-4E36-AD0E-08F326B381B2}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.BinIR", "src\BinIR\B2R2.BinIR.fsproj", "{7AE36E18-182E-4E36-AD0E-08F326B381B2}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "B2R2.FrontEnd", "FrontEnd", "{93429CD0-F010-450F-9C16-67C8E7F6E644}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.BinIR.Tests", "src\BinIR.Tests\B2R2.BinIR.Tests.fsproj", "{A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.Core", "src\FrontEnd\Core\B2R2.FrontEnd.Core.fsproj", "{F5AD1150-9B7B-4112-9E08-C5542119750E}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FrontEnd", "FrontEnd", "{55E62B6F-2C33-4E89-ADD5-0CE9BAA76401}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.Intel", "src\FrontEnd\Intel\B2R2.FrontEnd.Intel.fsproj", "{5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BinLifter", "BinLifter", "{0CAF4618-5C72-4A71-BAEB-79AA4065B9D6}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.ARM32", "src\FrontEnd\ARM32\B2R2.FrontEnd.ARM32.fsproj", "{813B9B3A-8ECD-49ED-A231-7B220F7F5662}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.Core", "src\FrontEnd\BinLifter\Core\B2R2.FrontEnd.BinLifter.Core.fsproj", "{717ED421-8AE2-435F-888F-91F676C87C32}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.ARM64", "src\FrontEnd\ARM64\B2R2.FrontEnd.ARM64.fsproj", "{4B949B7B-715C-480E-BC1E-AAAECBB17922}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.Intel", "src\FrontEnd\BinLifter\Intel\B2R2.FrontEnd.BinLifter.Intel.fsproj", "{B9E587C6-D492-478A-856D-A7FC67EB5FE0}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.MIPS", "src\FrontEnd\MIPS\B2R2.FrontEnd.MIPS.fsproj", "{B0FBC90F-9579-434C-A703-3F4777F2AC01}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.ARM32", "src\FrontEnd\BinLifter\ARM32\B2R2.FrontEnd.BinLifter.ARM32.fsproj", "{65784B83-F76F-4C1A-AAAD-6417614116C6}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.EVM", "src\FrontEnd\EVM\B2R2.FrontEnd.EVM.fsproj", "{24FDFC45-63AE-43BB-9CFF-18CB1BE14571}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.ARM64", "src\FrontEnd\BinLifter\ARM64\B2R2.FrontEnd.BinLifter.ARM64.fsproj", "{8CA197A9-96CE-4284-80B5-EC0132F20A62}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.TMS320C6000", "src\FrontEnd\TMS320C6000\B2R2.FrontEnd.TMS320C6000.fsproj", "{F8DAB23E-8992-4E93-8376-C428BB5F2423}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.AVR", "src\FrontEnd\BinLifter\AVR\B2R2.FrontEnd.BinLifter.AVR.fsproj", "{A425AE4A-691C-4540-9CA0-2B7D32EFE230}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.Optimizer", "src\FrontEnd\Optimizer\B2R2.FrontEnd.Optimizer.fsproj", "{58B017A0-2084-4388-B2CF-2073F3712AD2}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.MIPS", "src\FrontEnd\BinLifter\MIPS\B2R2.FrontEnd.BinLifter.MIPS.fsproj", "{40C841D4-C7D0-489B-80FB-5B4D22DB60E7}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.Library", "src\FrontEnd\Library\B2R2.FrontEnd.Library.fsproj", "{6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.EVM", "src\FrontEnd\BinLifter\EVM\B2R2.FrontEnd.BinLifter.EVM.fsproj", "{49C21BFB-126B-473D-876E-C9965CCD3096}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.Tests", "src\FrontEnd.Tests\B2R2.FrontEnd.Tests.fsproj", "{7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.TMS320C6000", "src\FrontEnd\BinLifter\TMS320C6000\B2R2.FrontEnd.BinLifter.TMS320C6000.fsproj", "{E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.BinGraph", "src\BinGraph\B2R2.BinGraph.fsproj", "{C6A685B1-7AEA-4ADF-8206-09FB563F3342}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.CIL", "src\FrontEnd\BinLifter\CIL\B2R2.FrontEnd.BinLifter.CIL.fsproj", "{A0A5A856-7C41-46E5-B773-97B677E532B5}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.BinGraph.Tests", "src\BinGraph.Tests\B2R2.BinGraph.Tests.fsproj", "{72402835-6446-4B54-8FEF-3E42B17730EA}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.Optimizer", "src\FrontEnd\BinLifter\Optimizer\B2R2.FrontEnd.BinLifter.Optimizer.fsproj", "{772A6D09-0FB3-46B0-A234-9196704D4657}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.ROP", "src\ROP\B2R2.ROP.fsproj", "{FD759318-1E7C-499B-9DDB-9B7ADC216602}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.Tests", "src\FrontEnd\BinLifter.Tests\B2R2.FrontEnd.BinLifter.Tests.fsproj", "{5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Visualization", "src\Visualization\B2R2.Visualization.fsproj", "{FA2308B6-C47A-47F1-A028-E86CA0323E2A}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinFile", "src\FrontEnd\BinFile\B2R2.FrontEnd.BinFile.fsproj", "{1CD7C68A-A371-49CE-8F54-A7E781EE332A}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.BinFile", "src\BinFile\B2R2.BinFile.fsproj", "{2B55B11C-D04A-4451-B8D2-0CDA632940EE}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinFile.Tests", "src\FrontEnd\BinFile.Tests\B2R2.FrontEnd.BinFile.Tests.fsproj", "{80DB4163-821F-4C85-80AB-B6E5E946C4F9}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.BinFile.Tests", "src\BinFile.Tests\B2R2.BinFile.Tests.fsproj", "{960663A9-F17E-4F94-AC5B-E581A6171028}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinInterface", "src\FrontEnd\BinInterface\B2R2.FrontEnd.BinInterface.fsproj", "{C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.BinEssence", "src\BinEssence\B2R2.BinEssence.fsproj", "{6E0693DF-23FE-41EF-AA97-8310AF5120E9}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.NameMangling", "src\FrontEnd\NameMangling\B2R2.FrontEnd.NameMangling.fsproj", "{ADB65D83-B476-4F0B-8B9F-8719A8AB7624}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Lens", "src\Lens\B2R2.Lens.fsproj", "{4FE21337-C76D-431E-B0A8-7726D1A335DC}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.NameMangling.Tests", "src\FrontEnd\NameMangling.Tests\B2R2.FrontEnd.NameMangling.Tests.fsproj", "{26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "B2R2.Utilities", "Utilities", "{E1C9E2B5-9ABE-4AC7-994D-4E9C44BDD49E}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RearEnd", "RearEnd", "{BBF63851-BC21-45CC-A671-9ED1A538E052}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Utilities.Core", "src\Utilities\Core\B2R2.Utilities.Core.fsproj", "{1B874C58-C5C7-41A0-B188-E80D4882729E}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.Core", "src\RearEnd\Core\B2R2.RearEnd.Core.fsproj", "{42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Utilities.FileViewer", "src\Utilities\FileViewer\B2R2.Utilities.FileViewer.fsproj", "{94B5D8E5-F3B1-438A-94E1-095574259B6C}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.FileViewer", "src\RearEnd\FileViewer\B2R2.RearEnd.FileViewer.fsproj", "{84AD21E8-23A0-4029-9767-50F7863E7A02}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Utilities.BinDump", "src\Utilities\BinDump\B2R2.Utilities.BinDump.fsproj", "{7095B11D-8CF7-4526-A687-1307765CCADA}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.BinDump", "src\RearEnd\BinDump\B2R2.RearEnd.BinDump.fsproj", "{44BFF304-5D42-4065-9260-E2C9E552EB24}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Utilities.BinExplorer", "src\Utilities\BinExplorer\B2R2.Utilities.BinExplorer.fsproj", "{A6964A5A-176B-4E02-8137-81443075EAA7}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.ROP", "src\RearEnd\ROP\B2R2.RearEnd.ROP.fsproj", "{0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Utilities.Assembler", "src\Utilities\Assembler\B2R2.Utilities.Assembler.fsproj", "{2D501B10-F7E8-4E86-9742-94530CDF9BD4}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.Visualization", "src\RearEnd\Visualization\B2R2.RearEnd.Visualization.fsproj", "{7FACEAF5-30A5-4502-822C-485FE980A6C3}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Utilities.Repl", "src\Utilities\Repl\B2R2.Utilities.Repl.fsproj", "{6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.BinExplorer", "src\RearEnd\BinExplorer\B2R2.RearEnd.BinExplorer.fsproj", "{05276DA5-3CF1-4950-8923-9A5F4C1A15D8}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.ConcEval", "src\ConcEval\B2R2.ConcEval.fsproj", "{0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.Assembler", "src\RearEnd\Assembler\B2R2.RearEnd.Assembler.fsproj", "{300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "B2R2.Assembler", "Assembler", "{C76D41A4-7963-41F0-9F6D-CDC80624FB25}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.Repl", "src\RearEnd\Repl\B2R2.RearEnd.Repl.fsproj", "{35184561-8AAB-4E74-9E0D-231D16E336BF}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Assembler.Core", "src\Assembler\Core\B2R2.Assembler.Core.fsproj", "{1B051A0D-D01B-4A3A-9821-C139CEDC6E43}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.Launcher", "src\RearEnd\Launcher\B2R2.RearEnd.Launcher.fsproj", "{ECF6ADAE-C222-41E9-BA5B-811866193A2B}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Assembler.ARM32", "src\Assembler\ARM32\B2R2.Assembler.ARM32.fsproj", "{076A78FA-959E-4741-89A5-0767B5F70C9C}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Peripheral", "Peripheral", "{F0888151-28C5-4EF0-86CB-9C66218F89AE}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Assembler.Intel", "src\Assembler\Intel\B2R2.Assembler.Intel.fsproj", "{03D5E1E9-3BD2-4D6C-9252-91D6867803B8}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Assembly", "Assembly", "{F90413F1-AB57-43C0-B401-E7C2EC83198C}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Assembler.MIPS", "src\Assembler\MIPS\B2R2.Assembler.MIPS.fsproj", "{991634E3-32C0-4EC7-8F3D-9373721EE9DC}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.Core", "src\Peripheral\Assembly\Core\B2R2.Peripheral.Assembly.Core.fsproj", "{D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Assembler.LowUIR", "src\Assembler\LowUIR\B2R2.Assembler.LowUIR.fsproj", "{6702318E-E585-4CAD-8BD6-5E39FD15BC4D}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.ARM32", "src\Peripheral\Assembly\ARM32\B2R2.Peripheral.Assembly.ARM32.fsproj", "{54652BFC-61CF-4DF0-B34A-64406A43F708}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Assembler.Interface", "src\Assembler\Interface\B2R2.Assembler.Interface.fsproj", "{EAC00D28-63C9-42E4-B169-40071EC2B3BD}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.Intel", "src\Peripheral\Assembly\Intel\B2R2.Peripheral.Assembly.Intel.fsproj", "{F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Assembler.Tests", "src\Assembler.Tests\B2R2.Assembler.Tests.fsproj", "{0964634E-371B-4ADB-9CA6-288AE0AD2EE5}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.MIPS", "src\Peripheral\Assembly\MIPS\B2R2.Peripheral.Assembly.MIPS.fsproj", "{7C6A7725-FA4E-45FB-A4CB-8F581D017C05}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.NameMangling", "src\NameMangling\B2R2.NameMangling.fsproj", "{98733F39-94B6-405F-8BFC-98064F9C8250}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.LowUIR", "src\Peripheral\Assembly\LowUIR\B2R2.Peripheral.Assembly.LowUIR.fsproj", "{DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.NameMangling.Tests", "src\NameMangling.Tests\B2R2.NameMangling.Tests.fsproj", "{0BEC4ACF-3F78-456B-B18F-2E422085AF78}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.AsmInterface", "src\Peripheral\Assembly\AsmInterface\B2R2.Peripheral.Assembly.AsmInterface.fsproj", "{A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.DataFlow", "src\DataFlow\B2R2.DataFlow.fsproj", "{6BEC2D0D-365C-4069-9253-82EE136E59B8}" -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.DataFlow.Tests", "src\DataFlow.Tests\B2R2.DataFlow.Tests.fsproj", "{F09A1806-432C-4627-B86B-C8DE3C7116D4}" -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.MiddleEnd", "src\MiddleEnd\B2R2.MiddleEnd.fsproj", "{FB1F392C-F78E-4578-AE3D-359365F521E2}" -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.MiddleEnd.Tests", "src\MiddleEnd.Tests\B2R2.MiddleEnd.Tests.fsproj", "{ECF76680-BA01-4B53-85CC-9B9A4C206FB9}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.Tests", "src\Peripheral\Assembly.Tests\B2R2.Peripheral.Assembly.Tests.fsproj", "{3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -101,9 +95,6 @@ Global Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {92A41F1C-8B77-4479-8CD3-FB8987269C60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {92A41F1C-8B77-4479-8CD3-FB8987269C60}.Debug|Any CPU.Build.0 = Debug|Any CPU @@ -141,507 +132,450 @@ Global {7AE36E18-182E-4E36-AD0E-08F326B381B2}.Release|x64.Build.0 = Release|Any CPU {7AE36E18-182E-4E36-AD0E-08F326B381B2}.Release|x86.ActiveCfg = Release|Any CPU {7AE36E18-182E-4E36-AD0E-08F326B381B2}.Release|x86.Build.0 = Release|Any CPU - {F5AD1150-9B7B-4112-9E08-C5542119750E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F5AD1150-9B7B-4112-9E08-C5542119750E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F5AD1150-9B7B-4112-9E08-C5542119750E}.Debug|x64.ActiveCfg = Debug|Any CPU - {F5AD1150-9B7B-4112-9E08-C5542119750E}.Debug|x64.Build.0 = Debug|Any CPU - {F5AD1150-9B7B-4112-9E08-C5542119750E}.Debug|x86.ActiveCfg = Debug|Any CPU - {F5AD1150-9B7B-4112-9E08-C5542119750E}.Debug|x86.Build.0 = Debug|Any CPU - {F5AD1150-9B7B-4112-9E08-C5542119750E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F5AD1150-9B7B-4112-9E08-C5542119750E}.Release|Any CPU.Build.0 = Release|Any CPU - {F5AD1150-9B7B-4112-9E08-C5542119750E}.Release|x64.ActiveCfg = Release|Any CPU - {F5AD1150-9B7B-4112-9E08-C5542119750E}.Release|x64.Build.0 = Release|Any CPU - {F5AD1150-9B7B-4112-9E08-C5542119750E}.Release|x86.ActiveCfg = Release|Any CPU - {F5AD1150-9B7B-4112-9E08-C5542119750E}.Release|x86.Build.0 = Release|Any CPU - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}.Debug|x64.ActiveCfg = Debug|Any CPU - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}.Debug|x64.Build.0 = Debug|Any CPU - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}.Debug|x86.ActiveCfg = Debug|Any CPU - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}.Debug|x86.Build.0 = Debug|Any CPU - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}.Release|Any CPU.Build.0 = Release|Any CPU - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}.Release|x64.ActiveCfg = Release|Any CPU - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}.Release|x64.Build.0 = Release|Any CPU - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}.Release|x86.ActiveCfg = Release|Any CPU - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC}.Release|x86.Build.0 = Release|Any CPU - {813B9B3A-8ECD-49ED-A231-7B220F7F5662}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {813B9B3A-8ECD-49ED-A231-7B220F7F5662}.Debug|Any CPU.Build.0 = Debug|Any CPU - {813B9B3A-8ECD-49ED-A231-7B220F7F5662}.Debug|x64.ActiveCfg = Debug|Any CPU - {813B9B3A-8ECD-49ED-A231-7B220F7F5662}.Debug|x64.Build.0 = Debug|Any CPU - {813B9B3A-8ECD-49ED-A231-7B220F7F5662}.Debug|x86.ActiveCfg = Debug|Any CPU - {813B9B3A-8ECD-49ED-A231-7B220F7F5662}.Debug|x86.Build.0 = Debug|Any CPU - {813B9B3A-8ECD-49ED-A231-7B220F7F5662}.Release|Any CPU.ActiveCfg = Release|Any CPU - {813B9B3A-8ECD-49ED-A231-7B220F7F5662}.Release|Any CPU.Build.0 = Release|Any CPU - {813B9B3A-8ECD-49ED-A231-7B220F7F5662}.Release|x64.ActiveCfg = Release|Any CPU - {813B9B3A-8ECD-49ED-A231-7B220F7F5662}.Release|x64.Build.0 = Release|Any CPU - {813B9B3A-8ECD-49ED-A231-7B220F7F5662}.Release|x86.ActiveCfg = Release|Any CPU - {813B9B3A-8ECD-49ED-A231-7B220F7F5662}.Release|x86.Build.0 = Release|Any CPU - {4B949B7B-715C-480E-BC1E-AAAECBB17922}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4B949B7B-715C-480E-BC1E-AAAECBB17922}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4B949B7B-715C-480E-BC1E-AAAECBB17922}.Debug|x64.ActiveCfg = Debug|Any CPU - {4B949B7B-715C-480E-BC1E-AAAECBB17922}.Debug|x64.Build.0 = Debug|Any CPU - {4B949B7B-715C-480E-BC1E-AAAECBB17922}.Debug|x86.ActiveCfg = Debug|Any CPU - {4B949B7B-715C-480E-BC1E-AAAECBB17922}.Debug|x86.Build.0 = Debug|Any CPU - {4B949B7B-715C-480E-BC1E-AAAECBB17922}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4B949B7B-715C-480E-BC1E-AAAECBB17922}.Release|Any CPU.Build.0 = Release|Any CPU - {4B949B7B-715C-480E-BC1E-AAAECBB17922}.Release|x64.ActiveCfg = Release|Any CPU - {4B949B7B-715C-480E-BC1E-AAAECBB17922}.Release|x64.Build.0 = Release|Any CPU - {4B949B7B-715C-480E-BC1E-AAAECBB17922}.Release|x86.ActiveCfg = Release|Any CPU - {4B949B7B-715C-480E-BC1E-AAAECBB17922}.Release|x86.Build.0 = Release|Any CPU - {B0FBC90F-9579-434C-A703-3F4777F2AC01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B0FBC90F-9579-434C-A703-3F4777F2AC01}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B0FBC90F-9579-434C-A703-3F4777F2AC01}.Debug|x64.ActiveCfg = Debug|Any CPU - {B0FBC90F-9579-434C-A703-3F4777F2AC01}.Debug|x64.Build.0 = Debug|Any CPU - {B0FBC90F-9579-434C-A703-3F4777F2AC01}.Debug|x86.ActiveCfg = Debug|Any CPU - {B0FBC90F-9579-434C-A703-3F4777F2AC01}.Debug|x86.Build.0 = Debug|Any CPU - {B0FBC90F-9579-434C-A703-3F4777F2AC01}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B0FBC90F-9579-434C-A703-3F4777F2AC01}.Release|Any CPU.Build.0 = Release|Any CPU - {B0FBC90F-9579-434C-A703-3F4777F2AC01}.Release|x64.ActiveCfg = Release|Any CPU - {B0FBC90F-9579-434C-A703-3F4777F2AC01}.Release|x64.Build.0 = Release|Any CPU - {B0FBC90F-9579-434C-A703-3F4777F2AC01}.Release|x86.ActiveCfg = Release|Any CPU - {B0FBC90F-9579-434C-A703-3F4777F2AC01}.Release|x86.Build.0 = Release|Any CPU - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}.Debug|x64.ActiveCfg = Debug|Any CPU - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}.Debug|x64.Build.0 = Debug|Any CPU - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}.Debug|x86.ActiveCfg = Debug|Any CPU - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}.Debug|x86.Build.0 = Debug|Any CPU - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}.Release|Any CPU.Build.0 = Release|Any CPU - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}.Release|x64.ActiveCfg = Release|Any CPU - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}.Release|x64.Build.0 = Release|Any CPU - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}.Release|x86.ActiveCfg = Release|Any CPU - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658}.Release|x86.Build.0 = Release|Any CPU - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}.Debug|x64.ActiveCfg = Debug|Any CPU - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}.Debug|x64.Build.0 = Debug|Any CPU - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}.Debug|x86.ActiveCfg = Debug|Any CPU - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}.Debug|x86.Build.0 = Debug|Any CPU - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}.Release|Any CPU.Build.0 = Release|Any CPU - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}.Release|x64.ActiveCfg = Release|Any CPU - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}.Release|x64.Build.0 = Release|Any CPU - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}.Release|x86.ActiveCfg = Release|Any CPU - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE}.Release|x86.Build.0 = Release|Any CPU - {C6A685B1-7AEA-4ADF-8206-09FB563F3342}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C6A685B1-7AEA-4ADF-8206-09FB563F3342}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C6A685B1-7AEA-4ADF-8206-09FB563F3342}.Debug|x64.ActiveCfg = Debug|Any CPU - {C6A685B1-7AEA-4ADF-8206-09FB563F3342}.Debug|x64.Build.0 = Debug|Any CPU - {C6A685B1-7AEA-4ADF-8206-09FB563F3342}.Debug|x86.ActiveCfg = Debug|Any CPU - {C6A685B1-7AEA-4ADF-8206-09FB563F3342}.Debug|x86.Build.0 = Debug|Any CPU - {C6A685B1-7AEA-4ADF-8206-09FB563F3342}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C6A685B1-7AEA-4ADF-8206-09FB563F3342}.Release|Any CPU.Build.0 = Release|Any CPU - {C6A685B1-7AEA-4ADF-8206-09FB563F3342}.Release|x64.ActiveCfg = Release|Any CPU - {C6A685B1-7AEA-4ADF-8206-09FB563F3342}.Release|x64.Build.0 = Release|Any CPU - {C6A685B1-7AEA-4ADF-8206-09FB563F3342}.Release|x86.ActiveCfg = Release|Any CPU - {C6A685B1-7AEA-4ADF-8206-09FB563F3342}.Release|x86.Build.0 = Release|Any CPU - {72402835-6446-4B54-8FEF-3E42B17730EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {72402835-6446-4B54-8FEF-3E42B17730EA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {72402835-6446-4B54-8FEF-3E42B17730EA}.Debug|x64.ActiveCfg = Debug|Any CPU - {72402835-6446-4B54-8FEF-3E42B17730EA}.Debug|x64.Build.0 = Debug|Any CPU - {72402835-6446-4B54-8FEF-3E42B17730EA}.Debug|x86.ActiveCfg = Debug|Any CPU - {72402835-6446-4B54-8FEF-3E42B17730EA}.Debug|x86.Build.0 = Debug|Any CPU - {72402835-6446-4B54-8FEF-3E42B17730EA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {72402835-6446-4B54-8FEF-3E42B17730EA}.Release|Any CPU.Build.0 = Release|Any CPU - {72402835-6446-4B54-8FEF-3E42B17730EA}.Release|x64.ActiveCfg = Release|Any CPU - {72402835-6446-4B54-8FEF-3E42B17730EA}.Release|x64.Build.0 = Release|Any CPU - {72402835-6446-4B54-8FEF-3E42B17730EA}.Release|x86.ActiveCfg = Release|Any CPU - {72402835-6446-4B54-8FEF-3E42B17730EA}.Release|x86.Build.0 = Release|Any CPU - {FD759318-1E7C-499B-9DDB-9B7ADC216602}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FD759318-1E7C-499B-9DDB-9B7ADC216602}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FD759318-1E7C-499B-9DDB-9B7ADC216602}.Debug|x64.ActiveCfg = Debug|Any CPU - {FD759318-1E7C-499B-9DDB-9B7ADC216602}.Debug|x64.Build.0 = Debug|Any CPU - {FD759318-1E7C-499B-9DDB-9B7ADC216602}.Debug|x86.ActiveCfg = Debug|Any CPU - {FD759318-1E7C-499B-9DDB-9B7ADC216602}.Debug|x86.Build.0 = Debug|Any CPU - {FD759318-1E7C-499B-9DDB-9B7ADC216602}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FD759318-1E7C-499B-9DDB-9B7ADC216602}.Release|Any CPU.Build.0 = Release|Any CPU - {FD759318-1E7C-499B-9DDB-9B7ADC216602}.Release|x64.ActiveCfg = Release|Any CPU - {FD759318-1E7C-499B-9DDB-9B7ADC216602}.Release|x64.Build.0 = Release|Any CPU - {FD759318-1E7C-499B-9DDB-9B7ADC216602}.Release|x86.ActiveCfg = Release|Any CPU - {FD759318-1E7C-499B-9DDB-9B7ADC216602}.Release|x86.Build.0 = Release|Any CPU - {FA2308B6-C47A-47F1-A028-E86CA0323E2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FA2308B6-C47A-47F1-A028-E86CA0323E2A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FA2308B6-C47A-47F1-A028-E86CA0323E2A}.Debug|x64.ActiveCfg = Debug|Any CPU - {FA2308B6-C47A-47F1-A028-E86CA0323E2A}.Debug|x64.Build.0 = Debug|Any CPU - {FA2308B6-C47A-47F1-A028-E86CA0323E2A}.Debug|x86.ActiveCfg = Debug|Any CPU - {FA2308B6-C47A-47F1-A028-E86CA0323E2A}.Debug|x86.Build.0 = Debug|Any CPU - {FA2308B6-C47A-47F1-A028-E86CA0323E2A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FA2308B6-C47A-47F1-A028-E86CA0323E2A}.Release|Any CPU.Build.0 = Release|Any CPU - {FA2308B6-C47A-47F1-A028-E86CA0323E2A}.Release|x64.ActiveCfg = Release|Any CPU - {FA2308B6-C47A-47F1-A028-E86CA0323E2A}.Release|x64.Build.0 = Release|Any CPU - {FA2308B6-C47A-47F1-A028-E86CA0323E2A}.Release|x86.ActiveCfg = Release|Any CPU - {FA2308B6-C47A-47F1-A028-E86CA0323E2A}.Release|x86.Build.0 = Release|Any CPU - {2B55B11C-D04A-4451-B8D2-0CDA632940EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2B55B11C-D04A-4451-B8D2-0CDA632940EE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2B55B11C-D04A-4451-B8D2-0CDA632940EE}.Debug|x64.ActiveCfg = Debug|Any CPU - {2B55B11C-D04A-4451-B8D2-0CDA632940EE}.Debug|x64.Build.0 = Debug|Any CPU - {2B55B11C-D04A-4451-B8D2-0CDA632940EE}.Debug|x86.ActiveCfg = Debug|Any CPU - {2B55B11C-D04A-4451-B8D2-0CDA632940EE}.Debug|x86.Build.0 = Debug|Any CPU - {2B55B11C-D04A-4451-B8D2-0CDA632940EE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2B55B11C-D04A-4451-B8D2-0CDA632940EE}.Release|Any CPU.Build.0 = Release|Any CPU - {2B55B11C-D04A-4451-B8D2-0CDA632940EE}.Release|x64.ActiveCfg = Release|Any CPU - {2B55B11C-D04A-4451-B8D2-0CDA632940EE}.Release|x64.Build.0 = Release|Any CPU - {2B55B11C-D04A-4451-B8D2-0CDA632940EE}.Release|x86.ActiveCfg = Release|Any CPU - {2B55B11C-D04A-4451-B8D2-0CDA632940EE}.Release|x86.Build.0 = Release|Any CPU - {960663A9-F17E-4F94-AC5B-E581A6171028}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {960663A9-F17E-4F94-AC5B-E581A6171028}.Debug|Any CPU.Build.0 = Debug|Any CPU - {960663A9-F17E-4F94-AC5B-E581A6171028}.Debug|x64.ActiveCfg = Debug|Any CPU - {960663A9-F17E-4F94-AC5B-E581A6171028}.Debug|x64.Build.0 = Debug|Any CPU - {960663A9-F17E-4F94-AC5B-E581A6171028}.Debug|x86.ActiveCfg = Debug|Any CPU - {960663A9-F17E-4F94-AC5B-E581A6171028}.Debug|x86.Build.0 = Debug|Any CPU - {960663A9-F17E-4F94-AC5B-E581A6171028}.Release|Any CPU.ActiveCfg = Release|Any CPU - {960663A9-F17E-4F94-AC5B-E581A6171028}.Release|Any CPU.Build.0 = Release|Any CPU - {960663A9-F17E-4F94-AC5B-E581A6171028}.Release|x64.ActiveCfg = Release|Any CPU - {960663A9-F17E-4F94-AC5B-E581A6171028}.Release|x64.Build.0 = Release|Any CPU - {960663A9-F17E-4F94-AC5B-E581A6171028}.Release|x86.ActiveCfg = Release|Any CPU - {960663A9-F17E-4F94-AC5B-E581A6171028}.Release|x86.Build.0 = Release|Any CPU - {58B017A0-2084-4388-B2CF-2073F3712AD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {58B017A0-2084-4388-B2CF-2073F3712AD2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {58B017A0-2084-4388-B2CF-2073F3712AD2}.Debug|x64.ActiveCfg = Debug|Any CPU - {58B017A0-2084-4388-B2CF-2073F3712AD2}.Debug|x64.Build.0 = Debug|Any CPU - {58B017A0-2084-4388-B2CF-2073F3712AD2}.Debug|x86.ActiveCfg = Debug|Any CPU - {58B017A0-2084-4388-B2CF-2073F3712AD2}.Debug|x86.Build.0 = Debug|Any CPU - {58B017A0-2084-4388-B2CF-2073F3712AD2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {58B017A0-2084-4388-B2CF-2073F3712AD2}.Release|Any CPU.Build.0 = Release|Any CPU - {58B017A0-2084-4388-B2CF-2073F3712AD2}.Release|x64.ActiveCfg = Release|Any CPU - {58B017A0-2084-4388-B2CF-2073F3712AD2}.Release|x64.Build.0 = Release|Any CPU - {58B017A0-2084-4388-B2CF-2073F3712AD2}.Release|x86.ActiveCfg = Release|Any CPU - {58B017A0-2084-4388-B2CF-2073F3712AD2}.Release|x86.Build.0 = Release|Any CPU - {1B874C58-C5C7-41A0-B188-E80D4882729E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1B874C58-C5C7-41A0-B188-E80D4882729E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1B874C58-C5C7-41A0-B188-E80D4882729E}.Debug|x64.ActiveCfg = Debug|Any CPU - {1B874C58-C5C7-41A0-B188-E80D4882729E}.Debug|x64.Build.0 = Debug|Any CPU - {1B874C58-C5C7-41A0-B188-E80D4882729E}.Debug|x86.ActiveCfg = Debug|Any CPU - {1B874C58-C5C7-41A0-B188-E80D4882729E}.Debug|x86.Build.0 = Debug|Any CPU - {1B874C58-C5C7-41A0-B188-E80D4882729E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1B874C58-C5C7-41A0-B188-E80D4882729E}.Release|Any CPU.Build.0 = Release|Any CPU - {1B874C58-C5C7-41A0-B188-E80D4882729E}.Release|x64.ActiveCfg = Release|Any CPU - {1B874C58-C5C7-41A0-B188-E80D4882729E}.Release|x64.Build.0 = Release|Any CPU - {1B874C58-C5C7-41A0-B188-E80D4882729E}.Release|x86.ActiveCfg = Release|Any CPU - {1B874C58-C5C7-41A0-B188-E80D4882729E}.Release|x86.Build.0 = Release|Any CPU - {94B5D8E5-F3B1-438A-94E1-095574259B6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {94B5D8E5-F3B1-438A-94E1-095574259B6C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {94B5D8E5-F3B1-438A-94E1-095574259B6C}.Debug|x64.ActiveCfg = Debug|Any CPU - {94B5D8E5-F3B1-438A-94E1-095574259B6C}.Debug|x64.Build.0 = Debug|Any CPU - {94B5D8E5-F3B1-438A-94E1-095574259B6C}.Debug|x86.ActiveCfg = Debug|Any CPU - {94B5D8E5-F3B1-438A-94E1-095574259B6C}.Debug|x86.Build.0 = Debug|Any CPU - {94B5D8E5-F3B1-438A-94E1-095574259B6C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {94B5D8E5-F3B1-438A-94E1-095574259B6C}.Release|Any CPU.Build.0 = Release|Any CPU - {94B5D8E5-F3B1-438A-94E1-095574259B6C}.Release|x64.ActiveCfg = Release|Any CPU - {94B5D8E5-F3B1-438A-94E1-095574259B6C}.Release|x64.Build.0 = Release|Any CPU - {94B5D8E5-F3B1-438A-94E1-095574259B6C}.Release|x86.ActiveCfg = Release|Any CPU - {94B5D8E5-F3B1-438A-94E1-095574259B6C}.Release|x86.Build.0 = Release|Any CPU - {7095B11D-8CF7-4526-A687-1307765CCADA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7095B11D-8CF7-4526-A687-1307765CCADA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7095B11D-8CF7-4526-A687-1307765CCADA}.Debug|x64.ActiveCfg = Debug|Any CPU - {7095B11D-8CF7-4526-A687-1307765CCADA}.Debug|x64.Build.0 = Debug|Any CPU - {7095B11D-8CF7-4526-A687-1307765CCADA}.Debug|x86.ActiveCfg = Debug|Any CPU - {7095B11D-8CF7-4526-A687-1307765CCADA}.Debug|x86.Build.0 = Debug|Any CPU - {7095B11D-8CF7-4526-A687-1307765CCADA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7095B11D-8CF7-4526-A687-1307765CCADA}.Release|Any CPU.Build.0 = Release|Any CPU - {7095B11D-8CF7-4526-A687-1307765CCADA}.Release|x64.ActiveCfg = Release|Any CPU - {7095B11D-8CF7-4526-A687-1307765CCADA}.Release|x64.Build.0 = Release|Any CPU - {7095B11D-8CF7-4526-A687-1307765CCADA}.Release|x86.ActiveCfg = Release|Any CPU - {7095B11D-8CF7-4526-A687-1307765CCADA}.Release|x86.Build.0 = Release|Any CPU - {A6964A5A-176B-4E02-8137-81443075EAA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A6964A5A-176B-4E02-8137-81443075EAA7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A6964A5A-176B-4E02-8137-81443075EAA7}.Debug|x64.ActiveCfg = Debug|Any CPU - {A6964A5A-176B-4E02-8137-81443075EAA7}.Debug|x64.Build.0 = Debug|Any CPU - {A6964A5A-176B-4E02-8137-81443075EAA7}.Debug|x86.ActiveCfg = Debug|Any CPU - {A6964A5A-176B-4E02-8137-81443075EAA7}.Debug|x86.Build.0 = Debug|Any CPU - {A6964A5A-176B-4E02-8137-81443075EAA7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A6964A5A-176B-4E02-8137-81443075EAA7}.Release|Any CPU.Build.0 = Release|Any CPU - {A6964A5A-176B-4E02-8137-81443075EAA7}.Release|x64.ActiveCfg = Release|Any CPU - {A6964A5A-176B-4E02-8137-81443075EAA7}.Release|x64.Build.0 = Release|Any CPU - {A6964A5A-176B-4E02-8137-81443075EAA7}.Release|x86.ActiveCfg = Release|Any CPU - {A6964A5A-176B-4E02-8137-81443075EAA7}.Release|x86.Build.0 = Release|Any CPU - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}.Debug|x64.ActiveCfg = Debug|Any CPU - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}.Debug|x64.Build.0 = Debug|Any CPU - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}.Debug|x86.ActiveCfg = Debug|Any CPU - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}.Debug|x86.Build.0 = Debug|Any CPU - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}.Release|Any CPU.Build.0 = Release|Any CPU - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}.Release|x64.ActiveCfg = Release|Any CPU - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}.Release|x64.Build.0 = Release|Any CPU - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}.Release|x86.ActiveCfg = Release|Any CPU - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9}.Release|x86.Build.0 = Release|Any CPU - {991634E3-32C0-4EC7-8F3D-9373721EE9DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {991634E3-32C0-4EC7-8F3D-9373721EE9DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {991634E3-32C0-4EC7-8F3D-9373721EE9DC}.Debug|x64.ActiveCfg = Debug|Any CPU - {991634E3-32C0-4EC7-8F3D-9373721EE9DC}.Debug|x64.Build.0 = Debug|Any CPU - {991634E3-32C0-4EC7-8F3D-9373721EE9DC}.Debug|x86.ActiveCfg = Debug|Any CPU - {991634E3-32C0-4EC7-8F3D-9373721EE9DC}.Debug|x86.Build.0 = Debug|Any CPU - {991634E3-32C0-4EC7-8F3D-9373721EE9DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {991634E3-32C0-4EC7-8F3D-9373721EE9DC}.Release|Any CPU.Build.0 = Release|Any CPU - {991634E3-32C0-4EC7-8F3D-9373721EE9DC}.Release|x64.ActiveCfg = Release|Any CPU - {991634E3-32C0-4EC7-8F3D-9373721EE9DC}.Release|x64.Build.0 = Release|Any CPU - {991634E3-32C0-4EC7-8F3D-9373721EE9DC}.Release|x86.ActiveCfg = Release|Any CPU - {991634E3-32C0-4EC7-8F3D-9373721EE9DC}.Release|x86.Build.0 = Release|Any CPU - {98733F39-94B6-405F-8BFC-98064F9C8250}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {98733F39-94B6-405F-8BFC-98064F9C8250}.Debug|Any CPU.Build.0 = Debug|Any CPU - {98733F39-94B6-405F-8BFC-98064F9C8250}.Debug|x64.ActiveCfg = Debug|Any CPU - {98733F39-94B6-405F-8BFC-98064F9C8250}.Debug|x64.Build.0 = Debug|Any CPU - {98733F39-94B6-405F-8BFC-98064F9C8250}.Debug|x86.ActiveCfg = Debug|Any CPU - {98733F39-94B6-405F-8BFC-98064F9C8250}.Debug|x86.Build.0 = Debug|Any CPU - {98733F39-94B6-405F-8BFC-98064F9C8250}.Release|Any CPU.ActiveCfg = Release|Any CPU - {98733F39-94B6-405F-8BFC-98064F9C8250}.Release|Any CPU.Build.0 = Release|Any CPU - {98733F39-94B6-405F-8BFC-98064F9C8250}.Release|x64.ActiveCfg = Release|Any CPU - {98733F39-94B6-405F-8BFC-98064F9C8250}.Release|x64.Build.0 = Release|Any CPU - {98733F39-94B6-405F-8BFC-98064F9C8250}.Release|x86.ActiveCfg = Release|Any CPU - {98733F39-94B6-405F-8BFC-98064F9C8250}.Release|x86.Build.0 = Release|Any CPU - {0BEC4ACF-3F78-456B-B18F-2E422085AF78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0BEC4ACF-3F78-456B-B18F-2E422085AF78}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0BEC4ACF-3F78-456B-B18F-2E422085AF78}.Debug|x64.ActiveCfg = Debug|Any CPU - {0BEC4ACF-3F78-456B-B18F-2E422085AF78}.Debug|x64.Build.0 = Debug|Any CPU - {0BEC4ACF-3F78-456B-B18F-2E422085AF78}.Debug|x86.ActiveCfg = Debug|Any CPU - {0BEC4ACF-3F78-456B-B18F-2E422085AF78}.Debug|x86.Build.0 = Debug|Any CPU - {0BEC4ACF-3F78-456B-B18F-2E422085AF78}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0BEC4ACF-3F78-456B-B18F-2E422085AF78}.Release|Any CPU.Build.0 = Release|Any CPU - {0BEC4ACF-3F78-456B-B18F-2E422085AF78}.Release|x64.ActiveCfg = Release|Any CPU - {0BEC4ACF-3F78-456B-B18F-2E422085AF78}.Release|x64.Build.0 = Release|Any CPU - {0BEC4ACF-3F78-456B-B18F-2E422085AF78}.Release|x86.ActiveCfg = Release|Any CPU - {0BEC4ACF-3F78-456B-B18F-2E422085AF78}.Release|x86.Build.0 = Release|Any CPU - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D}.Debug|x64.ActiveCfg = Debug|Any CPU - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D}.Debug|x64.Build.0 = Debug|Any CPU - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D}.Debug|x86.ActiveCfg = Debug|Any CPU - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D}.Debug|x86.Build.0 = Debug|Any CPU - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D}.Release|Any CPU.Build.0 = Release|Any CPU - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D}.Release|x64.ActiveCfg = Release|Any CPU - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D}.Release|x64.Build.0 = Release|Any CPU - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D}.Release|x86.ActiveCfg = Release|Any CPU - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D}.Release|x86.Build.0 = Release|Any CPU - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}.Debug|x64.ActiveCfg = Debug|Any CPU - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}.Debug|x64.Build.0 = Debug|Any CPU - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}.Debug|x86.ActiveCfg = Debug|Any CPU - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}.Debug|x86.Build.0 = Debug|Any CPU - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}.Release|Any CPU.Build.0 = Release|Any CPU - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}.Release|x64.ActiveCfg = Release|Any CPU - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}.Release|x64.Build.0 = Release|Any CPU - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}.Release|x86.ActiveCfg = Release|Any CPU - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3}.Release|x86.Build.0 = Release|Any CPU - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571}.Debug|Any CPU.Build.0 = Debug|Any CPU - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571}.Debug|x64.ActiveCfg = Debug|Any CPU - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571}.Debug|x64.Build.0 = Debug|Any CPU - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571}.Debug|x86.ActiveCfg = Debug|Any CPU - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571}.Debug|x86.Build.0 = Debug|Any CPU - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571}.Release|Any CPU.ActiveCfg = Release|Any CPU - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571}.Release|Any CPU.Build.0 = Release|Any CPU - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571}.Release|x64.ActiveCfg = Release|Any CPU - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571}.Release|x64.Build.0 = Release|Any CPU - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571}.Release|x86.ActiveCfg = Release|Any CPU - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571}.Release|x86.Build.0 = Release|Any CPU - {EAC00D28-63C9-42E4-B169-40071EC2B3BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EAC00D28-63C9-42E4-B169-40071EC2B3BD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EAC00D28-63C9-42E4-B169-40071EC2B3BD}.Debug|x64.ActiveCfg = Debug|Any CPU - {EAC00D28-63C9-42E4-B169-40071EC2B3BD}.Debug|x64.Build.0 = Debug|Any CPU - {EAC00D28-63C9-42E4-B169-40071EC2B3BD}.Debug|x86.ActiveCfg = Debug|Any CPU - {EAC00D28-63C9-42E4-B169-40071EC2B3BD}.Debug|x86.Build.0 = Debug|Any CPU - {EAC00D28-63C9-42E4-B169-40071EC2B3BD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EAC00D28-63C9-42E4-B169-40071EC2B3BD}.Release|Any CPU.Build.0 = Release|Any CPU - {EAC00D28-63C9-42E4-B169-40071EC2B3BD}.Release|x64.ActiveCfg = Release|Any CPU - {EAC00D28-63C9-42E4-B169-40071EC2B3BD}.Release|x64.Build.0 = Release|Any CPU - {EAC00D28-63C9-42E4-B169-40071EC2B3BD}.Release|x86.ActiveCfg = Release|Any CPU - {EAC00D28-63C9-42E4-B169-40071EC2B3BD}.Release|x86.Build.0 = Release|Any CPU - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5}.Debug|x64.ActiveCfg = Debug|Any CPU - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5}.Debug|x64.Build.0 = Debug|Any CPU - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5}.Debug|x86.ActiveCfg = Debug|Any CPU - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5}.Debug|x86.Build.0 = Debug|Any CPU - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5}.Release|Any CPU.Build.0 = Release|Any CPU - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5}.Release|x64.ActiveCfg = Release|Any CPU - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5}.Release|x64.Build.0 = Release|Any CPU - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5}.Release|x86.ActiveCfg = Release|Any CPU - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5}.Release|x86.Build.0 = Release|Any CPU - {076A78FA-959E-4741-89A5-0767B5F70C9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {076A78FA-959E-4741-89A5-0767B5F70C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {076A78FA-959E-4741-89A5-0767B5F70C9C}.Debug|x64.ActiveCfg = Debug|Any CPU - {076A78FA-959E-4741-89A5-0767B5F70C9C}.Debug|x64.Build.0 = Debug|Any CPU - {076A78FA-959E-4741-89A5-0767B5F70C9C}.Debug|x86.ActiveCfg = Debug|Any CPU - {076A78FA-959E-4741-89A5-0767B5F70C9C}.Debug|x86.Build.0 = Debug|Any CPU - {076A78FA-959E-4741-89A5-0767B5F70C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {076A78FA-959E-4741-89A5-0767B5F70C9C}.Release|Any CPU.Build.0 = Release|Any CPU - {076A78FA-959E-4741-89A5-0767B5F70C9C}.Release|x64.ActiveCfg = Release|Any CPU - {076A78FA-959E-4741-89A5-0767B5F70C9C}.Release|x64.Build.0 = Release|Any CPU - {076A78FA-959E-4741-89A5-0767B5F70C9C}.Release|x86.ActiveCfg = Release|Any CPU - {076A78FA-959E-4741-89A5-0767B5F70C9C}.Release|x86.Build.0 = Release|Any CPU - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8}.Debug|x64.ActiveCfg = Debug|Any CPU - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8}.Debug|x64.Build.0 = Debug|Any CPU - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8}.Debug|x86.ActiveCfg = Debug|Any CPU - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8}.Debug|x86.Build.0 = Debug|Any CPU - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8}.Release|Any CPU.Build.0 = Release|Any CPU - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8}.Release|x64.ActiveCfg = Release|Any CPU - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8}.Release|x64.Build.0 = Release|Any CPU - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8}.Release|x86.ActiveCfg = Release|Any CPU - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8}.Release|x86.Build.0 = Release|Any CPU - {6E0693DF-23FE-41EF-AA97-8310AF5120E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6E0693DF-23FE-41EF-AA97-8310AF5120E9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6E0693DF-23FE-41EF-AA97-8310AF5120E9}.Debug|x64.ActiveCfg = Debug|Any CPU - {6E0693DF-23FE-41EF-AA97-8310AF5120E9}.Debug|x64.Build.0 = Debug|Any CPU - {6E0693DF-23FE-41EF-AA97-8310AF5120E9}.Debug|x86.ActiveCfg = Debug|Any CPU - {6E0693DF-23FE-41EF-AA97-8310AF5120E9}.Debug|x86.Build.0 = Debug|Any CPU - {6E0693DF-23FE-41EF-AA97-8310AF5120E9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6E0693DF-23FE-41EF-AA97-8310AF5120E9}.Release|Any CPU.Build.0 = Release|Any CPU - {6E0693DF-23FE-41EF-AA97-8310AF5120E9}.Release|x64.ActiveCfg = Release|Any CPU - {6E0693DF-23FE-41EF-AA97-8310AF5120E9}.Release|x64.Build.0 = Release|Any CPU - {6E0693DF-23FE-41EF-AA97-8310AF5120E9}.Release|x86.ActiveCfg = Release|Any CPU - {6E0693DF-23FE-41EF-AA97-8310AF5120E9}.Release|x86.Build.0 = Release|Any CPU - {4FE21337-C76D-431E-B0A8-7726D1A335DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4FE21337-C76D-431E-B0A8-7726D1A335DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4FE21337-C76D-431E-B0A8-7726D1A335DC}.Debug|x64.ActiveCfg = Debug|Any CPU - {4FE21337-C76D-431E-B0A8-7726D1A335DC}.Debug|x64.Build.0 = Debug|Any CPU - {4FE21337-C76D-431E-B0A8-7726D1A335DC}.Debug|x86.ActiveCfg = Debug|Any CPU - {4FE21337-C76D-431E-B0A8-7726D1A335DC}.Debug|x86.Build.0 = Debug|Any CPU - {4FE21337-C76D-431E-B0A8-7726D1A335DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4FE21337-C76D-431E-B0A8-7726D1A335DC}.Release|Any CPU.Build.0 = Release|Any CPU - {4FE21337-C76D-431E-B0A8-7726D1A335DC}.Release|x64.ActiveCfg = Release|Any CPU - {4FE21337-C76D-431E-B0A8-7726D1A335DC}.Release|x64.Build.0 = Release|Any CPU - {4FE21337-C76D-431E-B0A8-7726D1A335DC}.Release|x86.ActiveCfg = Release|Any CPU - {4FE21337-C76D-431E-B0A8-7726D1A335DC}.Release|x86.Build.0 = Release|Any CPU - {F8DAB23E-8992-4E93-8376-C428BB5F2423}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F8DAB23E-8992-4E93-8376-C428BB5F2423}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F8DAB23E-8992-4E93-8376-C428BB5F2423}.Debug|x64.ActiveCfg = Debug|Any CPU - {F8DAB23E-8992-4E93-8376-C428BB5F2423}.Debug|x64.Build.0 = Debug|Any CPU - {F8DAB23E-8992-4E93-8376-C428BB5F2423}.Debug|x86.ActiveCfg = Debug|Any CPU - {F8DAB23E-8992-4E93-8376-C428BB5F2423}.Debug|x86.Build.0 = Debug|Any CPU - {F8DAB23E-8992-4E93-8376-C428BB5F2423}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F8DAB23E-8992-4E93-8376-C428BB5F2423}.Release|Any CPU.Build.0 = Release|Any CPU - {F8DAB23E-8992-4E93-8376-C428BB5F2423}.Release|x64.ActiveCfg = Release|Any CPU - {F8DAB23E-8992-4E93-8376-C428BB5F2423}.Release|x64.Build.0 = Release|Any CPU - {F8DAB23E-8992-4E93-8376-C428BB5F2423}.Release|x86.ActiveCfg = Release|Any CPU - {F8DAB23E-8992-4E93-8376-C428BB5F2423}.Release|x86.Build.0 = Release|Any CPU - {6BEC2D0D-365C-4069-9253-82EE136E59B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6BEC2D0D-365C-4069-9253-82EE136E59B8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6BEC2D0D-365C-4069-9253-82EE136E59B8}.Debug|x64.ActiveCfg = Debug|Any CPU - {6BEC2D0D-365C-4069-9253-82EE136E59B8}.Debug|x64.Build.0 = Debug|Any CPU - {6BEC2D0D-365C-4069-9253-82EE136E59B8}.Debug|x86.ActiveCfg = Debug|Any CPU - {6BEC2D0D-365C-4069-9253-82EE136E59B8}.Debug|x86.Build.0 = Debug|Any CPU - {6BEC2D0D-365C-4069-9253-82EE136E59B8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6BEC2D0D-365C-4069-9253-82EE136E59B8}.Release|Any CPU.Build.0 = Release|Any CPU - {6BEC2D0D-365C-4069-9253-82EE136E59B8}.Release|x64.ActiveCfg = Release|Any CPU - {6BEC2D0D-365C-4069-9253-82EE136E59B8}.Release|x64.Build.0 = Release|Any CPU - {6BEC2D0D-365C-4069-9253-82EE136E59B8}.Release|x86.ActiveCfg = Release|Any CPU - {6BEC2D0D-365C-4069-9253-82EE136E59B8}.Release|x86.Build.0 = Release|Any CPU - {F09A1806-432C-4627-B86B-C8DE3C7116D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F09A1806-432C-4627-B86B-C8DE3C7116D4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F09A1806-432C-4627-B86B-C8DE3C7116D4}.Debug|x64.ActiveCfg = Debug|Any CPU - {F09A1806-432C-4627-B86B-C8DE3C7116D4}.Debug|x64.Build.0 = Debug|Any CPU - {F09A1806-432C-4627-B86B-C8DE3C7116D4}.Debug|x86.ActiveCfg = Debug|Any CPU - {F09A1806-432C-4627-B86B-C8DE3C7116D4}.Debug|x86.Build.0 = Debug|Any CPU - {F09A1806-432C-4627-B86B-C8DE3C7116D4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F09A1806-432C-4627-B86B-C8DE3C7116D4}.Release|Any CPU.Build.0 = Release|Any CPU - {F09A1806-432C-4627-B86B-C8DE3C7116D4}.Release|x64.ActiveCfg = Release|Any CPU - {F09A1806-432C-4627-B86B-C8DE3C7116D4}.Release|x64.Build.0 = Release|Any CPU - {F09A1806-432C-4627-B86B-C8DE3C7116D4}.Release|x86.ActiveCfg = Release|Any CPU - {F09A1806-432C-4627-B86B-C8DE3C7116D4}.Release|x86.Build.0 = Release|Any CPU - {FB1F392C-F78E-4578-AE3D-359365F521E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FB1F392C-F78E-4578-AE3D-359365F521E2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FB1F392C-F78E-4578-AE3D-359365F521E2}.Debug|x64.ActiveCfg = Debug|Any CPU - {FB1F392C-F78E-4578-AE3D-359365F521E2}.Debug|x64.Build.0 = Debug|Any CPU - {FB1F392C-F78E-4578-AE3D-359365F521E2}.Debug|x86.ActiveCfg = Debug|Any CPU - {FB1F392C-F78E-4578-AE3D-359365F521E2}.Debug|x86.Build.0 = Debug|Any CPU - {FB1F392C-F78E-4578-AE3D-359365F521E2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FB1F392C-F78E-4578-AE3D-359365F521E2}.Release|Any CPU.Build.0 = Release|Any CPU - {FB1F392C-F78E-4578-AE3D-359365F521E2}.Release|x64.ActiveCfg = Release|Any CPU - {FB1F392C-F78E-4578-AE3D-359365F521E2}.Release|x64.Build.0 = Release|Any CPU - {FB1F392C-F78E-4578-AE3D-359365F521E2}.Release|x86.ActiveCfg = Release|Any CPU - {FB1F392C-F78E-4578-AE3D-359365F521E2}.Release|x86.Build.0 = Release|Any CPU - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9}.Debug|x64.ActiveCfg = Debug|Any CPU - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9}.Debug|x64.Build.0 = Debug|Any CPU - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9}.Debug|x86.ActiveCfg = Debug|Any CPU - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9}.Debug|x86.Build.0 = Debug|Any CPU - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9}.Release|Any CPU.Build.0 = Release|Any CPU - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9}.Release|x64.ActiveCfg = Release|Any CPU - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9}.Release|x64.Build.0 = Release|Any CPU - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9}.Release|x86.ActiveCfg = Release|Any CPU - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9}.Release|x86.Build.0 = Release|Any CPU - {2D501B10-F7E8-4E86-9742-94530CDF9BD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2D501B10-F7E8-4E86-9742-94530CDF9BD4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2D501B10-F7E8-4E86-9742-94530CDF9BD4}.Debug|x64.ActiveCfg = Debug|Any CPU - {2D501B10-F7E8-4E86-9742-94530CDF9BD4}.Debug|x64.Build.0 = Debug|Any CPU - {2D501B10-F7E8-4E86-9742-94530CDF9BD4}.Debug|x86.ActiveCfg = Debug|Any CPU - {2D501B10-F7E8-4E86-9742-94530CDF9BD4}.Debug|x86.Build.0 = Debug|Any CPU - {2D501B10-F7E8-4E86-9742-94530CDF9BD4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2D501B10-F7E8-4E86-9742-94530CDF9BD4}.Release|Any CPU.Build.0 = Release|Any CPU - {2D501B10-F7E8-4E86-9742-94530CDF9BD4}.Release|x64.ActiveCfg = Release|Any CPU - {2D501B10-F7E8-4E86-9742-94530CDF9BD4}.Release|x64.Build.0 = Release|Any CPU - {2D501B10-F7E8-4E86-9742-94530CDF9BD4}.Release|x86.ActiveCfg = Release|Any CPU - {2D501B10-F7E8-4E86-9742-94530CDF9BD4}.Release|x86.Build.0 = Release|Any CPU - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43}.Debug|x64.ActiveCfg = Debug|Any CPU - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43}.Debug|x64.Build.0 = Debug|Any CPU - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43}.Debug|x86.ActiveCfg = Debug|Any CPU - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43}.Debug|x86.Build.0 = Debug|Any CPU - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43}.Release|Any CPU.Build.0 = Release|Any CPU - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43}.Release|x64.ActiveCfg = Release|Any CPU - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43}.Release|x64.Build.0 = Release|Any CPU - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43}.Release|x86.ActiveCfg = Release|Any CPU - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43}.Release|x86.Build.0 = Release|Any CPU + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}.Debug|x64.ActiveCfg = Debug|Any CPU + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}.Debug|x64.Build.0 = Debug|Any CPU + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}.Debug|x86.ActiveCfg = Debug|Any CPU + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}.Debug|x86.Build.0 = Debug|Any CPU + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}.Release|Any CPU.Build.0 = Release|Any CPU + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}.Release|x64.ActiveCfg = Release|Any CPU + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}.Release|x64.Build.0 = Release|Any CPU + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}.Release|x86.ActiveCfg = Release|Any CPU + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}.Release|x86.Build.0 = Release|Any CPU + {717ED421-8AE2-435F-888F-91F676C87C32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {717ED421-8AE2-435F-888F-91F676C87C32}.Debug|Any CPU.Build.0 = Debug|Any CPU + {717ED421-8AE2-435F-888F-91F676C87C32}.Debug|x64.ActiveCfg = Debug|Any CPU + {717ED421-8AE2-435F-888F-91F676C87C32}.Debug|x64.Build.0 = Debug|Any CPU + {717ED421-8AE2-435F-888F-91F676C87C32}.Debug|x86.ActiveCfg = Debug|Any CPU + {717ED421-8AE2-435F-888F-91F676C87C32}.Debug|x86.Build.0 = Debug|Any CPU + {717ED421-8AE2-435F-888F-91F676C87C32}.Release|Any CPU.ActiveCfg = Release|Any CPU + {717ED421-8AE2-435F-888F-91F676C87C32}.Release|Any CPU.Build.0 = Release|Any CPU + {717ED421-8AE2-435F-888F-91F676C87C32}.Release|x64.ActiveCfg = Release|Any CPU + {717ED421-8AE2-435F-888F-91F676C87C32}.Release|x64.Build.0 = Release|Any CPU + {717ED421-8AE2-435F-888F-91F676C87C32}.Release|x86.ActiveCfg = Release|Any CPU + {717ED421-8AE2-435F-888F-91F676C87C32}.Release|x86.Build.0 = Release|Any CPU + {B9E587C6-D492-478A-856D-A7FC67EB5FE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9E587C6-D492-478A-856D-A7FC67EB5FE0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9E587C6-D492-478A-856D-A7FC67EB5FE0}.Debug|x64.ActiveCfg = Debug|Any CPU + {B9E587C6-D492-478A-856D-A7FC67EB5FE0}.Debug|x64.Build.0 = Debug|Any CPU + {B9E587C6-D492-478A-856D-A7FC67EB5FE0}.Debug|x86.ActiveCfg = Debug|Any CPU + {B9E587C6-D492-478A-856D-A7FC67EB5FE0}.Debug|x86.Build.0 = Debug|Any CPU + {B9E587C6-D492-478A-856D-A7FC67EB5FE0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9E587C6-D492-478A-856D-A7FC67EB5FE0}.Release|Any CPU.Build.0 = Release|Any CPU + {B9E587C6-D492-478A-856D-A7FC67EB5FE0}.Release|x64.ActiveCfg = Release|Any CPU + {B9E587C6-D492-478A-856D-A7FC67EB5FE0}.Release|x64.Build.0 = Release|Any CPU + {B9E587C6-D492-478A-856D-A7FC67EB5FE0}.Release|x86.ActiveCfg = Release|Any CPU + {B9E587C6-D492-478A-856D-A7FC67EB5FE0}.Release|x86.Build.0 = Release|Any CPU + {65784B83-F76F-4C1A-AAAD-6417614116C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65784B83-F76F-4C1A-AAAD-6417614116C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65784B83-F76F-4C1A-AAAD-6417614116C6}.Debug|x64.ActiveCfg = Debug|Any CPU + {65784B83-F76F-4C1A-AAAD-6417614116C6}.Debug|x64.Build.0 = Debug|Any CPU + {65784B83-F76F-4C1A-AAAD-6417614116C6}.Debug|x86.ActiveCfg = Debug|Any CPU + {65784B83-F76F-4C1A-AAAD-6417614116C6}.Debug|x86.Build.0 = Debug|Any CPU + {65784B83-F76F-4C1A-AAAD-6417614116C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65784B83-F76F-4C1A-AAAD-6417614116C6}.Release|Any CPU.Build.0 = Release|Any CPU + {65784B83-F76F-4C1A-AAAD-6417614116C6}.Release|x64.ActiveCfg = Release|Any CPU + {65784B83-F76F-4C1A-AAAD-6417614116C6}.Release|x64.Build.0 = Release|Any CPU + {65784B83-F76F-4C1A-AAAD-6417614116C6}.Release|x86.ActiveCfg = Release|Any CPU + {65784B83-F76F-4C1A-AAAD-6417614116C6}.Release|x86.Build.0 = Release|Any CPU + {8CA197A9-96CE-4284-80B5-EC0132F20A62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8CA197A9-96CE-4284-80B5-EC0132F20A62}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8CA197A9-96CE-4284-80B5-EC0132F20A62}.Debug|x64.ActiveCfg = Debug|Any CPU + {8CA197A9-96CE-4284-80B5-EC0132F20A62}.Debug|x64.Build.0 = Debug|Any CPU + {8CA197A9-96CE-4284-80B5-EC0132F20A62}.Debug|x86.ActiveCfg = Debug|Any CPU + {8CA197A9-96CE-4284-80B5-EC0132F20A62}.Debug|x86.Build.0 = Debug|Any CPU + {8CA197A9-96CE-4284-80B5-EC0132F20A62}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8CA197A9-96CE-4284-80B5-EC0132F20A62}.Release|Any CPU.Build.0 = Release|Any CPU + {8CA197A9-96CE-4284-80B5-EC0132F20A62}.Release|x64.ActiveCfg = Release|Any CPU + {8CA197A9-96CE-4284-80B5-EC0132F20A62}.Release|x64.Build.0 = Release|Any CPU + {8CA197A9-96CE-4284-80B5-EC0132F20A62}.Release|x86.ActiveCfg = Release|Any CPU + {8CA197A9-96CE-4284-80B5-EC0132F20A62}.Release|x86.Build.0 = Release|Any CPU + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7}.Debug|x64.ActiveCfg = Debug|Any CPU + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7}.Debug|x64.Build.0 = Debug|Any CPU + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7}.Debug|x86.ActiveCfg = Debug|Any CPU + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7}.Debug|x86.Build.0 = Debug|Any CPU + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7}.Release|Any CPU.Build.0 = Release|Any CPU + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7}.Release|x64.ActiveCfg = Release|Any CPU + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7}.Release|x64.Build.0 = Release|Any CPU + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7}.Release|x86.ActiveCfg = Release|Any CPU + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7}.Release|x86.Build.0 = Release|Any CPU + {49C21BFB-126B-473D-876E-C9965CCD3096}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49C21BFB-126B-473D-876E-C9965CCD3096}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49C21BFB-126B-473D-876E-C9965CCD3096}.Debug|x64.ActiveCfg = Debug|Any CPU + {49C21BFB-126B-473D-876E-C9965CCD3096}.Debug|x64.Build.0 = Debug|Any CPU + {49C21BFB-126B-473D-876E-C9965CCD3096}.Debug|x86.ActiveCfg = Debug|Any CPU + {49C21BFB-126B-473D-876E-C9965CCD3096}.Debug|x86.Build.0 = Debug|Any CPU + {49C21BFB-126B-473D-876E-C9965CCD3096}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49C21BFB-126B-473D-876E-C9965CCD3096}.Release|Any CPU.Build.0 = Release|Any CPU + {49C21BFB-126B-473D-876E-C9965CCD3096}.Release|x64.ActiveCfg = Release|Any CPU + {49C21BFB-126B-473D-876E-C9965CCD3096}.Release|x64.Build.0 = Release|Any CPU + {49C21BFB-126B-473D-876E-C9965CCD3096}.Release|x86.ActiveCfg = Release|Any CPU + {49C21BFB-126B-473D-876E-C9965CCD3096}.Release|x86.Build.0 = Release|Any CPU + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}.Debug|x64.ActiveCfg = Debug|Any CPU + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}.Debug|x64.Build.0 = Debug|Any CPU + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}.Debug|x86.ActiveCfg = Debug|Any CPU + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}.Debug|x86.Build.0 = Debug|Any CPU + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}.Release|Any CPU.Build.0 = Release|Any CPU + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}.Release|x64.ActiveCfg = Release|Any CPU + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}.Release|x64.Build.0 = Release|Any CPU + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}.Release|x86.ActiveCfg = Release|Any CPU + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}.Release|x86.Build.0 = Release|Any CPU + {A0A5A856-7C41-46E5-B773-97B677E532B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0A5A856-7C41-46E5-B773-97B677E532B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0A5A856-7C41-46E5-B773-97B677E532B5}.Debug|x64.ActiveCfg = Debug|Any CPU + {A0A5A856-7C41-46E5-B773-97B677E532B5}.Debug|x64.Build.0 = Debug|Any CPU + {A0A5A856-7C41-46E5-B773-97B677E532B5}.Debug|x86.ActiveCfg = Debug|Any CPU + {A0A5A856-7C41-46E5-B773-97B677E532B5}.Debug|x86.Build.0 = Debug|Any CPU + {A0A5A856-7C41-46E5-B773-97B677E532B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0A5A856-7C41-46E5-B773-97B677E532B5}.Release|Any CPU.Build.0 = Release|Any CPU + {A0A5A856-7C41-46E5-B773-97B677E532B5}.Release|x64.ActiveCfg = Release|Any CPU + {A0A5A856-7C41-46E5-B773-97B677E532B5}.Release|x64.Build.0 = Release|Any CPU + {A0A5A856-7C41-46E5-B773-97B677E532B5}.Release|x86.ActiveCfg = Release|Any CPU + {A0A5A856-7C41-46E5-B773-97B677E532B5}.Release|x86.Build.0 = Release|Any CPU + {772A6D09-0FB3-46B0-A234-9196704D4657}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {772A6D09-0FB3-46B0-A234-9196704D4657}.Debug|Any CPU.Build.0 = Debug|Any CPU + {772A6D09-0FB3-46B0-A234-9196704D4657}.Debug|x64.ActiveCfg = Debug|Any CPU + {772A6D09-0FB3-46B0-A234-9196704D4657}.Debug|x64.Build.0 = Debug|Any CPU + {772A6D09-0FB3-46B0-A234-9196704D4657}.Debug|x86.ActiveCfg = Debug|Any CPU + {772A6D09-0FB3-46B0-A234-9196704D4657}.Debug|x86.Build.0 = Debug|Any CPU + {772A6D09-0FB3-46B0-A234-9196704D4657}.Release|Any CPU.ActiveCfg = Release|Any CPU + {772A6D09-0FB3-46B0-A234-9196704D4657}.Release|Any CPU.Build.0 = Release|Any CPU + {772A6D09-0FB3-46B0-A234-9196704D4657}.Release|x64.ActiveCfg = Release|Any CPU + {772A6D09-0FB3-46B0-A234-9196704D4657}.Release|x64.Build.0 = Release|Any CPU + {772A6D09-0FB3-46B0-A234-9196704D4657}.Release|x86.ActiveCfg = Release|Any CPU + {772A6D09-0FB3-46B0-A234-9196704D4657}.Release|x86.Build.0 = Release|Any CPU + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}.Debug|x64.ActiveCfg = Debug|Any CPU + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}.Debug|x64.Build.0 = Debug|Any CPU + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}.Debug|x86.ActiveCfg = Debug|Any CPU + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}.Debug|x86.Build.0 = Debug|Any CPU + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}.Release|Any CPU.Build.0 = Release|Any CPU + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}.Release|x64.ActiveCfg = Release|Any CPU + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}.Release|x64.Build.0 = Release|Any CPU + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}.Release|x86.ActiveCfg = Release|Any CPU + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}.Release|x86.Build.0 = Release|Any CPU + {1CD7C68A-A371-49CE-8F54-A7E781EE332A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1CD7C68A-A371-49CE-8F54-A7E781EE332A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1CD7C68A-A371-49CE-8F54-A7E781EE332A}.Debug|x64.ActiveCfg = Debug|Any CPU + {1CD7C68A-A371-49CE-8F54-A7E781EE332A}.Debug|x64.Build.0 = Debug|Any CPU + {1CD7C68A-A371-49CE-8F54-A7E781EE332A}.Debug|x86.ActiveCfg = Debug|Any CPU + {1CD7C68A-A371-49CE-8F54-A7E781EE332A}.Debug|x86.Build.0 = Debug|Any CPU + {1CD7C68A-A371-49CE-8F54-A7E781EE332A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1CD7C68A-A371-49CE-8F54-A7E781EE332A}.Release|Any CPU.Build.0 = Release|Any CPU + {1CD7C68A-A371-49CE-8F54-A7E781EE332A}.Release|x64.ActiveCfg = Release|Any CPU + {1CD7C68A-A371-49CE-8F54-A7E781EE332A}.Release|x64.Build.0 = Release|Any CPU + {1CD7C68A-A371-49CE-8F54-A7E781EE332A}.Release|x86.ActiveCfg = Release|Any CPU + {1CD7C68A-A371-49CE-8F54-A7E781EE332A}.Release|x86.Build.0 = Release|Any CPU + {80DB4163-821F-4C85-80AB-B6E5E946C4F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80DB4163-821F-4C85-80AB-B6E5E946C4F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80DB4163-821F-4C85-80AB-B6E5E946C4F9}.Debug|x64.ActiveCfg = Debug|Any CPU + {80DB4163-821F-4C85-80AB-B6E5E946C4F9}.Debug|x64.Build.0 = Debug|Any CPU + {80DB4163-821F-4C85-80AB-B6E5E946C4F9}.Debug|x86.ActiveCfg = Debug|Any CPU + {80DB4163-821F-4C85-80AB-B6E5E946C4F9}.Debug|x86.Build.0 = Debug|Any CPU + {80DB4163-821F-4C85-80AB-B6E5E946C4F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80DB4163-821F-4C85-80AB-B6E5E946C4F9}.Release|Any CPU.Build.0 = Release|Any CPU + {80DB4163-821F-4C85-80AB-B6E5E946C4F9}.Release|x64.ActiveCfg = Release|Any CPU + {80DB4163-821F-4C85-80AB-B6E5E946C4F9}.Release|x64.Build.0 = Release|Any CPU + {80DB4163-821F-4C85-80AB-B6E5E946C4F9}.Release|x86.ActiveCfg = Release|Any CPU + {80DB4163-821F-4C85-80AB-B6E5E946C4F9}.Release|x86.Build.0 = Release|Any CPU + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}.Debug|x64.ActiveCfg = Debug|Any CPU + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}.Debug|x64.Build.0 = Debug|Any CPU + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}.Debug|x86.ActiveCfg = Debug|Any CPU + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}.Debug|x86.Build.0 = Debug|Any CPU + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}.Release|Any CPU.Build.0 = Release|Any CPU + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}.Release|x64.ActiveCfg = Release|Any CPU + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}.Release|x64.Build.0 = Release|Any CPU + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}.Release|x86.ActiveCfg = Release|Any CPU + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}.Release|x86.Build.0 = Release|Any CPU + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624}.Debug|x64.ActiveCfg = Debug|Any CPU + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624}.Debug|x64.Build.0 = Debug|Any CPU + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624}.Debug|x86.ActiveCfg = Debug|Any CPU + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624}.Debug|x86.Build.0 = Debug|Any CPU + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624}.Release|Any CPU.Build.0 = Release|Any CPU + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624}.Release|x64.ActiveCfg = Release|Any CPU + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624}.Release|x64.Build.0 = Release|Any CPU + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624}.Release|x86.ActiveCfg = Release|Any CPU + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624}.Release|x86.Build.0 = Release|Any CPU + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Debug|x64.ActiveCfg = Debug|Any CPU + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Debug|x64.Build.0 = Debug|Any CPU + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Debug|x86.ActiveCfg = Debug|Any CPU + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Debug|x86.Build.0 = Debug|Any CPU + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Release|Any CPU.Build.0 = Release|Any CPU + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Release|x64.ActiveCfg = Release|Any CPU + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Release|x64.Build.0 = Release|Any CPU + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Release|x86.ActiveCfg = Release|Any CPU + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Release|x86.Build.0 = Release|Any CPU + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Debug|x64.ActiveCfg = Debug|Any CPU + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Debug|x64.Build.0 = Debug|Any CPU + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Debug|x86.ActiveCfg = Debug|Any CPU + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Debug|x86.Build.0 = Debug|Any CPU + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Release|Any CPU.Build.0 = Release|Any CPU + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Release|x64.ActiveCfg = Release|Any CPU + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Release|x64.Build.0 = Release|Any CPU + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Release|x86.ActiveCfg = Release|Any CPU + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Release|x86.Build.0 = Release|Any CPU + {84AD21E8-23A0-4029-9767-50F7863E7A02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {84AD21E8-23A0-4029-9767-50F7863E7A02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84AD21E8-23A0-4029-9767-50F7863E7A02}.Debug|x64.ActiveCfg = Debug|Any CPU + {84AD21E8-23A0-4029-9767-50F7863E7A02}.Debug|x64.Build.0 = Debug|Any CPU + {84AD21E8-23A0-4029-9767-50F7863E7A02}.Debug|x86.ActiveCfg = Debug|Any CPU + {84AD21E8-23A0-4029-9767-50F7863E7A02}.Debug|x86.Build.0 = Debug|Any CPU + {84AD21E8-23A0-4029-9767-50F7863E7A02}.Release|Any CPU.ActiveCfg = Release|Any CPU + {84AD21E8-23A0-4029-9767-50F7863E7A02}.Release|Any CPU.Build.0 = Release|Any CPU + {84AD21E8-23A0-4029-9767-50F7863E7A02}.Release|x64.ActiveCfg = Release|Any CPU + {84AD21E8-23A0-4029-9767-50F7863E7A02}.Release|x64.Build.0 = Release|Any CPU + {84AD21E8-23A0-4029-9767-50F7863E7A02}.Release|x86.ActiveCfg = Release|Any CPU + {84AD21E8-23A0-4029-9767-50F7863E7A02}.Release|x86.Build.0 = Release|Any CPU + {44BFF304-5D42-4065-9260-E2C9E552EB24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44BFF304-5D42-4065-9260-E2C9E552EB24}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44BFF304-5D42-4065-9260-E2C9E552EB24}.Debug|x64.ActiveCfg = Debug|Any CPU + {44BFF304-5D42-4065-9260-E2C9E552EB24}.Debug|x64.Build.0 = Debug|Any CPU + {44BFF304-5D42-4065-9260-E2C9E552EB24}.Debug|x86.ActiveCfg = Debug|Any CPU + {44BFF304-5D42-4065-9260-E2C9E552EB24}.Debug|x86.Build.0 = Debug|Any CPU + {44BFF304-5D42-4065-9260-E2C9E552EB24}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44BFF304-5D42-4065-9260-E2C9E552EB24}.Release|Any CPU.Build.0 = Release|Any CPU + {44BFF304-5D42-4065-9260-E2C9E552EB24}.Release|x64.ActiveCfg = Release|Any CPU + {44BFF304-5D42-4065-9260-E2C9E552EB24}.Release|x64.Build.0 = Release|Any CPU + {44BFF304-5D42-4065-9260-E2C9E552EB24}.Release|x86.ActiveCfg = Release|Any CPU + {44BFF304-5D42-4065-9260-E2C9E552EB24}.Release|x86.Build.0 = Release|Any CPU + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}.Debug|x64.ActiveCfg = Debug|Any CPU + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}.Debug|x64.Build.0 = Debug|Any CPU + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}.Debug|x86.ActiveCfg = Debug|Any CPU + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}.Debug|x86.Build.0 = Debug|Any CPU + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}.Release|Any CPU.Build.0 = Release|Any CPU + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}.Release|x64.ActiveCfg = Release|Any CPU + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}.Release|x64.Build.0 = Release|Any CPU + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}.Release|x86.ActiveCfg = Release|Any CPU + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}.Release|x86.Build.0 = Release|Any CPU + {7FACEAF5-30A5-4502-822C-485FE980A6C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7FACEAF5-30A5-4502-822C-485FE980A6C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7FACEAF5-30A5-4502-822C-485FE980A6C3}.Debug|x64.ActiveCfg = Debug|Any CPU + {7FACEAF5-30A5-4502-822C-485FE980A6C3}.Debug|x64.Build.0 = Debug|Any CPU + {7FACEAF5-30A5-4502-822C-485FE980A6C3}.Debug|x86.ActiveCfg = Debug|Any CPU + {7FACEAF5-30A5-4502-822C-485FE980A6C3}.Debug|x86.Build.0 = Debug|Any CPU + {7FACEAF5-30A5-4502-822C-485FE980A6C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7FACEAF5-30A5-4502-822C-485FE980A6C3}.Release|Any CPU.Build.0 = Release|Any CPU + {7FACEAF5-30A5-4502-822C-485FE980A6C3}.Release|x64.ActiveCfg = Release|Any CPU + {7FACEAF5-30A5-4502-822C-485FE980A6C3}.Release|x64.Build.0 = Release|Any CPU + {7FACEAF5-30A5-4502-822C-485FE980A6C3}.Release|x86.ActiveCfg = Release|Any CPU + {7FACEAF5-30A5-4502-822C-485FE980A6C3}.Release|x86.Build.0 = Release|Any CPU + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8}.Debug|x64.ActiveCfg = Debug|Any CPU + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8}.Debug|x64.Build.0 = Debug|Any CPU + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8}.Debug|x86.ActiveCfg = Debug|Any CPU + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8}.Debug|x86.Build.0 = Debug|Any CPU + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8}.Release|Any CPU.Build.0 = Release|Any CPU + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8}.Release|x64.ActiveCfg = Release|Any CPU + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8}.Release|x64.Build.0 = Release|Any CPU + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8}.Release|x86.ActiveCfg = Release|Any CPU + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8}.Release|x86.Build.0 = Release|Any CPU + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}.Debug|x64.ActiveCfg = Debug|Any CPU + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}.Debug|x64.Build.0 = Debug|Any CPU + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}.Debug|x86.ActiveCfg = Debug|Any CPU + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}.Debug|x86.Build.0 = Debug|Any CPU + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}.Release|Any CPU.Build.0 = Release|Any CPU + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}.Release|x64.ActiveCfg = Release|Any CPU + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}.Release|x64.Build.0 = Release|Any CPU + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}.Release|x86.ActiveCfg = Release|Any CPU + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}.Release|x86.Build.0 = Release|Any CPU + {35184561-8AAB-4E74-9E0D-231D16E336BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35184561-8AAB-4E74-9E0D-231D16E336BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35184561-8AAB-4E74-9E0D-231D16E336BF}.Debug|x64.ActiveCfg = Debug|Any CPU + {35184561-8AAB-4E74-9E0D-231D16E336BF}.Debug|x64.Build.0 = Debug|Any CPU + {35184561-8AAB-4E74-9E0D-231D16E336BF}.Debug|x86.ActiveCfg = Debug|Any CPU + {35184561-8AAB-4E74-9E0D-231D16E336BF}.Debug|x86.Build.0 = Debug|Any CPU + {35184561-8AAB-4E74-9E0D-231D16E336BF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35184561-8AAB-4E74-9E0D-231D16E336BF}.Release|Any CPU.Build.0 = Release|Any CPU + {35184561-8AAB-4E74-9E0D-231D16E336BF}.Release|x64.ActiveCfg = Release|Any CPU + {35184561-8AAB-4E74-9E0D-231D16E336BF}.Release|x64.Build.0 = Release|Any CPU + {35184561-8AAB-4E74-9E0D-231D16E336BF}.Release|x86.ActiveCfg = Release|Any CPU + {35184561-8AAB-4E74-9E0D-231D16E336BF}.Release|x86.Build.0 = Release|Any CPU + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}.Debug|x64.ActiveCfg = Debug|Any CPU + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}.Debug|x64.Build.0 = Debug|Any CPU + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}.Debug|x86.ActiveCfg = Debug|Any CPU + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}.Debug|x86.Build.0 = Debug|Any CPU + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}.Release|Any CPU.Build.0 = Release|Any CPU + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}.Release|x64.ActiveCfg = Release|Any CPU + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}.Release|x64.Build.0 = Release|Any CPU + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}.Release|x86.ActiveCfg = Release|Any CPU + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}.Release|x86.Build.0 = Release|Any CPU + {54652BFC-61CF-4DF0-B34A-64406A43F708}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54652BFC-61CF-4DF0-B34A-64406A43F708}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54652BFC-61CF-4DF0-B34A-64406A43F708}.Debug|x64.ActiveCfg = Debug|Any CPU + {54652BFC-61CF-4DF0-B34A-64406A43F708}.Debug|x64.Build.0 = Debug|Any CPU + {54652BFC-61CF-4DF0-B34A-64406A43F708}.Debug|x86.ActiveCfg = Debug|Any CPU + {54652BFC-61CF-4DF0-B34A-64406A43F708}.Debug|x86.Build.0 = Debug|Any CPU + {54652BFC-61CF-4DF0-B34A-64406A43F708}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54652BFC-61CF-4DF0-B34A-64406A43F708}.Release|Any CPU.Build.0 = Release|Any CPU + {54652BFC-61CF-4DF0-B34A-64406A43F708}.Release|x64.ActiveCfg = Release|Any CPU + {54652BFC-61CF-4DF0-B34A-64406A43F708}.Release|x64.Build.0 = Release|Any CPU + {54652BFC-61CF-4DF0-B34A-64406A43F708}.Release|x86.ActiveCfg = Release|Any CPU + {54652BFC-61CF-4DF0-B34A-64406A43F708}.Release|x86.Build.0 = Release|Any CPU + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}.Debug|x64.ActiveCfg = Debug|Any CPU + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}.Debug|x64.Build.0 = Debug|Any CPU + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}.Debug|x86.ActiveCfg = Debug|Any CPU + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}.Debug|x86.Build.0 = Debug|Any CPU + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}.Release|Any CPU.Build.0 = Release|Any CPU + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}.Release|x64.ActiveCfg = Release|Any CPU + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}.Release|x64.Build.0 = Release|Any CPU + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}.Release|x86.ActiveCfg = Release|Any CPU + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}.Release|x86.Build.0 = Release|Any CPU + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05}.Debug|x64.ActiveCfg = Debug|Any CPU + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05}.Debug|x64.Build.0 = Debug|Any CPU + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05}.Debug|x86.ActiveCfg = Debug|Any CPU + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05}.Debug|x86.Build.0 = Debug|Any CPU + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05}.Release|Any CPU.Build.0 = Release|Any CPU + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05}.Release|x64.ActiveCfg = Release|Any CPU + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05}.Release|x64.Build.0 = Release|Any CPU + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05}.Release|x86.ActiveCfg = Release|Any CPU + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05}.Release|x86.Build.0 = Release|Any CPU + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}.Debug|x64.ActiveCfg = Debug|Any CPU + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}.Debug|x64.Build.0 = Debug|Any CPU + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}.Debug|x86.ActiveCfg = Debug|Any CPU + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}.Debug|x86.Build.0 = Debug|Any CPU + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}.Release|Any CPU.Build.0 = Release|Any CPU + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}.Release|x64.ActiveCfg = Release|Any CPU + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}.Release|x64.Build.0 = Release|Any CPU + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}.Release|x86.ActiveCfg = Release|Any CPU + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}.Release|x86.Build.0 = Release|Any CPU + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}.Debug|x64.ActiveCfg = Debug|Any CPU + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}.Debug|x64.Build.0 = Debug|Any CPU + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}.Debug|x86.ActiveCfg = Debug|Any CPU + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}.Debug|x86.Build.0 = Debug|Any CPU + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}.Release|Any CPU.Build.0 = Release|Any CPU + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}.Release|x64.ActiveCfg = Release|Any CPU + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}.Release|x64.Build.0 = Release|Any CPU + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}.Release|x86.ActiveCfg = Release|Any CPU + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}.Release|x86.Build.0 = Release|Any CPU + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Debug|x64.ActiveCfg = Debug|Any CPU + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Debug|x64.Build.0 = Debug|Any CPU + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Debug|x86.ActiveCfg = Debug|Any CPU + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Debug|x86.Build.0 = Debug|Any CPU + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Release|Any CPU.Build.0 = Release|Any CPU + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Release|x64.ActiveCfg = Release|Any CPU + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Release|x64.Build.0 = Release|Any CPU + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Release|x86.ActiveCfg = Release|Any CPU + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Release|x86.Build.0 = Release|Any CPU + {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Debug|x64.ActiveCfg = Debug|Any CPU + {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Debug|x64.Build.0 = Debug|Any CPU + {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Debug|x86.ActiveCfg = Debug|Any CPU + {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Debug|x86.Build.0 = Debug|Any CPU + {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Release|Any CPU.Build.0 = Release|Any CPU + {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Release|x64.ActiveCfg = Release|Any CPU + {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Release|x64.Build.0 = Release|Any CPU + {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Release|x86.ActiveCfg = Release|Any CPU + {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Release|x86.Build.0 = Release|Any CPU + {A425AE4A-691C-4540-9CA0-2B7D32EFE230}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A425AE4A-691C-4540-9CA0-2B7D32EFE230}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A425AE4A-691C-4540-9CA0-2B7D32EFE230}.Debug|x64.ActiveCfg = Debug|Any CPU + {A425AE4A-691C-4540-9CA0-2B7D32EFE230}.Debug|x64.Build.0 = Debug|Any CPU + {A425AE4A-691C-4540-9CA0-2B7D32EFE230}.Debug|x86.ActiveCfg = Debug|Any CPU + {A425AE4A-691C-4540-9CA0-2B7D32EFE230}.Debug|x86.Build.0 = Debug|Any CPU + {A425AE4A-691C-4540-9CA0-2B7D32EFE230}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A425AE4A-691C-4540-9CA0-2B7D32EFE230}.Release|Any CPU.Build.0 = Release|Any CPU + {A425AE4A-691C-4540-9CA0-2B7D32EFE230}.Release|x64.ActiveCfg = Release|Any CPU + {A425AE4A-691C-4540-9CA0-2B7D32EFE230}.Release|x64.Build.0 = Release|Any CPU + {A425AE4A-691C-4540-9CA0-2B7D32EFE230}.Release|x86.ActiveCfg = Release|Any CPU + {A425AE4A-691C-4540-9CA0-2B7D32EFE230}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {92A41F1C-8B77-4479-8CD3-FB8987269C60} = {96279848-CA27-42C6-9488-498A8E696F67} {29FF59AD-E83D-4084-9DE5-564CA5687981} = {96279848-CA27-42C6-9488-498A8E696F67} {7AE36E18-182E-4E36-AD0E-08F326B381B2} = {96279848-CA27-42C6-9488-498A8E696F67} - {93429CD0-F010-450F-9C16-67C8E7F6E644} = {96279848-CA27-42C6-9488-498A8E696F67} - {C6A685B1-7AEA-4ADF-8206-09FB563F3342} = {96279848-CA27-42C6-9488-498A8E696F67} - {72402835-6446-4B54-8FEF-3E42B17730EA} = {96279848-CA27-42C6-9488-498A8E696F67} - {FD759318-1E7C-499B-9DDB-9B7ADC216602} = {96279848-CA27-42C6-9488-498A8E696F67} - {FA2308B6-C47A-47F1-A028-E86CA0323E2A} = {96279848-CA27-42C6-9488-498A8E696F67} - {2B55B11C-D04A-4451-B8D2-0CDA632940EE} = {96279848-CA27-42C6-9488-498A8E696F67} - {960663A9-F17E-4F94-AC5B-E581A6171028} = {96279848-CA27-42C6-9488-498A8E696F67} - {E1C9E2B5-9ABE-4AC7-994D-4E9C44BDD49E} = {96279848-CA27-42C6-9488-498A8E696F67} - {0AAD8FD3-EDB5-4019-82F3-6D1FDB9773F9} = {96279848-CA27-42C6-9488-498A8E696F67} - {C76D41A4-7963-41F0-9F6D-CDC80624FB25} = {96279848-CA27-42C6-9488-498A8E696F67} - {98733F39-94B6-405F-8BFC-98064F9C8250} = {96279848-CA27-42C6-9488-498A8E696F67} - {0BEC4ACF-3F78-456B-B18F-2E422085AF78} = {96279848-CA27-42C6-9488-498A8E696F67} - {FB1F392C-F78E-4578-AE3D-359365F521E2} = {96279848-CA27-42C6-9488-498A8E696F67} - {ECF76680-BA01-4B53-85CC-9B9A4C206FB9} = {96279848-CA27-42C6-9488-498A8E696F67} - {6E0693DF-23FE-41EF-AA97-8310AF5120E9} = {96279848-CA27-42C6-9488-498A8E696F67} - {6BEC2D0D-365C-4069-9253-82EE136E59B8} = {96279848-CA27-42C6-9488-498A8E696F67} - {F09A1806-432C-4627-B86B-C8DE3C7116D4} = {96279848-CA27-42C6-9488-498A8E696F67} - {4FE21337-C76D-431E-B0A8-7726D1A335DC} = {96279848-CA27-42C6-9488-498A8E696F67} - {F5AD1150-9B7B-4112-9E08-C5542119750E} = {93429CD0-F010-450F-9C16-67C8E7F6E644} - {5B5DFEA6-CD85-407C-9377-E22D80E2CFBC} = {93429CD0-F010-450F-9C16-67C8E7F6E644} - {813B9B3A-8ECD-49ED-A231-7B220F7F5662} = {93429CD0-F010-450F-9C16-67C8E7F6E644} - {4B949B7B-715C-480E-BC1E-AAAECBB17922} = {93429CD0-F010-450F-9C16-67C8E7F6E644} - {B0FBC90F-9579-434C-A703-3F4777F2AC01} = {93429CD0-F010-450F-9C16-67C8E7F6E644} - {6B1C5EB5-E729-4BD8-B55E-BB4CBFC84658} = {93429CD0-F010-450F-9C16-67C8E7F6E644} - {7C8F1CE7-82F7-471E-8FC2-84DDEDBEDCCE} = {93429CD0-F010-450F-9C16-67C8E7F6E644} - {58B017A0-2084-4388-B2CF-2073F3712AD2} = {93429CD0-F010-450F-9C16-67C8E7F6E644} - {24FDFC45-63AE-43BB-9CFF-18CB1BE14571} = {93429CD0-F010-450F-9C16-67C8E7F6E644} - {F8DAB23E-8992-4E93-8376-C428BB5F2423} = {93429CD0-F010-450F-9C16-67C8E7F6E644} - {1B874C58-C5C7-41A0-B188-E80D4882729E} = {E1C9E2B5-9ABE-4AC7-994D-4E9C44BDD49E} - {94B5D8E5-F3B1-438A-94E1-095574259B6C} = {E1C9E2B5-9ABE-4AC7-994D-4E9C44BDD49E} - {7095B11D-8CF7-4526-A687-1307765CCADA} = {E1C9E2B5-9ABE-4AC7-994D-4E9C44BDD49E} - {A6964A5A-176B-4E02-8137-81443075EAA7} = {E1C9E2B5-9ABE-4AC7-994D-4E9C44BDD49E} - {6F53EF07-DE0B-4F95-93A5-2B96BD49F7E3} = {E1C9E2B5-9ABE-4AC7-994D-4E9C44BDD49E} - {2D501B10-F7E8-4E86-9742-94530CDF9BD4} = {E1C9E2B5-9ABE-4AC7-994D-4E9C44BDD49E} - {991634E3-32C0-4EC7-8F3D-9373721EE9DC} = {C76D41A4-7963-41F0-9F6D-CDC80624FB25} - {6702318E-E585-4CAD-8BD6-5E39FD15BC4D} = {C76D41A4-7963-41F0-9F6D-CDC80624FB25} - {EAC00D28-63C9-42E4-B169-40071EC2B3BD} = {C76D41A4-7963-41F0-9F6D-CDC80624FB25} - {076A78FA-959E-4741-89A5-0767B5F70C9C} = {C76D41A4-7963-41F0-9F6D-CDC80624FB25} - {03D5E1E9-3BD2-4D6C-9252-91D6867803B8} = {C76D41A4-7963-41F0-9F6D-CDC80624FB25} - {0964634E-371B-4ADB-9CA6-288AE0AD2EE5} = {C76D41A4-7963-41F0-9F6D-CDC80624FB25} - {1B051A0D-D01B-4A3A-9821-C139CEDC6E43} = {C76D41A4-7963-41F0-9F6D-CDC80624FB25} + {A015D2D5-EBB2-455C-BF72-EE8EEC2854D4} = {96279848-CA27-42C6-9488-498A8E696F67} + {55E62B6F-2C33-4E89-ADD5-0CE9BAA76401} = {96279848-CA27-42C6-9488-498A8E696F67} + {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} = {55E62B6F-2C33-4E89-ADD5-0CE9BAA76401} + {717ED421-8AE2-435F-888F-91F676C87C32} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {B9E587C6-D492-478A-856D-A7FC67EB5FE0} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {65784B83-F76F-4C1A-AAAD-6417614116C6} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {8CA197A9-96CE-4284-80B5-EC0132F20A62} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {40C841D4-C7D0-489B-80FB-5B4D22DB60E7} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {49C21BFB-126B-473D-876E-C9965CCD3096} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {A0A5A856-7C41-46E5-B773-97B677E532B5} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {772A6D09-0FB3-46B0-A234-9196704D4657} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1} = {55E62B6F-2C33-4E89-ADD5-0CE9BAA76401} + {1CD7C68A-A371-49CE-8F54-A7E781EE332A} = {55E62B6F-2C33-4E89-ADD5-0CE9BAA76401} + {80DB4163-821F-4C85-80AB-B6E5E946C4F9} = {55E62B6F-2C33-4E89-ADD5-0CE9BAA76401} + {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0} = {55E62B6F-2C33-4E89-ADD5-0CE9BAA76401} + {ADB65D83-B476-4F0B-8B9F-8719A8AB7624} = {55E62B6F-2C33-4E89-ADD5-0CE9BAA76401} + {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C} = {55E62B6F-2C33-4E89-ADD5-0CE9BAA76401} + {BBF63851-BC21-45CC-A671-9ED1A538E052} = {96279848-CA27-42C6-9488-498A8E696F67} + {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4} = {BBF63851-BC21-45CC-A671-9ED1A538E052} + {84AD21E8-23A0-4029-9767-50F7863E7A02} = {BBF63851-BC21-45CC-A671-9ED1A538E052} + {44BFF304-5D42-4065-9260-E2C9E552EB24} = {BBF63851-BC21-45CC-A671-9ED1A538E052} + {0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4} = {BBF63851-BC21-45CC-A671-9ED1A538E052} + {7FACEAF5-30A5-4502-822C-485FE980A6C3} = {BBF63851-BC21-45CC-A671-9ED1A538E052} + {05276DA5-3CF1-4950-8923-9A5F4C1A15D8} = {BBF63851-BC21-45CC-A671-9ED1A538E052} + {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB} = {BBF63851-BC21-45CC-A671-9ED1A538E052} + {35184561-8AAB-4E74-9E0D-231D16E336BF} = {BBF63851-BC21-45CC-A671-9ED1A538E052} + {F0888151-28C5-4EF0-86CB-9C66218F89AE} = {96279848-CA27-42C6-9488-498A8E696F67} + {F90413F1-AB57-43C0-B401-E7C2EC83198C} = {F0888151-28C5-4EF0-86CB-9C66218F89AE} + {D332DFCA-E6EE-482B-BAE4-2592F5BB5D26} = {F90413F1-AB57-43C0-B401-E7C2EC83198C} + {54652BFC-61CF-4DF0-B34A-64406A43F708} = {F90413F1-AB57-43C0-B401-E7C2EC83198C} + {F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9} = {F90413F1-AB57-43C0-B401-E7C2EC83198C} + {7C6A7725-FA4E-45FB-A4CB-8F581D017C05} = {F90413F1-AB57-43C0-B401-E7C2EC83198C} + {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83} = {F90413F1-AB57-43C0-B401-E7C2EC83198C} + {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D} = {F90413F1-AB57-43C0-B401-E7C2EC83198C} + {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5} = {F0888151-28C5-4EF0-86CB-9C66218F89AE} + {ECF6ADAE-C222-41E9-BA5B-811866193A2B} = {BBF63851-BC21-45CC-A671-9ED1A538E052} + {A425AE4A-691C-4540-9CA0-2B7D32EFE230} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E18BA4C9-E1E4-42CD-8393-505DEDE479A2} EndGlobalSection EndGlobal diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index daef73ce..0d1ead59 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,11 +35,8 @@ using the following tags: ### F# Coding Style -Please read the [F# design -guidelines](https://fsharp.org/specs/component-design-guidelines/) and the [F# -style -guideline](https://github.com/fsprojects/fantomas/blob/master/docs/FormattingConventions.md), -before you proceed as we mostly follow these guidelines. +Please read the [F# code formatting guideline](https://docs.microsoft.com/en-us/dotnet/fsharp/style-guide/formatting), +before you proceed as we mostly follow it. #### Basic Rules diff --git a/Directory.Build.props b/Directory.Build.props index 3a5d5f57..f142c83a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,10 +3,15 @@ B2R2 SoftSec Lab. @ KAIST SoftSec Lab. @ KAIST - 0.4.0 - $(VersionSuffix) - B2R2: the Next-Generation Reversing Platform + 0.5.0 + Copyright (c) SoftSec Lab. @ KAIST, since 2016 true + https://github.com/B2R2-org/B2R2 + git + https://b2r2.org/ + Binary;Disassembly;Assembly;CFG;Reversing;x86;AARCH64;MIPS;AVR;ELF;Mach-O;PE + $([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../')) + diff --git a/README.md b/README.md index f7bd21b2..6d4892da 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ [![Build status](https://ci.appveyor.com/api/projects/status/0c0tcxh813ev8w6i?svg=true)](https://ci.appveyor.com/project/sangkilc/b2r2) [![Build Status](https://travis-ci.com/B2R2-org/B2R2.svg?branch=master)](https://travis-ci.com/B2R2-org/B2R2) ![](https://img.shields.io/github/license/B2R2-org/B2R2.svg?style=flat) -[![](https://img.shields.io/nuget/vpre/B2R2.FrontEnd.svg?style=flat)](https://www.nuget.org/packages/B2R2.FrontEnd) +![](https://img.shields.io/tokei/lines/github/B2R2-org/B2R2) +[![](https://img.shields.io/nuget/v/B2R2.RearEnd.Launcher)](https://www.nuget.org/packages/B2R2.RearEnd.Launcher/) B2R2 ==== @@ -46,16 +47,28 @@ B2R2? Features? --------- -Currently, our focus is on the front-end of binary analysis, which includes -binary parser, lifter, and optimizer. B2R2 natively supports parallel lifting, -which is a new technique we introduced in 2019 NDSS Bar. Please refer to our -[paper](#citation) for more details about the technique as well as our design -decisions. We also have our own back-end tools such as symbolic executor, but we -are *not* planning to open-source them yet. Nevertheless, B2R2 includes several -useful middle-end or back-end features such as ROP chain compilation, CFG -building, and automatic graph drawing, and etc. B2R2 also comes with a simple -command-line utility that we call [`BinExplorer`](src/Utilities/BinExplorer), -which can help explore such features using a simple command line interface. +B2R2 supports instruction parsing, binary disassembly, assembly, control-flow +recovery, and many more. B2R2 also comes with several user-level command-line +tools that are similar to readelf and objdump, although our tools are +platform-agnostic. B2R2 currently supports four binary file formats: ELF, PE, +Mach-O, and WebAssembly. + +Below is a list of features that we currently support. Some of them are work in +progress, but we look forward to your contributions! Feel free to write a PR +(Pull Request) while making sure that you have read our [contribution +guideline](CONTRIBUTING.md). + +| Feature | x86 | x86-64 | ARMv7 (& Thumb) | ARMv8 | MIPS32 | MIPS64 | EVM | TMS320C600 | AVR | PPC | +|-----------------------|:-----------:|:------------|:--------------------:|:--------------------:|:--------------------:|:--------------------:|:-----------:|:-----------:|:-----------:|:----------:| +| Instruction Parsing | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | +| Disassembly | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | +| Lifting | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | :full_moon: | :new_moon: | +| CFG Recovery | :full_moon: | :full_moon: | :first_quarter_moon: | :first_quarter_moon: | :first_quarter_moon: | :first_quarter_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | +| Data-Flow | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | +| Instruction Emulation | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | +| Assembly | :full_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | +| REPL | :full_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | +| ROP Compilation | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | Dependencies? ------------- @@ -68,6 +81,19 @@ leverage. - [Microsoft.FSharpLu.Json](https://www.nuget.org/packages/Microsoft.FSharpLu.Json/) - [FParsec](https://www.nuget.org/packages/FParsec) +Note about v0.5.0 +----------------- + +We have made significant changes in our middle-end (CFG recovery, and function +identification, etc.) engines for this version, and we are still improving it. +The current version is stable enough, but we are actively changing the +implementation while doing some internal research, which is hoding us back for +open-sourcing it. Hence, we decided to partly publicize our tool (everything but +the middle-end engine). We always welcome PRs for our front-end modules :smile: + +We may bump few more versions before making everything public, but we will +eventually open-source everything. So please stay tuned! + API Documentation ----------------- @@ -94,7 +120,7 @@ Let's try to use B2R2 APIs. 1. Add our nuget package *B2R2.FrontEnd* to the project: ``` - $ dotnet add package B2R2.FrontEnd + $ dotnet add package B2R2.FrontEnd.BinInterface ``` 1. Modify the `Program.fs` file with your favorite editor as follows: @@ -107,9 +133,9 @@ Let's try to use B2R2 APIs. let main argv = let isa = ISA.OfString "amd64" let bytes = [| 0x65uy; 0xffuy; 0x15uy; 0x10uy; 0x00uy; 0x00uy; 0x00uy |] - let handler = BinHandler.Init (isa, bytes) - let ins = BinHandler.ParseInstr handler 0UL - ins.Translate handler.TranslationContext |> printfn "%A" + let hdl = BinHandle.Init (isa, bytes) + let ins = BinHandle.ParseInstr (hdl, 0UL) + ins.Translate hdl.TranslationContext |> printfn "%A" 0 ``` @@ -120,8 +146,8 @@ Let's try to use B2R2 APIs. Build ----- -Building B2R2 is fun and easy. All you need to do is to install .NET Core SDK -3.0 or above. Yea, that's it! +Building B2R2 is fun and easy. All you need to do is to install .NET 5 SDK or +above. Yea, that's it! - To build B2R2 in release mode, type ```make release``` or ```dotnet build -c Release``` in the source root. @@ -132,31 +158,6 @@ Building B2R2 is fun and easy. All you need to do is to install .NET Core SDK For your information, please visit the official web site of F# to get more tips about installing the development environment for F#: http://fsharp.org/. -Why Reinventing the Wheel? --------------------------- - -There are many other great tools available, but we wanted to build a -*functional-first* binary analysis platform that is painless to install and runs -on any platform without any hassle. B2R2 is in its *infancy* stage, but we -believe it provides a rich set of library functions for binary analysis. It also -has a strong front-end that is easily adaptable and extendible! Currently it -reliably supports x86 and x86-64, meaning that we have heavily tested them; and -it partially supports ARMv7 (and Thumb), ARMv8, MIPS32, MIPS64, and EVM meaning -that they work, but we haven't tested them thorougly yet. - - -Features to be Added? ---------------------- - -Below is a list of features that we plan to add in the future: the list is -totally incomplete. Some of them are work in progress, but we look forward your -contributions! Feel free to write a PR (Pull Requst) while making sure that you -have read our [contribution guideline](CONTRIBUTING.md). - -- Implement CFG recovery algorithms. -- Implement assembler for currently supported ISAs using a parser combinator. -- Support for more architectures such as PPC. - Credits ------- diff --git a/src/FrontEnd/Library/b2r2-240x240.png b/assets/b2r2-240x240.png similarity index 100% rename from src/FrontEnd/Library/b2r2-240x240.png rename to assets/b2r2-240x240.png diff --git a/lib/libfpu/.gitignore b/lib/libfpu/.gitignore deleted file mode 100644 index 724c9b40..00000000 --- a/lib/libfpu/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libfpu.so diff --git a/lib/libfpu/Makefile b/lib/libfpu/Makefile deleted file mode 100644 index 86613278..00000000 --- a/lib/libfpu/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -OUTPUT := libfpu.so - -all: $(OUTPUT) - -clean: - @rm -rf $(OUTPUT) - -$(OUTPUT): fpu.c - @$(CC) -O3 -shared -fPIC $< -o$@ - -.PHONY: clean diff --git a/lib/libfpu/fpu.c b/lib/libfpu/fpu.c deleted file mode 100644 index 04c583eb..00000000 --- a/lib/libfpu/fpu.c +++ /dev/null @@ -1,7 +0,0 @@ -#include - -// FIXME -int myfunc(int x) -{ - return x; -} diff --git a/samples/CSharp/b2r2.csx b/samples/CSharp/b2r2.csx index a4a9556c..d5dc42b9 100644 --- a/samples/CSharp/b2r2.csx +++ b/samples/CSharp/b2r2.csx @@ -1,26 +1,19 @@ // ---------------------------------------------------------------------------- // B2R2 C# Sample. // ---------------------------------------------------------------------------- -// Currently we assume that you have published all the binaries into the -// `../../build` directory. To do so, you can simply run `make publish` in the -// source root directory. -// ---------------------------------------------------------------------------- -#r "../../build/B2R2.Core.dll" -#r "../../build/B2R2.BinIR.dll" -#r "../../build/B2R2.FrontEnd.Core.dll" -#r "../../build/B2R2.FrontEnd.Library.dll" +#r "nuget: B2R2.FrontEnd.BinInterface" using System; using B2R2; -using B2R2.FrontEnd; -using B2R2.BinIR.LowUIR; +using B2R2.FrontEnd.BinLifter; +using B2R2.FrontEnd.BinInterface; ISA isa = ISA.OfString( "amd64" ); byte [] binary = new byte[] { 0x65, 0xff, 0x15, 0x10, 0x00, 0x00, 0x00 }; -BinHandler handler = BinHandler.Init( isa, binary ); +BinHandle handler = BinHandle.Init( isa, binary ); // Parse the binary. -Instruction ins = BinHandler.ParseInstr( handler, 0UL ); +Instruction ins = BinHandle.ParseInstr( handler, 0UL ); // Disassemble it. string s = ins.Disasm(); // Print it. diff --git a/samples/FSharp/b2r2.fsx b/samples/FSharp/b2r2.fsx index 21f09b89..1534332f 100644 --- a/samples/FSharp/b2r2.fsx +++ b/samples/FSharp/b2r2.fsx @@ -1,23 +1,14 @@ // ---------------------------------------------------------------------------- // B2R2 F# Sample. // ---------------------------------------------------------------------------- -// Currently we assume that you have published all the binaries into the -// `../../build` directory. To do so, you can simply run `make publish` in the -// source root directory. -// ---------------------------------------------------------------------------- -#r "../../build/B2R2.Core.dll" -#r "../../build/B2R2.BinIR.dll" -#r "../../build/B2R2.BinFile.dll" -#r "../../build/B2R2.FrontEnd.Core.dll" -#r "../../build/B2R2.FrontEnd.Library.dll" +#r "nuget: B2R2.FrontEnd.BinInterface" open B2R2 -open B2R2.FrontEnd -open B2R2.BinIR.LowUIR +open B2R2.FrontEnd.BinInterface let isa = ISA.OfString "amd64" let bytes = [| 0x65uy; 0xffuy; 0x15uy; 0x10uy; 0x00uy; 0x00uy; 0x00uy |] -let handler = BinHandler.Init (isa, bytes) -let ins = BinHandler.ParseInstr handler 0UL +let hdl = BinHandle.Init (isa, bytes) +let ins = BinHandle.ParseInstr (hdl, 0UL) ins.Disasm () |> printfn "%s" diff --git a/samples/Python/b2r2.py b/samples/Python/b2r2.py deleted file mode 100644 index f960250c..00000000 --- a/samples/Python/b2r2.py +++ /dev/null @@ -1,23 +0,0 @@ -# ----------------------------------------------------------------------------- -# B2R2 Python Sample. -# ----------------------------------------------------------------------------- -# Currently we assume that you have published all the binaries into the -# `../../build` directory. To do so, you can simply run `make publish` in the -# source root directory. -# ----------------------------------------------------------------------------- - -import clr -import os, sys -sys.path.append(os.path.abspath(r'../../build/')) -clr.AddReferenceToFile(r'B2R2.Core.dll') -clr.AddReferenceToFile(r'B2R2.FrontEnd.Core.dll') -clr.AddReferenceToFile(r'B2R2.FrontEnd.Library.dll') - -from B2R2 import * -from B2R2.FrontEnd import * - -isa = ISA.OfString("amd64") -binary = ByteArray.ofHexString('65ff1510000000') -handler = BinHandler.Init(isa, binary) -ins = handler.ParseInstr(handler, 0) -print(ins.Disasm()) diff --git a/samples/VB/B2R2.vbproj b/samples/VB/B2R2.vbproj new file mode 100644 index 00000000..1e8675a5 --- /dev/null +++ b/samples/VB/B2R2.vbproj @@ -0,0 +1,13 @@ + + + + Exe + VB + net5.0 + + + + + + + diff --git a/samples/VB/Program.vb b/samples/VB/Program.vb new file mode 100644 index 00000000..b06b70f9 --- /dev/null +++ b/samples/VB/Program.vb @@ -0,0 +1,17 @@ +' ---------------------------------------------------------------------------- ' +' B2R2 VB Sample. +' ---------------------------------------------------------------------------- ' + +Imports System +Imports B2R2 +Imports B2R2.FrontEnd.BinInterface + +Module Program + Sub Main(args As String()) + Dim i = ISA.OfString("amd64") + Dim bs = New Byte() { &H65, &Hff, &H15, &H10, &H00, &H00, &H00 } + Dim hdl = BinHandle.Init(i, bs) + Dim ins = BinHandle.ParseInstr(hdl, 0) + Console.WriteLine(ins.Disasm()) + End Sub +End Module diff --git a/src/Assembler.Tests/B2R2.Assembler.Tests.fsproj b/src/Assembler.Tests/B2R2.Assembler.Tests.fsproj deleted file mode 100644 index 11fb082f..00000000 --- a/src/Assembler.Tests/B2R2.Assembler.Tests.fsproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - netcoreapp3.0 - false - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Assembler/ARM32/B2R2.Assembler.ARM32.fsproj b/src/Assembler/ARM32/B2R2.Assembler.ARM32.fsproj deleted file mode 100644 index f4355e8b..00000000 --- a/src/Assembler/ARM32/B2R2.Assembler.ARM32.fsproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - netstandard2.1 - - - - - - - - - - - - - - diff --git a/src/Assembler/Core/B2R2.Assembler.Core.fsproj b/src/Assembler/Core/B2R2.Assembler.Core.fsproj deleted file mode 100644 index ad5856a0..00000000 --- a/src/Assembler/Core/B2R2.Assembler.Core.fsproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - netstandard2.1 - - - - - - - - - - - diff --git a/src/Assembler/Intel/B2R2.Assembler.Intel.fsproj b/src/Assembler/Intel/B2R2.Assembler.Intel.fsproj deleted file mode 100644 index 939d8e01..00000000 --- a/src/Assembler/Intel/B2R2.Assembler.Intel.fsproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - netstandard2.1 - - - - - - - - - - - - - - - - - - diff --git a/src/Assembler/Interface/B2R2.Assembler.Interface.fsproj b/src/Assembler/Interface/B2R2.Assembler.Interface.fsproj deleted file mode 100644 index 39a7ec8c..00000000 --- a/src/Assembler/Interface/B2R2.Assembler.Interface.fsproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - netstandard2.1 - - - - - - - - - - - - - - diff --git a/src/Assembler/LowUIR/B2R2.Assembler.LowUIR.fsproj b/src/Assembler/LowUIR/B2R2.Assembler.LowUIR.fsproj deleted file mode 100644 index eabaf056..00000000 --- a/src/Assembler/LowUIR/B2R2.Assembler.LowUIR.fsproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - netstandard2.1 - - - - - - - - - - - - - - - - - - diff --git a/src/Assembler/LowUIR/LowUIRParser.fs b/src/Assembler/LowUIR/LowUIRParser.fs deleted file mode 100644 index fd4dd532..00000000 --- a/src/Assembler/LowUIR/LowUIRParser.fs +++ /dev/null @@ -1,237 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.Assembler.LowUIR - -open FParsec -open B2R2 -open B2R2.FrontEnd -open B2R2.BinIR.LowUIR -open B2R2.Assembler.LowUIR.Utils - -type ExpectedType = RegType - -type Parser<'t> = Parser<'t, ExpectedType> - -type LowUIRParser (isa, regbay: RegisterBay) = - let makeExpectedType c = - updateUserState (fun _ -> AST.typeOf c) - >>. preturn c - - /// Parses name that can be used as a variable or register Name. - let pNormalString = - many1 (digit <|> letter) |>> (Seq.map string) |>> String.concat "" - let pHexToUInt64 = - many (digit <|> anyOf "ABCDEF") |>> (Seq.map string) |>> String.concat "" - |>> (fun str -> uint64 ( "0x" + str)) - - let pCaseString (s: string) = - pstring s <|> (pstring ( s.ToLower () ) >>. preturn s) s - - let numberFormat = NumberLiteralOptions.AllowMinusSign - ||| NumberLiteralOptions.AllowBinary - ||| NumberLiteralOptions.AllowHexadecimal - ||| NumberLiteralOptions.AllowOctal - ||| NumberLiteralOptions.AllowPlusSign - - let pnumber : Parser = - numberLiteral numberFormat "number" - |>> fun nl -> - int64 nl.String - - (*---------------------------Primitives.-----------------------------*) - - let pRegType = - (anyOf "IiFf" ) >>. pint32 |>> RegType.fromBitWidth - - let pBitVector = - pnumber .>> spaces - .>>. (opt (pchar ':' >>. spaces >>. pRegType)) - >>= (fun (n, typ) -> - if typ.IsNone then getUserState |>> (fun t -> BitVector.ofInt64 n t) - else preturn (BitVector.ofInt64 n typ.Value)) - - let pUnaryOperator = - [ "-"; "~"; "sqrt"; "cos"; "sin"; "tan"; "atan" ] - |> List.map pstring |> List.map attempt |> choice |>> unOpFromString - - let pBinaryOperator = - [ "-|"; "++"; "+"; "-"; "*"; "/"; "?/"; "%"; "?%"; "<<" ; ">>"; "?>>"; - "&"; "|"; "^"; "::"; ".+"; ".-"; ".*"; "./"; ".^"; "lg" ] - |> List.map pstring |> List.map attempt |> choice |>> binOpFromString - - let pRelativeOperator = - [ "="; "!=" ; ">"; ">="; "?>"; "<"; "<="; "?<="; "?<" ] - |> List.map pstring |> List.map attempt |> choice |>> relOpFromString - - let pCastType = //pstring "sext" <|> pstring "zext" |>> castTypeFromString - [ "sext"; "zext"; "itof"; "round"; "ceil"; "floor"; "trunc"; "fext" ] - |> List.map pstring |> List.map attempt |> choice |>> castTypeFromString - - (*---------------------------Expressions.----------------------------*) - - (*Reference to Expression parser created here.*) - let pExpr, pExprRef = createParserForwardedToRef () - - let pNumE = pBitVector |>> AST.num - - let regnames = regbay.GetAllRegNames () - - let pVarE = - List.map pCaseString regnames |> List.map attempt - |> choice |>> regbay.StrToRegExpr - - let pTempVarE = - spaces >>. pstring "T_" >>. pint32 .>> spaces .>> pchar ':' .>> spaces - .>>. pRegType |>> (fun (num, typ) -> TempVar (typ, num)) - - let pUnOpE = - pchar '(' >>. spaces >>. pUnaryOperator - .>> spaces .>>. pExpr .>> spaces .>> pchar ')' - |>> (fun (op, e1) -> AST.unop op e1) - - let pBinOpE = - pchar '(' >>. spaces >>. pExpr .>> spaces .>>. pBinaryOperator .>> spaces - .>>. pExpr .>> spaces .>> pchar ')' - |>> (fun ((e1, op), e2 )-> AST.binop op e1 e2) - - let pRelOpE = - pchar '(' >>. spaces >>. pExpr .>> spaces .>>. pRelativeOperator .>> spaces - .>>. pExpr .>> spaces .>> pchar ')' - |>> (fun ((e1, op), e2 )-> AST.relop op e1 e2) - - let pLoadE = - pchar '[' >>. pExpr .>> spaces .>> pchar ']' .>> spaces .>> pchar ':' - .>> spaces .>>. pRegType - |>> (fun (e, typ) -> AST.load isa.Endian typ e) - - let pIteE = - pchar '(' >>. pstring "ite" >>. spaces >>. pchar '(' >>. spaces - >>. pExpr .>> spaces .>> pchar ')' .>> spaces .>> pchar '(' .>> spaces - .>>. pExpr .>> spaces .>> pchar ')' .>> spaces .>> pchar '(' .>> spaces - .>>. pExpr .>> pchar ')' .>> spaces .>> pchar ')' - |>> (fun ((cond, e1), e2) -> AST.ite cond e1 e2) - - let pCastE = - pCastType .>> spaces .>> pchar ':' .>> spaces .>>. pRegType .>> spaces - .>> pchar '(' .>> spaces .>>. pExpr .>> spaces .>> pchar ')' - |>> (fun ((kind, typ), expr) -> AST.cast kind typ expr) - - let pExtractE = - pchar '(' .>> spaces >>. pExpr .>> spaces .>> pchar '[' .>> spaces - .>>. pint32 .>> spaces .>> pchar ':' .>> spaces .>>. pint32 .>> spaces - .>> pchar ']' .>> spaces .>> pchar ')' - |>> (fun ((expr, n), pos) -> - AST.extract expr (RegType.fromBitWidth (n + 1 - pos)) pos) - - let pUndefinedExprE = - pstring "Undefined expression (" .>> spaces >>. pNormalString .>> spaces - .>> pchar ')' |>> AST.unDef dummyRegType - do - pExprRef := - pNumE - <|> attempt pTempVarE - <|> attempt pUnOpE - <|> attempt pBinOpE <|> attempt pRelOpE <|> attempt pLoadE - <|> attempt pIteE <|> attempt pCastE <|> attempt pExtractE - <|> attempt pUndefinedExprE - <|> pVarE - - (*-----------------------------Statements.---------------------------*) - - let pISMark = - pstring "SMark" >>. spaces >>. pchar '(' >>. spaces >>. pHexToUInt64 - .>> spaces .>> pchar ')' - |>> (fun addr -> ISMark (addr, 0u)) - - let pIEMark = - pstring "EMark" >>. spaces >>. pchar '(' >>. spaces - >>. pstring "pc">>. spaces >>. pstring ":=" >>. spaces - >>. pHexToUInt64 .>> spaces .>> pchar ')' |>> IEMark - - /// Parses ISMark or IEMark. - let pStartOrEndMark = - spaces >>. pstring "===" >>. spaces >>. pchar 'I' - >>. (pISMark <|> pIEMark) - - let pLMark = - spaces >>. pstring "===" >>. spaces >>. pstring "LMark" >>. spaces - >>. pchar '(' >>. spaces >>. pNormalString .>> spaces .>> pchar ')' - |>> AST.lblSymbol |>> LMark - - let pPut = - (attempt pTempVarE <|> pVarE >>= makeExpectedType) .>> spaces - .>> pstring ":=" .>> spaces .>>. pExpr - |>> (fun (dest, value) -> AST.(:=) dest value) - - let pJmp = - pstring "JmpLbl" .>> spaces >>. pExpr |>> Jmp - - let pInterJmp = - pstring "Jmp" .>> spaces >>. pExpr - |>> (fun expr -> InterJmp (dummyExpr, expr, dummyInterJmpInfo)) - - let pStore = - pchar '[' .>> spaces >>. pExpr .>> spaces .>> pchar ']' .>> spaces - .>> pstring ":=" .>> spaces .>>. pExpr - |>> (fun (expr1, expr2) -> Store (isa.Endian, expr1, expr2)) - - let pCJmp = - pstring "if" .>> spaces >>. pExpr .>> spaces .>> pstring "then" .>> spaces - .>> pstring "JmpLbl" .>> spaces .>>. pExpr .>> spaces .>> pstring "else" - .>> spaces .>> pstring "JmpLbl" .>> spaces .>>. pExpr - |>> (fun ((cond, tExpr), fExpr) -> CJmp (cond, tExpr, fExpr)) - - let pInterCJmp = - pstring "if" .>> spaces >>. pExpr .>> spaces .>> pstring "then" .>> spaces - .>> pstring "Jmp" .>> spaces .>>. pExpr .>> spaces .>> pstring "else" - .>> spaces .>> pstring "Jmp" .>> spaces .>>. pExpr - |>> (fun ((cond, tExp), fExp) -> InterCJmp (cond, dummyExpr, tExp, fExp)) - - let pSideEffect = - pstring "SideEffect" .>> spaces >>. pNormalString - |>> (fun str -> sideEffectFromString str |> SideEffect) - - let statement = - attempt pStartOrEndMark - <|> pLMark - <|> attempt pPut - <|> attempt pInterJmp - <|> attempt pJmp - <|> attempt pStore - <|> attempt pInterCJmp - <|> attempt pCJmp - <|> attempt pSideEffect - >>= typeCheckR - - member __.Run str = - match runParserOnString statement 0 "" str with - | Success (result, _, pos) -> - if pos.Column <> int64 (str.Length + 1) then - printfn "Invalid characters at the end of input" - [||] - else [| result |] - | Failure (str, _, _) -> - printfn "%s" str - [||] diff --git a/src/Assembler/LowUIR/LowUIRParserUtils.fs b/src/Assembler/LowUIR/LowUIRParserUtils.fs deleted file mode 100644 index d39b3c21..00000000 --- a/src/Assembler/LowUIR/LowUIRParserUtils.fs +++ /dev/null @@ -1,108 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.Assembler.LowUIR.Utils - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.LowUIR -open FParsec - -/// Used when parsing Undefined expression(not relevant). -let dummyRegType = 32 -/// Used when parsing InterJmp statments(not relevant). -let dummyExpr = Undefined (dummyRegType, "dummy value") -/// Used when parsing InterJmp statements(not relevant). -let dummyInterJmpInfo = InterJmpInfo.Base - -let typeCheckR st = - if AST.typeCheck st then preturn st else fail "statment type check failed" - -let pcFromRegName n = PCVar ((RegType.fromBitWidth 32), n) - -let binOpFromString = function - | "+" -> BinOpType.ADD - | "-" -> BinOpType.SUB - | "*" -> BinOpType.MUL - | "/" -> BinOpType.DIV - | "?/" -> BinOpType.SDIV - | "%" -> BinOpType.MOD - | "?%" -> BinOpType. SMOD - | "<<" -> BinOpType.SHL - | ">>" -> BinOpType. SHR - | "?>>" -> BinOpType. SAR - | "&" -> BinOpType. AND - | "|" -> BinOpType. OR - | "^" -> BinOpType. XOR - | "++" -> BinOpType.CONCAT - | "-|" -> BinOpType.APP - | "::" -> BinOpType.CONS - | ".+" -> BinOpType.FADD - | ".-" -> BinOpType.FSUB - | ".*" -> BinOpType.FMUL - | "./" -> BinOpType.FDIV - | ".^" -> BinOpType.FPOW - | "lg" -> BinOpType.FLOG - | _ -> raise IllegalASTTypeException - -let unOpFromString = function - | "-" -> UnOpType.NEG - | "~" -> UnOpType.NOT - | "sqrt" -> UnOpType.FSQRT - | "cos" -> UnOpType.FCOS - | "sin" -> UnOpType.FSIN - | "tan" -> UnOpType.FTAN - | "atan" -> UnOpType.FATAN - | _ -> raise IllegalASTTypeException - -let relOpFromString = function - | "=" -> RelOpType.EQ - | "!=" -> RelOpType.NEQ - | ">" -> RelOpType.GT - | ">=" -> RelOpType.GE - | "?>" -> RelOpType.SGT - | "?>=" -> RelOpType.SGE - | "<" -> RelOpType.LT - | "<=" -> RelOpType.LE - | "?<" -> RelOpType.SLT - | "?<=" -> RelOpType.SLE - | ".>" -> RelOpType.FGT - | ".>=" -> RelOpType.FGE - | ".<" -> RelOpType.FLT - | ".<=" -> RelOpType.FLE - | _ -> raise IllegalASTTypeException - -let castTypeFromString = function - | "sext" -> CastKind.SignExt - | "zext" -> CastKind.ZeroExt - | "itof" -> CastKind.IntToFloat - | "round" -> CastKind.FtoIRound - | "ceil" -> CastKind.FtoICeil - | "floor" -> CastKind.FtoIFloor - | "trunc" -> CastKind.FtoITrunc - | "fext" -> CastKind.FloatExt - | _ -> raise IllegalASTTypeException - -let sideEffectFromString = function - | _ -> ClockCounter diff --git a/src/Assembler/MIPS/B2R2.Assembler.MIPS.fsproj b/src/Assembler/MIPS/B2R2.Assembler.MIPS.fsproj deleted file mode 100644 index 400bd1a9..00000000 --- a/src/Assembler/MIPS/B2R2.Assembler.MIPS.fsproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - netstandard2.1 - - - - - - - - - - - - - - - - - diff --git a/src/BinEssence/B2R2.BinEssence.fsproj b/src/BinEssence/B2R2.BinEssence.fsproj deleted file mode 100644 index 980472e1..00000000 --- a/src/BinEssence/B2R2.BinEssence.fsproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - netstandard2.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/BinEssence/BBLInfo.fs b/src/BinEssence/BBLInfo.fs deleted file mode 100644 index b27aa413..00000000 --- a/src/BinEssence/BBLInfo.fs +++ /dev/null @@ -1,51 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinEssence - -open B2R2 -open B2R2.BinGraph - -/// Represents instruction-level basic block leader. -type BBLInfo = { - /// Instruction-level basic block boundary - Boundary: AddrRange - /// IR-level leaders (program points) within the bbl. - Leaders: Set -} - -/// Collection of basic-block information. -type BBLStore = { - /// Addr to BBLInfo. - BBLMap: Map - /// Instruciton-level basic block boundaries. - Boundaries: IntervalSet - /// Vertices. - VertexMap: Map> -} -with - static member Init () = - { BBLMap = Map.empty - Boundaries = IntervalSet.empty - VertexMap = Map.empty } diff --git a/src/BinEssence/BasicBlock.fs b/src/BinEssence/BasicBlock.fs deleted file mode 100644 index 48f000eb..00000000 --- a/src/BinEssence/BasicBlock.fs +++ /dev/null @@ -1,42 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinEssence - -open B2R2 -open B2R2.BinGraph - -/// The base type for basic block. -[] -type BasicBlock (pp: ProgramPoint) = - inherit VertexData (VertexData.genID ()) - /// The start position (ProgramPoint) of the basic block. - member __.PPoint with get() = pp - /// The instruction address range of the basic block. - abstract Range: AddrRange with get - /// Check if this is a fake basic block inserted by our analysis. We create a - /// fake block to represent call target vertices in a function-level CFG. - abstract IsFakeBlock: unit -> bool - /// Convert this basic block to a visual representation. - abstract ToVisualBlock: unit -> VisualBlock diff --git a/src/BinEssence/BinEssence.fs b/src/BinEssence/BinEssence.fs deleted file mode 100644 index 359e2210..00000000 --- a/src/BinEssence/BinEssence.fs +++ /dev/null @@ -1,784 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinEssence - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinIR.LowUIR -open B2R2.BinGraph -open System.Collections.Generic -open System.Runtime.InteropServices - -/// Raised when the given address is not a start address of a function. -exception InvalidFunctionAddressException - -/// -/// BinEssence is the main corpus of binary, which contains all the essential -/// information about parsed binary instructions, basic blocks, CFGs, as well -/// as intermediary information for recovering CFG. This is the key data -/// structure we maintain throughout the middle-end analyses. -/// -/// -/// B2R2's middle-end analyses roughly work as follows. -/// -/// We first start by creating an empty BinEssence, and recursively parse -/// (and lift) binary instructions starting from basic entry points we -/// obtained from the target binary. In this stage, we simply follow -/// concrete edges (including intra-instruction branches) appeared in -/// LowUIR. Therefore we may miss indirect branches in this stage, but we -/// will handle them later. After parsing all reachable instructions, we -/// obtain a mapping (InstrMap) from an address to an InsInfo. -/// -/// -/// We build the Super Control Flow Graph (SCFG) on the fly, but whenever -/// there is an edge that intersects existing basic block, we will split the -/// block into two. -/// -/// -/// We mark every call target encountered to build both CallerMap and -/// CalleeMap. Normally, being a call target (i.e., callee) implies being a -/// function entry. However, this is not always the case. We should not -/// always consider a callee as a function. Nevertheless, our lens-based -/// framework can provide a valid CFG at any callee, which can greatly help -/// further analyses. -/// -/// -/// Once we obtained basic information, i.e., BinEssence, to work with, we -/// perform some post analyses to improve the information. For example, we -/// remove unnecessary edges from the SCFG by disconnecting return edges -/// from a function that termiates the process (e.g., exit function), and we -/// recover indirect branch targets to discover more instructions. After the -/// post analyses, we may or may not have an updated Apparatus, in which -/// case we rerun the above steps to update our SCFG (with newly found -/// instructions, etc.). -/// -/// -type BinEssence = { - BinHandler: BinHandler - InstrMap: InstrMap - BBLStore: BBLStore - CalleeMap: CalleeMap - SCFG: DiGraph - NoReturnInfo: NoReturnInfo - IndirectBranchMap: Map - IgnoreIllegal: bool -} -with - member __.IsNoReturn (src: Vertex) = - __.NoReturnInfo.NoReturnCallSites - |> Set.contains src.VData.PPoint - - /// Retrieve an IR-based CFG (subgraph) of a function starting at the given - /// address (addr) from the SCFG, and the root node. When the - /// preserveRecursiveEdge parameter is false, we create fake blocks for - /// recursive calls, which is useful for intra-procedural analyses. - member __.GetFunctionCFG (addr: Addr, - [] - preserveRecursiveEdge) = - let newGraph = IRCFG.init PersistentGraph - let vMap = Dictionary> () - let visited = HashSet () - let rec loop newGraph pos = - if visited.Contains pos then newGraph - else - visited.Add pos |> ignore - getVertex newGraph pos - |> foldSuccessors (Map.find pos __.BBLStore.VertexMap) - and getVertex newGraph pos = - match vMap.TryGetValue pos with - | true, v -> v, newGraph - | false, _ -> - let oldV = Map.find pos __.BBLStore.VertexMap - let v, newGraph = DiGraph.addVertex newGraph oldV.VData - vMap.[pos] <- v - v, newGraph - and foldSuccessors origVertex (curVertex, newGraph) = - DiGraph.getSuccs __.SCFG origVertex - |> List.fold (fun newGraph succ -> - __.SCFG.FindEdgeData origVertex succ - |> addEdge newGraph curVertex succ) newGraph - and addEdge newGraph parent child e = - match e with - | ExternalCallEdge | ExternalJmpEdge | RetEdge | ImplicitCallEdge -> - newGraph - | CallEdge - when preserveRecursiveEdge && child.VData.PPoint.Address = addr -> - let child, newGraph = getVertex newGraph child.VData.PPoint - DiGraph.addEdge newGraph parent child RecursiveCallEdge - | CallEdge | IndirectCallEdge -> - let last = parent.VData.LastInstruction - let fallPp = ProgramPoint (last.Address + uint64 last.Length, 0) - let childPp = - if child.VData.IsFakeBlock () then ProgramPoint.GetFake () - else child.VData.PPoint - let fake = IRBasicBlock ([||], childPp) - let child, newGraph = DiGraph.addVertex newGraph fake - let newGraph = DiGraph.addEdge newGraph parent child e - if __.IsNoReturn parent then newGraph - else - try - let fall, newGraph = getVertex newGraph fallPp - DiGraph.addEdge newGraph child fall RetEdge - with :? KeyNotFoundException -> -#if DEBUG - printfn "[W] Illegal fall-through edge (%x) ignored." fallPp.Address -#endif - newGraph - | InterJmpEdge -> - if __.CalleeMap.Contains child.VData.PPoint.Address then - let childPp = child.VData.PPoint - let fake = IRBasicBlock ([||], childPp) - let child, newGraph = DiGraph.addVertex newGraph fake - DiGraph.addEdge newGraph parent child CallEdge - else - let child, newGraph = getVertex newGraph child.VData.PPoint - let newGraph = DiGraph.addEdge newGraph parent child e - loop newGraph child.VData.PPoint - | _ -> - let child, newGraph = getVertex newGraph child.VData.PPoint - let newGraph = DiGraph.addEdge newGraph parent child e - loop newGraph child.VData.PPoint - if __.CalleeMap.Contains addr then - let rootPos = ProgramPoint (addr, 0) - let newGraph = loop newGraph rootPos - newGraph, vMap.[rootPos] - else raise InvalidFunctionAddressException - - member private __.ReverseLookUp src = - let queue = Queue> ([ src ]) - let visited = HashSet> () - let rec loop () = - if queue.Count = 0 then None - else - let v = queue.Dequeue () - if visited.Contains v then loop () - else - visited.Add v |> ignore - let addr = v.VData.PPoint.Address - if __.CalleeMap.Contains addr then Some v - else - DiGraph.getPreds __.SCFG v - |> List.iter (fun v -> - if visited.Contains v then () - else queue.Enqueue (v)) - loop () - loop () - - /// Find a basic block (vertex) in the SCFG that the given address belongs to. - member __.FindVertex (addr) = - let bbls = __.BBLStore - bbls.Boundaries - |> IntervalSet.findAll (AddrRange (addr, addr + 1UL)) - |> List.map (fun r -> ProgramPoint (AddrRange.GetMin r, 0)) - |> List.sortBy (fun p -> if p.Address = addr then -1 else 1) - |> List.choose (fun p -> Map.tryFind p bbls.VertexMap) - |> List.tryHead - - /// For a given address, find the first vertex of a function that the address - /// belongs to. - member __.FindFunctionVertex (addr) = - let bbls = __.BBLStore - IntervalSet.findAll (AddrRange (addr, addr + 1UL)) bbls.Boundaries - |> List.map (fun r -> - let addr = AddrRange.GetMin r - Map.find (ProgramPoint (addr, 0)) bbls.VertexMap) - |> List.tryPick __.ReverseLookUp - -[] -module BinEssence = - - let private getBoundary bbls addr = - match IntervalSet.tryFindByAddr addr bbls.Boundaries with - | Some range -> range - | None -> Utils.impossible () - - let private removeBBLInfo addr bbls = - let boundary = getBoundary bbls addr - let bblInfo = Map.find boundary.Min bbls.BBLMap - let bbls = - { bbls with - BBLMap = Map.remove boundary.Min bbls.BBLMap - Boundaries = IntervalSet.remove boundary bbls.Boundaries } - struct (bblInfo, bbls) - - let private addBBLInfo bblInfo bbls = - let boundary = bblInfo.Boundary - { bbls with - BBLMap = Map.add boundary.Min bblInfo bbls.BBLMap - Boundaries = IntervalSet.add boundary bbls.Boundaries } - - let inline private bblExists bbls addr = - Map.containsKey addr bbls.BBLMap - - let inline private isExecutableLeader hdl addr = - hdl.FileInfo.IsExecutableAddr addr - - let inline private isIntruding bbls leader = - IntervalSet.containsAddr leader bbls.Boundaries - - let inline private isKnownInstruction (instrMap: InstrMap) leader = - instrMap.ContainsKey leader - - let private computeNeighbors g targetV = - let incomings, cycleEdge = - DiGraph.getPreds g targetV - |> List.fold (fun (incomings, cycleEdge) p -> - let e = DiGraph.findEdgeData g p targetV - if p.GetID () = targetV.GetID () then incomings, Some e - else (p, e) :: incomings, cycleEdge) ([], None) - let outgoings = - DiGraph.getSuccs g targetV - |> List.fold (fun outgoings s -> - let e = DiGraph.findEdgeData g targetV s - if s.GetID () = targetV.GetID () then outgoings - else (s, e) :: outgoings) [] - struct (incomings, outgoings, cycleEdge) - - let splitIRBBlock g targetV (splitPoint: ProgramPoint) = - let insInfos = (targetV: Vertex).VData.GetInsInfos () - let srcInfos, dstInfos = - insInfos - |> Array.partition (fun insInfo -> - insInfo.Instruction.Address < splitPoint.Address) - let srcBlk = IRBasicBlock (srcInfos, targetV.VData.PPoint) - let dstBlk = IRBasicBlock (dstInfos, splitPoint) - let src, g = DiGraph.addVertex g srcBlk - let dst, g = DiGraph.addVertex g dstBlk - let g = DiGraph.addEdge g src dst FallThroughEdge - struct (src, dst, g) - - let private updateIRCFG bbls g prevBBL splitPoint target = - if Set.contains splitPoint prevBBL.Leaders then - (* The split point was one of the known IR-level leaders. So, we don't - need to further split the vertex. *) - struct (None, bbls, g) - else - let targetV = Map.find target bbls.VertexMap - let struct (ins, outs, cycleEdge) = computeNeighbors g targetV - let g = DiGraph.removeVertex g targetV - let bbls = { bbls with VertexMap = Map.remove target bbls.VertexMap } - let struct (src, dst, g) = splitIRBBlock g targetV splitPoint - let g = ins |> List.fold (fun g (p, e) -> DiGraph.addEdge g p src e) g - let g = outs |> List.fold (fun g (s, e) -> DiGraph.addEdge g dst s e) g - let g = - match cycleEdge with - | Some e -> DiGraph.addEdge g dst src e - | None -> g - let vertexMap = - bbls.VertexMap |> Map.add target src |> Map.add splitPoint dst - let bbls = { bbls with VertexMap = vertexMap } - struct (Some target, bbls, g) - - let private splitBBLInfo prevBBL fsts snds splitAddr bbls = - let oldBoundary = prevBBL.Boundary - let prevBoundary = AddrRange (oldBoundary.Min, splitAddr) - let newBoundary = AddrRange (splitAddr, oldBoundary.Max) - let prevInfo = { Boundary = prevBoundary; Leaders = fsts } - let newInfo = { Boundary = newBoundary; Leaders = snds } - bbls - |> addBBLInfo prevInfo - |> addBBLInfo newInfo - - let private updateCalleeMap ess bbls splitPoint fstLeader = - let v = Map.find splitPoint bbls.VertexMap - match v.VData.GetLastStmt (), (fstLeader: ProgramPoint option) with - | InterJmp (_, Num addr, InterJmpInfo.IsCall), Some fstLeader -> - let target = BitVector.toUInt64 addr - ess.CalleeMap.ReplaceCaller - ess.BinHandler fstLeader.Address splitPoint.Address target - | _ -> ess.CalleeMap - - /// Split a block into two (by the given leader address). - let private splitBlock ess leader elms = - let splitPoint = ProgramPoint (leader, 0) - (* 1. Remove previous block from bbls *) - let struct (prevBBL, bbls) = removeBBLInfo leader ess.BBLStore - (* 2. Split IR-level leaders into two: fsts (first leaders) and snds. *) - let fsts, snds = Set.partition (fun pp -> pp < splitPoint) prevBBL.Leaders - let snds = Set.add splitPoint snds - (* 3. Update IR-level Graph *) - let struct (fstLeader, bbls, g) = - updateIRCFG bbls ess.SCFG prevBBL splitPoint (Set.maxElement fsts) - (* 4. Split bblInfo *) - let bbls = splitBBLInfo prevBBL fsts snds splitPoint.Address bbls - (* 5. Update calleeMap *) - let calleeMap = updateCalleeMap ess bbls splitPoint fstLeader - let ess = { ess with BBLStore = bbls; SCFG = g; CalleeMap = calleeMap } - let elms = - List.map (fun elm -> - match elm, fstLeader with - | CFGEdge (src, edge, dst), Some fstLeader when fstLeader = src -> - CFGEdge (splitPoint, edge, dst) - | elm, _ -> elm) elms - ess, elms - - let private hasNoFallThrough (stmts: Stmt []) = - if stmts.Length > 0 then - match stmts.[stmts.Length - 1] with - | InterJmp (_, _, InterJmpInfo.IsCall) -> false - | InterJmp (_, _, _) - | SideEffect (BinIR.Halt) - | SideEffect (BinIR.UndefinedInstr) -> true - | _ -> false - else false - - /// Construct an InstructionInfo for the given program point (myPoint). - let private constructInfo (instrMap: InstrMap) ppoint nextLeader = - match instrMap.TryGetValue ((ppoint: ProgramPoint).Address) with - | false, _ -> None, nextLeader - | true, i -> - if ppoint.Address <> (nextLeader: ProgramPoint).Address then - let nextInsAddr = i.Instruction.Address + uint64 i.Instruction.Length - let nextPoint = - if hasNoFallThrough i.Stmts then nextLeader - else ProgramPoint (nextInsAddr, 0) - if ppoint.Position > 0 then - let delta = i.Stmts.Length - ppoint.Position - let i' = { i with Stmts = Array.sub i.Stmts ppoint.Position delta } - Some i', nextPoint - else Some i, nextPoint - else (* Intra-instruction case. *) - let delta = nextLeader.Position - ppoint.Position - let i' = { i with Stmts = Array.sub i.Stmts ppoint.Position delta } - Some i', nextLeader - - let rec private gatherBB instrMap boundary leaders acc ppoint nextIdx = - let nextLeader = - if nextIdx >= (leaders: ProgramPoint []).Length then - ProgramPoint ((boundary: AddrRange).Max, 0) - else leaders.[nextIdx] - if nextLeader > ppoint then - match constructInfo instrMap ppoint nextLeader with - | None, _ -> [||] - | Some info, nextPoint -> - let acc = info :: acc - if hasNoFallThrough info.Stmts then List.rev acc |> List.toArray - else gatherBB instrMap boundary leaders acc nextPoint nextIdx - elif nextLeader = ppoint then List.rev acc |> List.toArray - (* Next point is beyond the next leader's point. This is possible when two - control flows divide an instruction into two parts. This typically - happens in obfuscated code. *) - else gatherBB instrMap boundary leaders acc ppoint (nextIdx + 1) - - let private createNode instrMap boundary leaders bbls idx leader = - let instrs = gatherBB instrMap boundary leaders [] leader (idx + 1) - IRBasicBlock (instrs, leader) :: bbls - - let private buildVertices instrMap bblInfo = - let pps = Set.toArray bblInfo.Leaders - Array.foldi (createNode instrMap bblInfo.Boundary pps) [] pps - |> fst - - let getIntraEdge src symbol edgeProp edges = - let dstPos = - Map.find symbol (src: Vertex).VData.LastInsInfo.Labels - (src.VData.PPoint, dstPos, edgeProp) :: edges - - let private getInterEdge (src: Vertex) addr edgeProp edges = - let dstPos = ProgramPoint (addr, 0) - (src.VData.PPoint, dstPos, edgeProp) :: edges - - let private getFallthroughEdge src isPseudo edges = - let last = (src: Vertex).VData.LastInstruction - let fallAddr = last.Address + uint64 last.Length - let edge = if isPseudo then CallFallThroughEdge else FallThroughEdge - getInterEdge src fallAddr edge edges - - let private getIndirectEdges indMap src isCall edges = - let srcAddr = (src: Vertex).VData.PPoint.Address - match Map.tryFind srcAddr indMap with - | None -> - if isCall then - let fakePos = ProgramPoint.GetFake () - (src.VData.PPoint, fakePos, IndirectCallEdge) :: edges - else edges - | Some indInfo -> - let edge = if isCall then IndirectCallEdge else IndirectJmpEdge - indInfo.TargetAddresses - |> Set.fold (fun edges target -> - let targetPoint = ProgramPoint (target, 0) - (src.VData.PPoint, targetPoint, edge) :: edges) edges - - let private getNextPPoint (src: Vertex) = - let ppoints = src.VData.LastInsInfo.ReachablePPs - if Set.isEmpty ppoints then - let last = src.VData.LastInstruction - ProgramPoint (last.Address + uint64 last.Length, 0) - else - let _, bigger = - Set.partition (fun ppoint -> ppoint <= src.VData.PPoint) ppoints - if Set.isEmpty bigger then - let last = src.VData.LastInstruction - ProgramPoint (last.Address + uint64 last.Length, 0) - else Set.minElement bigger - - let getEdges ess edges (src: Vertex) = - match src.VData.GetLastStmt () with - | Jmp (Name s) -> - ess, getIntraEdge src s IntraJmpEdge edges - | CJmp (_, Name s1, Name s2) -> - let edges = - edges - |> getIntraEdge src s1 IntraCJmpTrueEdge - |> getIntraEdge src s2 IntraCJmpFalseEdge - ess, edges - | CJmp (_, Name s1, Undefined _) -> - ess, getIntraEdge src s1 IntraCJmpTrueEdge edges - | CJmp (_, Undefined _, Name s2) -> - ess, getIntraEdge src s2 IntraCJmpFalseEdge edges - | InterJmp (_, _, InterJmpInfo.IsRet) -> - ess, edges (* Connect ret edges later. *) - | InterJmp (_, Num addr, InterJmpInfo.IsCall) -> - let target = BitVector.toUInt64 addr - let calleeMap = ess.CalleeMap.AddEntry ess.BinHandler target - let edges = getInterEdge src target CallEdge edges - let calleeMap = - calleeMap.AddCaller ess.BinHandler src.VData.PPoint.Address target - let ess = { ess with CalleeMap = calleeMap } - if ess.IsNoReturn src then ess, edges - else ess, getFallthroughEdge src true edges - | InterJmp (_, Num addr, _) -> - let edges = getInterEdge src (BitVector.toUInt64 addr) InterJmpEdge edges - ess, edges - | InterCJmp (_, _, Num addr1, Num addr2) -> - let addr1 = BitVector.toUInt64 addr1 - let addr2 = BitVector.toUInt64 addr2 - let edges = - edges - |> getInterEdge src addr1 InterCJmpTrueEdge - |> getInterEdge src addr2 InterCJmpFalseEdge - ess, edges - | InterCJmp (_, _, Num addr, _) -> - src.VData.HasIndirectBranch <- true - (* Need to connect indirect edge here also *) - let edges = - getInterEdge src (BitVector.toUInt64 addr) InterCJmpTrueEdge edges - ess, edges - | InterCJmp (_, _, _, Num addr) -> - src.VData.HasIndirectBranch <- true - (* Need to connect indirect edge here also *) - let edges = - getInterEdge src (BitVector.toUInt64 addr) InterCJmpFalseEdge edges - ess, edges - | InterJmp (_, _, InterJmpInfo.IsCall) -> (* Indirect call *) - src.VData.HasIndirectBranch <- true - let edges = getIndirectEdges ess.IndirectBranchMap src true edges - (* XXX: Update callInfo here *) - if ess.IsNoReturn src then ess, edges - else ess, getFallthroughEdge src true edges - | InterJmp (_) - | InterCJmp (_) -> - src.VData.HasIndirectBranch <- true - ess, getIndirectEdges ess.IndirectBranchMap src false edges - | SideEffect (BinIR.SysCall) when ess.IsNoReturn src -> ess, edges - | SideEffect (BinIR.Halt) - | SideEffect (BinIR.UndefinedInstr) -> ess, edges - | _ -> (* Fall through case *) - let next = getNextPPoint src - if next.Position = 0 then - ess, getFallthroughEdge src false edges - else ess, (src.VData.PPoint, next, IntraJmpEdge) :: edges - - let rec internal addEdgeLoop ess elms = function - | [] -> ess, elms - | (srcPoint, dstPoint, e) :: edges when ProgramPoint.IsFake dstPoint -> - let src = Map.find srcPoint ess.BBLStore.VertexMap - let bbl = IRBasicBlock ([||], dstPoint) - let dst, g = DiGraph.addVertex ess.SCFG bbl - let g = DiGraph.addEdge g src dst e - addEdgeLoop { ess with SCFG = g } elms edges - | (srcPoint, dstPoint, e) :: edges -> - match Map.tryFind dstPoint ess.BBLStore.VertexMap with - | Some dst -> - let src = Map.find srcPoint ess.BBLStore.VertexMap - let g = DiGraph.addEdge ess.SCFG src dst e - let ess = { ess with SCFG = g } - if DiGraph.getSuccs g dst |> List.isEmpty then - let ess, edges = getEdges ess edges dst - addEdgeLoop ess elms edges - else addEdgeLoop ess elms edges - | None -> (* Put edge info to elms as we didn't create the dst yet. *) - if dstPoint.Position <> 0 then Utils.impossible () else () - let elms = CFGEdge (srcPoint, e, dstPoint.Address) :: elms - addEdgeLoop ess elms edges - - let private connectEdges ess elms vertices edges foundIndJmp = - let ess, elms = addEdgeLoop ess elms edges - let foundIndJmp = - if List.exists (fun (bbl: IRBasicBlock) -> bbl.HasIndirectBranch) vertices - then true - else foundIndJmp - Ok <| struct (ess, foundIndJmp, elms) - - let private extractLeaders ess (boundary: AddrRange) fstLeader addrs = - addrs - |> List.fold (fun pps addr -> - let insInfo = ess.InstrMap.[addr] - let pps' = - Set.filter (fun (ppoint: ProgramPoint) -> - let addr = ppoint.Address - boundary.Min <= addr && addr < boundary.Max) insInfo.ReachablePPs - Set.union pps pps') (Set.singleton fstLeader) - - let private buildBlock ess leader addrs lastAddr foundIndJmp elms edgeInfo = - let last = ess.InstrMap.[lastAddr].Instruction - let boundary = AddrRange (leader, lastAddr + uint64 last.Length) - let leader = ProgramPoint (leader, 0) - let pps = extractLeaders ess boundary leader addrs - let bblInfo = { Boundary = boundary; Leaders = pps } - let bbls = addBBLInfo bblInfo ess.BBLStore - let vertices = buildVertices ess.InstrMap bblInfo - let vertexMap, g = - vertices - |> List.fold (fun (vertexMap, g) bbl -> - let v, g = DiGraph.addVertex g bbl - Map.add bbl.PPoint v vertexMap, g) (bbls.VertexMap, ess.SCFG) - let bbls = { bbls with VertexMap = vertexMap } - let ess = { ess with BBLStore = bbls; SCFG = g } - match edgeInfo with - | Some (src, e) -> - connectEdges ess elms vertices [(src, leader, e)] foundIndJmp - | None -> - let ess, edges = getEdges ess [] (Map.find leader ess.BBLStore.VertexMap) - connectEdges ess elms vertices edges foundIndJmp - - let internal parseNewBBL ess foundIndJmp elms ctxt addr edgeInfo = - match InstrMap.parse ess.BinHandler ctxt ess.InstrMap ess.BBLStore addr with - | Ok (instrMap, block, lastAddr) -> - let ess = { ess with InstrMap = instrMap } - buildBlock ess addr block lastAddr foundIndJmp elms edgeInfo - | Error _ -> Error () - - let rec private getBlockAddressesWithInstrMap ess addrs addr = - let ins = ess.InstrMap.[addr].Instruction - let nextAddr = addr + uint64 ins.Length - if ins.IsExit () || Map.containsKey nextAddr ess.BBLStore.BBLMap then - struct (List.rev (addr :: addrs), ins.Address) - else getBlockAddressesWithInstrMap ess (addr :: addrs) nextAddr - - let internal updateCFGWithVertex ess foundIndJmp elms addr ctxt = - if bblExists ess.BBLStore addr then Ok <| struct (ess, foundIndJmp, elms) - elif not <| isExecutableLeader ess.BinHandler addr then Error () - elif isIntruding ess.BBLStore addr then - if isKnownInstruction ess.InstrMap addr then (* Need to split *) - let ess, elms = splitBlock ess addr elms - Ok <| struct (ess, foundIndJmp, elms) - else Error () - elif isKnownInstruction ess.InstrMap addr then - let struct (block, lastAddr) = getBlockAddressesWithInstrMap ess [] addr - buildBlock ess addr block lastAddr foundIndJmp elms None - else parseNewBBL ess foundIndJmp elms ctxt addr None - - let private computeNextParsingContext ess src edge = - let prevVertex = Map.find src ess.BBLStore.VertexMap - let ctxt = prevVertex.VData.LastInstruction.NextParsingContext - match ess.BinHandler.ISA.Arch with - | Arch.ARMv7 -> - match edge, prevVertex.VData.LastInstruction.AuxParsingContext with - | CallFallThroughEdge, Some ctxt -> ctxt - | _ -> ctxt - | _ -> ctxt - - let internal updateCFGWithEdge ess foundIndJmp elms src edge dst = - if bblExists ess.BBLStore dst then - let ess, elms = addEdgeLoop ess elms [(src, ProgramPoint (dst, 0), edge)] - Ok <| struct (ess, foundIndJmp, elms) - elif not <| isExecutableLeader ess.BinHandler dst then Error () - elif isIntruding ess.BBLStore dst then - if isKnownInstruction ess.InstrMap dst then (* Need to split *) - let ess, elms = splitBlock ess dst elms - let src = Map.find src ess.BBLStore.VertexMap - let dst = Map.find (ProgramPoint (dst, 0)) ess.BBLStore.VertexMap - let g = DiGraph.addEdge ess.SCFG src dst edge - let ess = { ess with SCFG = g } - Ok <| struct (ess, foundIndJmp, elms) - else Error () - elif isKnownInstruction ess.InstrMap dst then - let struct (block, lastAddr) = getBlockAddressesWithInstrMap ess [] dst - buildBlock ess dst block lastAddr foundIndJmp elms (Some (src, edge)) - else - let ctxt = computeNextParsingContext ess src edge - parseNewBBL ess foundIndJmp elms ctxt dst (Some (src, edge)) - - let rec internal updateCFG ess foundIndJmp = function - | [] -> Ok (ess, foundIndJmp) - | CFGEntry (addr, ctxt) :: elms -> - match updateCFGWithVertex ess foundIndJmp elms addr ctxt with - | Ok (ess, foundIndJmp, elms) -> updateCFG ess foundIndJmp elms - | Error () -> Error () - | CFGEdge (src, edge, dst) :: elms -> - match updateCFGWithEdge ess foundIndJmp elms src edge dst with - | Ok (ess, foundIndJmp, elms) -> updateCFG ess foundIndJmp elms - | Error () -> Error () - - let private removeNoReturnFallThroughEdges ess = - let bbls = ess.BBLStore - ess.NoReturnInfo.NoReturnCallSites - |> Set.fold (fun g ppoint -> - match Map.tryFind ppoint bbls.VertexMap with - | None -> g - | Some v -> - DiGraph.getSuccs g v - |> List.fold (fun acc s -> - if DiGraph.findEdgeData g v s = FallThroughEdge then (v, s) :: acc - elif DiGraph.findEdgeData g v s = CallFallThroughEdge then - (v, s) :: acc - else acc) [] - |> List.fold (fun g (src, dst) -> - DiGraph.removeEdge g src dst) g) ess.SCFG - - let private getUnreachables bbls (calleeMap: CalleeMap) g = - let reachables = - calleeMap.Entries - |> Set.fold (fun acc entry -> - let ppoint = ProgramPoint (entry, 0) - let v = Map.find ppoint bbls.VertexMap - let acc = Set.add ppoint acc - Traversal.foldPostorder g v (fun acc v -> - Set.add v.VData.PPoint acc) acc) Set.empty - let ppoints = - bbls.VertexMap - |> Map.fold (fun acc ppoint _ -> Set.add ppoint acc) Set.empty - Set.difference ppoints reachables - - let private removeNoReturnFallThroughs ess = - let bbls = ess.BBLStore - let g = removeNoReturnFallThroughEdges ess - let unreachables = getUnreachables bbls ess.CalleeMap g - (* Update calleeMap here *) - let calleeMap, g = - unreachables - |> Set.fold (fun (calleeMap: CalleeMap, g) ppoint -> - let v = Map.find ppoint bbls.VertexMap - let calleeMap = - match v.VData.GetLastStmt () with - | InterJmp (_, Num addr, InterJmpInfo.IsCall) -> - let target = BitVector.toUInt64 addr - calleeMap.RemoveCaller v.VData.PPoint.Address target - | InterJmp (_, _, InterJmpInfo.IsCall) -> (* Indirect call *) - (* XXX: Update callInfo here *) - calleeMap - | _ -> calleeMap - let g = DiGraph.removeVertex g v - calleeMap, g) (ess.CalleeMap, g) - let bbls = - unreachables - |> Set.fold (fun bbls ppoint -> - let addr = ppoint.Address - match Map.tryFind addr bbls.BBLMap with - | Some bblInfo -> - let boundary = bblInfo.Boundary - let newBBLMap = Map.remove addr bbls.BBLMap - let newBoundaries = IntervalSet.remove boundary bbls.Boundaries - let newVertexMap = Map.remove ppoint bbls.VertexMap - { bbls with - BBLMap = newBBLMap - Boundaries = newBoundaries - VertexMap = newVertexMap } - | None -> - { bbls with - VertexMap = Map.remove ppoint bbls.VertexMap }) bbls - { ess with BBLStore = bbls; CalleeMap = calleeMap; SCFG = g } - - [] - let addEntry ess (addr, ctxt) = - let ess = - { ess with CalleeMap = ess.CalleeMap.AddEntry ess.BinHandler addr } - match updateCFG ess false [ CFGEntry (addr, ctxt) ] with - | Ok (ess, _) -> Ok ess - | Error () -> if ess.IgnoreIllegal then Error () else Utils.impossible () - - [] - let addEntries ess entries = - entries - |> List.fold (fun res entry -> - match res with - | Ok ess -> addEntry ess entry - | _ -> res) (Ok ess) - - [] - let addEdge ess src dst edgeKind = - let edgeInfo = [ CFGEdge (ProgramPoint (src, 0), edgeKind, dst) ] - match updateCFG ess false edgeInfo with - | Ok (ess, hasNewIndBranch) -> Ok (ess, hasNewIndBranch) - | Error () -> if ess.IgnoreIllegal then Error () else Utils.impossible () - - [] - let addNoReturnInfo ess noRetFuncs noRetCallSites = - let noRetInfo = ess.NoReturnInfo - let noRetFuncs = Set.union noRetFuncs noRetInfo.NoReturnFuncs - let noRetCallSites = Set.union noRetCallSites noRetInfo.NoReturnCallSites - let noRetInfo = NoReturnInfo.Init noRetFuncs noRetCallSites - removeNoReturnFallThroughs { ess with NoReturnInfo = noRetInfo } - - [] - let addIndirectBranchMap ess indMap' = - let indMap = ess.IndirectBranchMap - let indMap = - indMap' |> Map.fold (fun m addr info -> Map.add addr info m) indMap - { ess with IndirectBranchMap = indMap } - - /// This function returns an initial sequence of entry points obtained from - /// the binary itself (e.g., from its symbol information). Therefore, if the - /// binary is stripped, the returned sequence will be incomplete, and we need - /// to expand it during the other analyses. - let private getInitialEntryPoints hdl = - let fi = hdl.FileInfo - let entries = fi.GetFunctionAddresses () |> Set.ofSeq - let entries = - fi.EntryPoint - |> Option.fold (fun acc addr -> Set.add addr acc) entries - |> Set.toList - match hdl.ISA.Arch with - | Arch.ARMv7 -> - let thumbCtxt = ParsingContext.Init ArchOperationMode.ThumbMode - let armCtxt = ParsingContext.Init ArchOperationMode.ARMMode - List.map (fun addr -> - if addr &&& 1UL = 1UL then addr - 1UL, thumbCtxt - else addr, armCtxt) entries - | _ -> - List.map (fun addr -> addr, hdl.DefaultParsingContext) entries - - let private initialize hdl ignoreIllegal = - { BinHandler = hdl - InstrMap = InstrMap () - BBLStore = BBLStore.Init () - CalleeMap = CalleeMap (hdl) - SCFG = IRCFG.init PersistentGraph - NoReturnInfo = NoReturnInfo.Init Set.empty Set.empty - IndirectBranchMap = Map.empty - IgnoreIllegal = defaultArg ignoreIllegal true } - - [] - let init hdl = - let ess = initialize hdl None - match getInitialEntryPoints hdl |> addEntries ess with - | Ok ess -> ess - | Error _ -> Utils.impossible () - - [] - let initByEntries hdl entries = - let ess = initialize hdl None - addEntries ess entries diff --git a/src/BinEssence/CFGEdgeKind.fs b/src/BinEssence/CFGEdgeKind.fs deleted file mode 100644 index 34200531..00000000 --- a/src/BinEssence/CFGEdgeKind.fs +++ /dev/null @@ -1,73 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinEssence - -/// We distinguish edges of a CFG by classifying them into several kinds. -type CFGEdgeKind = - /// An edge of a direct jump, e.g., JMP +0x42. - | InterJmpEdge - /// An edge of a conditional jump that is exercised when the condition is - /// true. - | InterCJmpTrueEdge - /// An edge of a conditional jump that is exercised when the condition is - /// false. - | InterCJmpFalseEdge - /// A direct jump edge only visible from an IR-level CFG, because there is a - /// control-flow inside a machine instruction. - | IntraJmpEdge - /// A true conditional edge only visible from an IR-level CFG, because there - /// is a control-flow inside a machine instruction. - | IntraCJmpTrueEdge - /// A false conditional edge only visible from an IR-level CFG, because there - /// is a control-flow inside a machine instruction. - | IntraCJmpFalseEdge - /// An edge of a regular call instruction. - | CallEdge - /// An edge of a recursive call instruction. - | RecursiveCallEdge - /// An edge from an indirect jmp instruction. - | IndirectJmpEdge - /// An edge from an indirect call instruction. - | IndirectCallEdge - /// An edge of a jmp instruction to an external function or PLT. - | ExternalJmpEdge - /// An edge of a call instruction to an external function or PLT. - | ExternalCallEdge - /// An edge of a function return. - | RetEdge - /// A simple fall-through case. This type is created when an edge cuts in two - /// consecutive instructions. - | FallThroughEdge - /// A fall-through after a call instruction. This is indeed a pseudo edge as - /// there's no direct control flow from a call instruction to its - /// fall-through. - | CallFallThroughEdge - /// An implicit edge that is not explicitly visible from the current CALL - /// instruction, but visible within the function. If there is a path in the - /// callee that calls a function, then we create an implicit edge from a - /// caller to any of the callees. - | ImplicitCallEdge - /// Unknown edge type. This should be an error case. - | UnknownEdge diff --git a/src/BinEssence/CFGElement.fs b/src/BinEssence/CFGElement.fs deleted file mode 100644 index 4a61e05a..00000000 --- a/src/BinEssence/CFGElement.fs +++ /dev/null @@ -1,33 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinEssence - -open B2R2 -open B2R2.FrontEnd - -/// Internally used to indicate CFG elements: either a vertex or an edge. -type internal CFGElement = - | CFGEntry of Addr * ParsingContext - | CFGEdge of src: ProgramPoint * CFGEdgeKind * dst: Addr diff --git a/src/BinEssence/CFGExport.fs b/src/BinEssence/CFGExport.fs deleted file mode 100644 index 9d90020f..00000000 --- a/src/BinEssence/CFGExport.fs +++ /dev/null @@ -1,74 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.BinEssence.CFGExport - -open B2R2.BinGraph - -open System.IO -open System.Text -open System.Runtime.Serialization -open System.Runtime.Serialization.Json - -[] -type EdgeData = { - [] - From: string - [] - To: string - [] - Type: string -} - -[] -type CFGData = { - [] - Nodes: string [] - [] - Edges: EdgeData [] -} - -let toJson cfg jsonPath = - let enc = Encoding.UTF8 - use fs = File.Create (jsonPath) - use writer = - JsonReaderWriterFactory.CreateJsonWriter (fs, enc, true, true, " ") - let nodes = - [] - |> DiGraph.foldVertex cfg (fun acc (v: Vertex<#BasicBlock>) -> - v.VData.PPoint.Address.ToString ("X") :: acc) - |> List.rev - |> List.toArray - let edges = - [] - |> DiGraph.foldEdge cfg (fun acc f t e -> - { From = f.VData.PPoint.Address.ToString ("X") - To = t.VData.PPoint.Address.ToString ("X") - Type = e.ToString () } :: acc) - |> List.rev - |> List.toArray - let data = { Nodes = nodes; Edges = edges } - let ser = DataContractJsonSerializer (typedefof) - ser.WriteObject (writer, data) - writer.Flush () diff --git a/src/BinEssence/CalleeMap.fs b/src/BinEssence/CalleeMap.fs deleted file mode 100644 index e1816824..00000000 --- a/src/BinEssence/CalleeMap.fs +++ /dev/null @@ -1,156 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinEssence - -open B2R2 -open B2R2.BinFile -open B2R2.FrontEnd - -/// Callee can be either external or internal. -type CalleeKind = - | ExternalCallee - | InternalCallee - -/// Callee is a function invoked within the binary under analysis. Callee can be -/// an external function, i.e., it does not need to be defined within the -/// binary. We let a target address be a callee's address if one of the -/// following two conditions hold: (1) the address is a target of a call -/// instruction, and (2) the address is maked as a function in the symbol table, -/// and the function is referenced by a branch instruction (either call or jmp). -type Callee = { - CalleeID: string - CalleeName: string - Addr: Addr option - CalleeKind: CalleeKind - Callers: Set - /// Is this callee a no-return function such as "exit"? - mutable IsNoReturn: bool -} -with - static member private obtainFuncIDAndName (hdl: BinHandler) (addr: Addr) = - let id = "func_" + addr.ToString ("X") - match hdl.FileInfo.TryFindFunctionSymbolName addr |> Utils.tupleToOpt with - | None -> id, id - | Some name -> id, name - - static member Init hdl addr calleeKind = - let id, name = Callee.obtainFuncIDAndName hdl addr - { CalleeID = id - CalleeName = name - Addr = Some addr - CalleeKind = calleeKind - Callers = Set.empty - IsNoReturn = false } - - static member AddCaller callerAddr callee = - { callee with Callers = Set.add callerAddr callee.Callers } - - static member RemoveCaller callerAddr callee = - { callee with Callers = Set.remove callerAddr callee.Callers } - -/// A mapping from callee's name to its information. -type CalleeMap (hdl, ?linkMap, ?strCalleeMap, ?addrCalleeMap, ?callerMap) = - let buildLinkMap hdl = - hdl.FileInfo.GetLinkageTableEntries () - |> Seq.fold (fun map entry -> - Map.add entry.TableAddress entry.FuncName map - |> Map.add entry.TrampolineAddress entry.FuncName) Map.empty - let linkMap = defaultArg linkMap <| buildLinkMap hdl - let strCalleeMap = defaultArg strCalleeMap Map.empty - let addrCalleeMap = defaultArg addrCalleeMap Map.empty - let callerMap = defaultArg callerMap Map.empty - - member __.Callees with get () = addrCalleeMap |> Map.toSeq |> Seq.map snd - member __.Entries with get () = - addrCalleeMap |> Map.toSeq |> Seq.map fst |> Set.ofSeq - member __.CallerMap with get () = callerMap - member __.Contains (addr) = Map.containsKey addr addrCalleeMap - member __.Contains (name) = Map.containsKey name strCalleeMap - member __.Find (addr) = Map.tryFind addr addrCalleeMap - member __.Find (name) = - Map.tryFind name strCalleeMap - |> Option.bind (fun addr -> Map.tryFind addr addrCalleeMap) - - member __.InternalCallees with get () = - addrCalleeMap |> Map.toSeq |> Seq.map snd - |> Seq.filter (fun c -> c.Addr.IsSome) - - member private __.AddCallee hdl entry = - if Map.containsKey entry addrCalleeMap then strCalleeMap, addrCalleeMap - else - let callee = - if Map.containsKey entry linkMap then ExternalCallee else InternalCallee - |> Callee.Init hdl entry - let strCalleeMap = Map.add callee.CalleeID entry strCalleeMap - let addrCalleeMap = Map.add entry callee addrCalleeMap - strCalleeMap, addrCalleeMap - - member __.AddEntry hdl entry = - let strCalleeMap, addrCalleeMap = __.AddCallee hdl entry - CalleeMap (hdl, linkMap, strCalleeMap, addrCalleeMap, callerMap) - - member __.AddCaller hdl callerAddr calleeAddr = - let strCalleeMap, addrCalleeMap = __.AddCallee hdl calleeAddr - (* Update calleeMap *) - let callee = - Map.find calleeAddr addrCalleeMap |> Callee.AddCaller callerAddr - let addrCalleeMap = Map.add calleeAddr callee addrCalleeMap - (* Update callerMap *) - let callerMap = - match Map.tryFind callerAddr callerMap with - | Some callees -> - Map.add callerAddr (Set.add calleeAddr callees) callerMap - | None -> Map.add callerAddr (Set.singleton calleeAddr) callerMap - CalleeMap (hdl, linkMap, strCalleeMap, addrCalleeMap, callerMap) - - member __.ReplaceCaller hdl oldCaller newCaller calleeAddr = - (* Update calleeMap *) - let callee = - Map.find calleeAddr addrCalleeMap - |> Callee.RemoveCaller oldCaller - |> Callee.AddCaller newCaller - let addrCalleeMap = Map.add calleeAddr callee addrCalleeMap - (* Update callerMap *) - let callees = Map.find oldCaller callerMap - let callerMap = - if Set.count callees = 1 then Map.remove oldCaller callerMap - else Map.add oldCaller (Set.remove calleeAddr callees) callerMap - let callerMap = - match Map.tryFind newCaller callerMap with - | Some callees -> Map.add newCaller (Set.add calleeAddr callees) callerMap - | None -> Map.add newCaller (Set.singleton calleeAddr) callerMap - CalleeMap (hdl, linkMap, strCalleeMap, addrCalleeMap, callerMap) - - member __.RemoveCaller callerAddr calleeAddr = - (* Update calleeMap *) - let callee = - Map.find calleeAddr addrCalleeMap |> Callee.RemoveCaller callerAddr - let addrCalleeMap = Map.add calleeAddr callee addrCalleeMap - (* Update callerMap *) - let callees = Map.find callerAddr callerMap |> Set.remove calleeAddr - let callerMap = - if Set.isEmpty callees then Map.remove callerAddr callerMap - else Map.add callerAddr callees callerMap - CalleeMap (hdl, linkMap, strCalleeMap, addrCalleeMap, callerMap) diff --git a/src/BinEssence/IRBasicBlock.fs b/src/BinEssence/IRBasicBlock.fs deleted file mode 100644 index 5287ba78..00000000 --- a/src/BinEssence/IRBasicBlock.fs +++ /dev/null @@ -1,90 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinEssence - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinGraph - -/// A basic block that consists of IR (LowUIR) statements. It contains all the -/// InstructionInfo of the basic block. -type IRBasicBlock (instrs: InstructionInfo [], point: ProgramPoint) = - inherit BasicBlock (point) - - let mutable hasIndirectBranch = false - - /// Does this block has indirect branch? This flag will be set after building - /// an SCFG. - member __.HasIndirectBranch - with get () = hasIndirectBranch and set (v) = hasIndirectBranch <- v - - /// The first instruction of the basic block. - member __.FirstInstruction = - if Array.isEmpty instrs then raise DummyDataAccessException - else instrs.[0].Instruction - - /// The last instruction of the basic block. - member __.LastInstruction = - if Array.isEmpty instrs then raise DummyDataAccessException - else instrs.[Array.length instrs - 1].Instruction - - member __.LastInsInfo = - if Array.isEmpty instrs then raise DummyDataAccessException - else instrs.[Array.length instrs - 1] - - /// The address range of the basic block. Even if the block contains a partial - /// IR statements of an instruction, we include the instruction to compute the - /// range. - override __.Range = - let lastAddr = __.LastInstruction.Address + uint64 __.LastInstruction.Length - AddrRange (__.PPoint.Address, lastAddr) - - override __.IsFakeBlock () = Array.isEmpty instrs - - override __.ToVisualBlock () = - __.GetIRStatements () - |> Array.concat - |> Array.map (fun stmt -> - [| { AsmWordKind = AsmWordKind.String - AsmWordValue = BinIR.LowUIR.Pp.stmtToString stmt } |]) - - /// Get an array of IR statements of a basic block. - member __.GetIRStatements () = instrs |> Array.map (fun i -> i.Stmts) - - /// Get an array of instructions that corresponds to each statement in the - /// IRStatements. - member __.GetInstructions () = instrs |> Array.map (fun i -> i.Instruction) - - /// Get the array of InstructionInfo of the basic block. - member __.GetInsInfos () = instrs - - /// Get the last IR statement of the bblock. - member __.GetLastStmt () = - let stmts = instrs.[instrs.Length - 1].Stmts - stmts.[stmts.Length - 1] - - override __.ToString () = - if instrs.Length = 0 then "IRBBLK(Dummy)" - else "IRBBLK(" + __.PPoint.Address.ToString("X") + ")" diff --git a/src/BinEssence/InstrMap.fs b/src/BinEssence/InstrMap.fs deleted file mode 100644 index ddf95166..00000000 --- a/src/BinEssence/InstrMap.fs +++ /dev/null @@ -1,121 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinEssence - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinIR.LowUIR -open System.Collections.Generic - -/// Address to an InstructionInfo mapping. InstrMap contains both valid and -/// bogus instructions so do not use InstrMap directly for analyses. -type InstrMap = Dictionary - -[] -module InstrMap = - - /// Remove unnecessary IEMark to ease the analysis. - let private trimIEMark (stmts: Stmt []) = - let last = stmts.[stmts.Length - 1] - let secondLast = stmts.[stmts.Length - 2] - match secondLast, last with - | InterJmp _, IEMark _ - | InterCJmp _, IEMark _ - | SideEffect _, IEMark _ -> - Array.sub stmts 0 (stmts.Length - 1) - | _ -> stmts - - let private trim stmts = - BinHandler.Optimize stmts - |> trimIEMark - - let private findLabels addr stmts = - stmts - |> Array.foldi (fun labels idx stmt -> - match stmt with - | LMark (s) -> - Map.add s (ProgramPoint (addr, idx)) labels - | _ -> labels) Map.empty - |> fst - - let private findReachablePPs labels stmts = - stmts - |> Array.fold (fun targets stmt -> - match stmt with - | Jmp (Name s) -> Set.add (Map.find s labels) targets - | CJmp (_, Name t, Name f) -> - targets |> Set.add (Map.find t labels) |> Set.add (Map.find f labels) - | CJmp (_, Name t, Undefined _) -> - Set.add (Map.find t labels) targets - | CJmp (_, Undefined _, Name f) -> - Set.add (Map.find f labels) targets - | InterJmp (_, Num bv, _) -> - let ppoint = ProgramPoint (BitVector.toUInt64 bv, 0) - Set.add ppoint targets - | InterCJmp (_, _, Num tBv, Num fBv) -> - let tPpoint = ProgramPoint (BitVector.toUInt64 tBv, 0) - let fPpoint = ProgramPoint (BitVector.toUInt64 fBv, 0) - targets |> Set.add tPpoint |> Set.add fPpoint - | InterCJmp (_, _, Num tBv, _) -> - let tPpoint = ProgramPoint (BitVector.toUInt64 tBv, 0) - Set.add tPpoint targets - | InterCJmp (_, _, _, Num fBv) -> - let fPpoint = ProgramPoint (BitVector.toUInt64 fBv, 0) - Set.add fPpoint targets - | _ -> targets) Set.empty - - let private newInstructionInfo hdl (ins: Instruction) = - let stmts = BinHandler.LiftInstr hdl ins |> trim - let labels = findLabels ins.Address stmts - { Instruction = ins - Stmts = stmts - Labels = labels - ReachablePPs = findReachablePPs labels stmts - ArchOperationMode = hdl.DefaultParsingContext.ArchOperationMode - Offset = hdl.DefaultParsingContext.CodeOffset } - - let rec private updateInstrMap hdl (instrMap: InstrMap) (instr: Instruction) = - instrMap.[instr.Address] <- newInstructionInfo hdl instr - - let rec private parseBBL hdl ctxt bblMap acc pc = - match BinHandler.TryParseInstr hdl ctxt pc with - | Some ins -> - let ctxt = ins.NextParsingContext - let nextAddr = pc + uint64 ins.Length - if ins.IsExit () || Map.containsKey nextAddr bblMap then - Ok <| struct (List.rev (ins :: acc), ins.Address) - else parseBBL hdl ctxt bblMap (ins :: acc) nextAddr - | None -> Error <| List.rev acc - - /// InstrMap will only have this API. Removing instructions from InstrMap is - /// not allowed. - let parse hdl ctxt instrMap bblStore leaderAddr = - match parseBBL hdl ctxt bblStore.BBLMap [] leaderAddr with - | Ok ([], _) -> failwith "Fatal error: an empty block encountered." - | Ok (instrs, lastAddr) -> - List.iter (updateInstrMap hdl instrMap) instrs - let addrs = List.map (fun (instr: Instruction) -> instr.Address) instrs - Ok <| struct (instrMap, addrs, lastAddr) - | Error _ -> Error () diff --git a/src/BinEssence/InstructionInfo.fs b/src/BinEssence/InstructionInfo.fs deleted file mode 100644 index 53333a38..00000000 --- a/src/BinEssence/InstructionInfo.fs +++ /dev/null @@ -1,50 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinEssence - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.LowUIR -open B2R2.FrontEnd - -/// Abstract information about the instruction and its corresponding IR -/// statements. -type InstructionInfo = { - /// Instruction. - Instruction: Instruction - /// IR. - Stmts: Stmt [] - /// Labels. - Labels: Map - /// Reachable program points (jump targets) from the instruction. - ReachablePPs: Set - /// Operation mode. - ArchOperationMode: ArchOperationMode - /// Instruction itself contains its address, but we may want to place this - /// instruction in a different location in a virtual address space. This field - /// is useful in such cases to give a specific offset to the instruction. This - /// field is zero in most cases (except EVM) though. - Offset: Addr -} diff --git a/src/BinFile.Tests/B2R2.BinFile.Tests.fsproj b/src/BinFile.Tests/B2R2.BinFile.Tests.fsproj deleted file mode 100644 index 47566fe0..00000000 --- a/src/BinFile.Tests/B2R2.BinFile.Tests.fsproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - netcoreapp3.0 - false - - - - - - - - - - - - - - - - - - diff --git a/src/BinFile/ELFDwarfTypes.fs b/src/BinFile/ELFDwarfTypes.fs deleted file mode 100644 index c61502a7..00000000 --- a/src/BinFile/ELFDwarfTypes.fs +++ /dev/null @@ -1,57 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinFile.ELF - -type ExceptionHeaderValue = - /// No value is present. - | DW_EH_PE_omit = 0xff - /// A literal pointer whose size is determined by the architecture. - | DW_EH_PE_absptr = 0x00 - /// Unsigned value is encoded using the LEB128. - | DW_EH_PE_uleb128 = 0x01 - /// A 2-byte unsigned value. - | DW_EH_PE_udata2 = 0x02 - /// A 4-byte unsigned value. - | DW_EH_PE_udata4 = 0x03 - /// A 8-byte unsigned value. - | DW_EH_PE_udata8 = 0x04 - /// Signed value is encoded using the LEB128. - | DW_EH_PE_sleb128 = 0x09 - /// A 2-byte signed value. - | DW_EH_PE_sdata2 = 0x0a - /// A 4-byte signed value. - | DW_EH_PE_sdata4 = 0x0b - /// A 8-byte signed value. - | DW_EH_PE_sdata8 = 0x0c - -type ExceptionHeaderApplication = - /// Value is used with no modification. - | DW_EH_PE_absptr = 0x00 - /// Value is relative to the current program counter. - | DW_EH_PE_pcrel = 0x10 - /// Value is relative to the beginning of the .eh_frame_hdr section. - | DW_EH_PE_datarel = 0x30 - /// No value is present. - | DW_EH_PE_omit = 0xff diff --git a/src/BinFile/ELFExceptionFrames.fs b/src/BinFile/ELFExceptionFrames.fs deleted file mode 100644 index e4a58ac0..00000000 --- a/src/BinFile/ELFExceptionFrames.fs +++ /dev/null @@ -1,213 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.BinFile.ELF.ExceptionFrames - -open System -open B2R2 -open B2R2.BinFile - -/// Raised when an unhandled eh_frame version is encountered. -exception UnhandledExceptionHandlingFrameVersion - -/// Raised when an unhandled augment string is encountered. -exception UnhandledAugString - -/// Raised when an unhandled encoding is encountered. -exception UnhandledEncoding - -let [] ehframe = ".eh_frame" - -let inline readInt (reader: BinReader) offset = - reader.ReadInt32 offset - -let inline readUInt64 (reader: BinReader) offset = - reader.ReadUInt64 offset - -let computeNextOffset len (reader: BinReader) offset = - if len = -1 then - let struct (len, offset) = readUInt64 reader offset - int len + offset, offset - else len + offset, offset - -let parseULEB128 (reader: BinReader) offset = - let span = reader.PeekSpan (offset) - let v, cnt = LEB128.DecodeUInt64 span - v, offset + cnt - -let parseSLEB128 (reader: BinReader) offset = - let span = reader.PeekSpan (offset) - let v, cnt = LEB128.DecodeSInt64 span - v, offset + cnt - -let parseReturnRegister (reader: BinReader) version offset = - if version = 1uy then reader.PeekByte offset |> uint64, offset + 1 - else parseULEB128 reader offset - -let parseAugmentationData (reader: BinReader) offset augstr = - if (augstr: string).StartsWith ('z') then - let len, offset = parseULEB128 reader offset - let span = reader.PeekSpan (int len, offset) - let arr = span.ToArray () - Some arr, offset + int len - else None, offset - -let personalityRoutinePointerSize addrSize = function - | 2uy -> 2 - | 3uy -> 4 - | 4uy -> 8 - | _ -> addrSize - -let rec parseEncodingLoop addrSize (data: byte []) offset = function - | 'L' :: rest -> parseEncodingLoop addrSize data (offset + 1) rest - | 'P' :: rest -> - let psz = data.[offset] &&& 7uy |> personalityRoutinePointerSize addrSize - parseEncodingLoop addrSize data (offset + psz + 1) rest - | 'R' :: _ -> - let d = data.[offset] - let v = - int (d &&& 0x0Fuy) - |> LanguagePrimitives.EnumOfValue - let app = - int (d &&& 0xF0uy) - |> LanguagePrimitives.EnumOfValue - v, app - | _ -> raise UnhandledAugString - -let parseEncodingAndApp addrSize (augstr: string) augdata = - match augdata with - | None -> - ExceptionHeaderValue.DW_EH_PE_absptr, - ExceptionHeaderApplication.DW_EH_PE_absptr - | Some (data: byte []) -> - augstr.[1..] - |> Seq.toList - |> parseEncodingLoop addrSize data 0 - -let parseCIE cls (reader: BinReader) offset = - let struct (version, offset) = reader.ReadByte offset - if version = 1uy || version = 3uy then - let span = reader.PeekSpan offset - let augstr = ByteArray.extractCStringFromSpan span 0 - let addrSize = WordSize.toByteWidth cls - let offset = offset + augstr.Length + 1 - let offset = if augstr.Contains "eh" then offset + addrSize else offset - let codeAlignmentFactor, offset = parseULEB128 reader offset - let dataAlignmentFactor, offset = parseSLEB128 reader offset - let retReg, offset = parseReturnRegister reader version offset - let augdata, _ = parseAugmentationData reader offset augstr - let enc, app = parseEncodingAndApp addrSize augstr augdata - { Version = version - AugmentationString = augstr - CodeAlignmentFactor = codeAlignmentFactor - DataAlignmentFactor = dataAlignmentFactor - ReturnAddressRegister = retReg - AugmentationData = augdata - FDEEncoding = enc - FDEApplication = app } - else - raise UnhandledExceptionHandlingFrameVersion - -let computePCInfo cls (reader: BinReader) cie offset = - match cie.FDEEncoding with - | ExceptionHeaderValue.DW_EH_PE_absptr -> - let struct (addr, offset) = FileHelper.readUIntOfType reader cls offset - let struct (len, _) = FileHelper.readUIntOfType reader cls offset - addr, len - | ExceptionHeaderValue.DW_EH_PE_uleb128 -> - let addr, offset = parseULEB128 reader offset - let len, _ = parseULEB128 reader offset - addr, len - | ExceptionHeaderValue.DW_EH_PE_udata2 -> - let struct (addr, offset) = reader.ReadUInt16 offset - let struct (len, _) = reader.ReadUInt16 offset - uint64 addr, uint64 len - | ExceptionHeaderValue.DW_EH_PE_sdata2 -> - let struct (addr, offset) = reader.ReadInt16 offset - let struct (len, _) = reader.ReadInt16 offset - uint64 addr, uint64 len - | ExceptionHeaderValue.DW_EH_PE_udata4 -> - let struct (addr, offset) = reader.ReadUInt32 offset - let struct (len, _) = reader.ReadUInt32 offset - uint64 addr, uint64 len - | ExceptionHeaderValue.DW_EH_PE_sdata4 -> - let struct (addr, offset) = reader.ReadInt32 offset - let struct (len, _) = reader.ReadInt32 offset - uint64 addr, uint64 len - | ExceptionHeaderValue.DW_EH_PE_udata8 -> - let struct (addr, offset) = reader.ReadUInt64 offset - let struct (len, _) = reader.ReadUInt64 offset - addr, len - | ExceptionHeaderValue.DW_EH_PE_sdata8 -> - let struct (addr, offset) = reader.ReadInt64 offset - let struct (len, _) = reader.ReadInt64 offset - uint64 addr, uint64 len - | _ -> raise UnhandledEncoding - -let adjustPCAddr cie myAddr addr = - match cie.FDEApplication with - | ExceptionHeaderApplication.DW_EH_PE_pcrel -> addr + myAddr - | _ -> addr - -let parseFDE cls (reader: BinReader) sAddr cie offset = - let myAddr = sAddr + uint64 offset - let addr, len = computePCInfo cls reader cie offset - let addr = adjustPCAddr cie myAddr addr - { PCBegin = addr; PCEnd = addr + len } - -let accumulateCFIs cfis cie fdes = - match cie with - | Some cie -> - { CIERecord = cie - FDERecord = List.rev fdes |> List.toArray } :: cfis - | None -> cfis - -let rec parseCallFrameInformation cls reader sAddr cie fdes offset cfis = - if offset >= ((reader: BinReader).Length ()) then accumulateCFIs cfis cie fdes - else - let struct (len, offset) = readInt reader offset - if len = 0 then accumulateCFIs cfis cie fdes - else - let nextOffset, offset = computeNextOffset len reader offset - let struct (id, offset) = readInt reader offset - if id = 0 then - let cfis = accumulateCFIs cfis cie fdes - let cie = parseCIE cls reader offset - parseCallFrameInformation cls reader sAddr (Some cie) [] nextOffset cfis - else - match cie with - | Some c -> - let fde = parseFDE cls reader sAddr c offset - let fdes = fde :: fdes - parseCallFrameInformation cls reader sAddr cie fdes nextOffset cfis - | None -> invalidArg "parseCallFrameInformation" "CIE not present" - -let parse (reader: BinReader) cls (secs: SectionInfo) = - match Map.tryFind ehframe secs.SecByName with - | Some sec -> - let size = Convert.ToInt32 sec.SecSize - let offset = Convert.ToInt32 sec.SecOffset - let reader = reader.SubReader offset size - parseCallFrameInformation cls reader sec.SecAddr None [] 0 [] - | None -> [] diff --git a/src/BinGraph.Tests/B2R2.BinGraph.Tests.fsproj b/src/BinGraph.Tests/B2R2.BinGraph.Tests.fsproj deleted file mode 100644 index 7888a654..00000000 --- a/src/BinGraph.Tests/B2R2.BinGraph.Tests.fsproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - netcoreapp3.0 - false - - - - - - - - - - - - - - - - - - - - diff --git a/src/BinGraph.Tests/ImperativeGraph.Tests.fs b/src/BinGraph.Tests/ImperativeGraph.Tests.fs deleted file mode 100644 index c0996128..00000000 --- a/src/BinGraph.Tests/ImperativeGraph.Tests.fs +++ /dev/null @@ -1,473 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinGraph.Tests - -open B2R2 -open B2R2.BinGraph -open Microsoft.VisualStudio.TestTools.UnitTesting - -[] -type BasicImperativeGraphTest () = - let v1 = V (1, (AddrRange (1UL, 2UL))) - let v2 = V (2, (AddrRange (2UL, 3UL))) - let v3 = V (3, (AddrRange (3UL, 4UL))) - let v4 = V (4, (AddrRange (4UL, 5UL))) - let v5 = V (5, (AddrRange (5UL, 6UL))) - let v6 = V (6, (AddrRange (6UL, 7UL))) - let v7 = V (7, (AddrRange (7UL, 8UL))) - let v8 = V (8, (AddrRange (8UL, 9UL))) - let v9 = V (9, (AddrRange (9UL, 10UL))) - let v10 = V (10, (AddrRange (10UL, 11UL))) - let v11 = V (11, (AddrRange (11UL, 12UL))) - let v12 = V (12, (AddrRange (12UL, 13UL))) - let v13 = V (13, (AddrRange (13UL, 14UL))) - - (* Graph example from Wikipedia. *) - let g1 = RangedDiGraph.init -1 ImperativeGraph - let n1, g1 = DiGraph.addVertex g1 v1 // Node 1 - let n2, g1 = DiGraph.addVertex g1 v2 // Node 2 - let n3, g1 = DiGraph.addVertex g1 v3 // Node 3 - let n4, g1 = DiGraph.addVertex g1 v4 // Node 4 - let n5, g1 = DiGraph.addVertex g1 v5 // Node 5 - let n6, g1 = DiGraph.addVertex g1 v6 // Node 6 - let g1 = DiGraph.addEdge g1 n1 n2 1 - let g1 = DiGraph.addEdge g1 n2 n3 2 - let g1 = DiGraph.addEdge g1 n2 n4 3 - let g1 = DiGraph.addEdge g1 n2 n6 4 - let g1 = DiGraph.addEdge g1 n3 n5 5 - let g1 = DiGraph.addEdge g1 n4 n5 6 - let g1 = DiGraph.addEdge g1 n5 n2 7 - let g1root = n1 - let ctxt1 = Dominator.initDominatorContext g1 g1root - - (* Graph example from Tiger book. *) - let g2 = RangedDiGraph.init -1 ImperativeGraph - let n1, g2 = DiGraph.addVertex g2 v1 // Node 1 - let n2, g2 = DiGraph.addVertex g2 v2 // Node 2 - let n3, g2 = DiGraph.addVertex g2 v3 // Node 3 - let n4, g2 = DiGraph.addVertex g2 v4 // Node 4 - let n5, g2 = DiGraph.addVertex g2 v5 // Node 5 - let n6, g2 = DiGraph.addVertex g2 v6 // Node 6 - let g2 = DiGraph.addEdge g2 n1 n2 1 - let g2 = DiGraph.addEdge g2 n1 n3 2 - let g2 = DiGraph.addEdge g2 n3 n4 3 - let g2 = DiGraph.addEdge g2 n4 n5 4 - let g2 = DiGraph.addEdge g2 n4 n6 5 - let g2 = DiGraph.addEdge g2 n6 n4 6 - let g2root = n1 - let ctxt2 = Dominator.initDominatorContext g2 g2root - - (* Arbitrary graph example *) - let g3 = RangedDiGraph.init -1 ImperativeGraph - let n1, g3 = DiGraph.addVertex g3 v1 // Node 1 - let n2, g3 = DiGraph.addVertex g3 v2 // Node 2 - let n3, g3 = DiGraph.addVertex g3 v3 // Node 3 - let n4, g3 = DiGraph.addVertex g3 v4 // Node 4 - let n5, g3 = DiGraph.addVertex g3 v5 // Node 5 - let g3 = DiGraph.addEdge g3 n1 n2 1 - let g3 = DiGraph.addEdge g3 n1 n3 2 - let g3 = DiGraph.addEdge g3 n2 n4 3 - let g3 = DiGraph.addEdge g3 n3 n4 4 - let g3 = DiGraph.addEdge g3 n3 n5 5 - let g3root = n1 - let ctxt3 = Dominator.initDominatorContext g3 g3root - - (* Graph example from Tiger book (Fig. 19.5) *) - let g4 = RangedDiGraph.init -1 ImperativeGraph - let n1, g4 = DiGraph.addVertex g4 v1 - let n2, g4 = DiGraph.addVertex g4 v2 - let n3, g4 = DiGraph.addVertex g4 v3 - let n4, g4 = DiGraph.addVertex g4 v4 - let n5, g4 = DiGraph.addVertex g4 v5 - let n6, g4 = DiGraph.addVertex g4 v6 - let n7, g4 = DiGraph.addVertex g4 v7 - let n8, g4 = DiGraph.addVertex g4 v8 - let n9, g4 = DiGraph.addVertex g4 v9 - let n10, g4 = DiGraph.addVertex g4 v10 - let n11, g4 = DiGraph.addVertex g4 v11 - let n12, g4 = DiGraph.addVertex g4 v12 - let n13, g4 = DiGraph.addVertex g4 v13 - let g4 = DiGraph.addEdge g4 n1 n2 1 - let g4 = DiGraph.addEdge g4 n1 n5 2 - let g4 = DiGraph.addEdge g4 n1 n9 3 - let g4 = DiGraph.addEdge g4 n2 n3 4 - let g4 = DiGraph.addEdge g4 n3 n3 5 - let g4 = DiGraph.addEdge g4 n3 n4 6 - let g4 = DiGraph.addEdge g4 n4 n13 7 - let g4 = DiGraph.addEdge g4 n5 n6 8 - let g4 = DiGraph.addEdge g4 n5 n7 9 - let g4 = DiGraph.addEdge g4 n6 n4 10 - let g4 = DiGraph.addEdge g4 n6 n8 11 - let g4 = DiGraph.addEdge g4 n7 n8 12 - let g4 = DiGraph.addEdge g4 n7 n12 13 - let g4 = DiGraph.addEdge g4 n8 n5 14 - let g4 = DiGraph.addEdge g4 n8 n13 15 - let g4 = DiGraph.addEdge g4 n9 n10 16 - let g4 = DiGraph.addEdge g4 n9 n11 17 - let g4 = DiGraph.addEdge g4 n10 n12 18 - let g4 = DiGraph.addEdge g4 n11 n12 19 - let g4 = DiGraph.addEdge g4 n12 n13 20 - let g4root = n1 - let ctxt4 = Dominator.initDominatorContext g4 g4root - - let getVertexVal (v: Vertex option) = (Option.get v).VData.Val - - let sum acc (v: Vertex) = v.VData.Val + acc - let inc acc _v1 _v2 e = acc + e - - [] - member __.``RangedDiGraph Traversal Test 1``() = - let s1 = Traversal.foldPostorder g1 g1root sum 0 - let s2 = Traversal.foldRevPostorder g1 g1root sum 0 - let s3 = Traversal.foldPreorder g1 g1root sum 0 - let s4 = DiGraph.foldVertex g1 sum 0 - let s5 = DiGraph.foldEdge g1 inc 0 - Assert.AreEqual (21, s1) - Assert.AreEqual (21, s2) - Assert.AreEqual (21, s3) - Assert.AreEqual (21, s4) - Assert.AreEqual (28, s5) - - [] - member __.``RangedDiGraph Traversal Test 2``() = - let s1 = - Traversal.foldPostorder g1 g1root (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - let s2 = - Traversal.foldPreorder g1 g1root (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - let s3 = - Traversal.foldPostorder g3 g3root (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - let s4 = - Traversal.foldPreorder g3 g3root (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - CollectionAssert.AreEqual ([| 5; 3; 4; 6; 2; 1 |], s1) - CollectionAssert.AreEqual ([| 1; 2; 3; 5; 4; 6 |], s2) - CollectionAssert.AreEqual ([| 4; 2; 5; 3; 1 |], s3) - CollectionAssert.AreEqual ([| 1; 2; 4; 3; 5 |], s4) - - [] - member __.``RangedDiGraph Removal Test``() = - let g2 = g1.Clone () - let g2root = DiGraph.findVertexByData g2 g1root.VData - let g2 = - (g2 :?> RangedDiGraph<_, _>).FindVertexByRange (AddrRange (3UL, 4UL)) - |> DiGraph.removeVertex g2 - let s1 = Traversal.foldPreorder g1 g1root sum 0 - let s2 = Traversal.foldPreorder g2 g2root sum 0 - Assert.AreEqual (6, DiGraph.getSize g1) - Assert.AreEqual (5, DiGraph.getSize g2) - Assert.AreEqual (21, s1) - Assert.AreEqual (18, s2) - - [] - member __.``Graph Transposition Test``() = - let g2 = DiGraph.reverse g1 - let g2root = DiGraph.findVertexByData g2 v6 - let s1 = Traversal.foldPreorder g1 g1root sum 0 - let s2 = Traversal.foldPreorder g2 g2root sum 0 - let lst = - g2.FoldEdge (fun acc s d _ -> (s.VData.Val, d.VData.Val) :: acc) [] - let edges = List.sort lst |> List.toArray - let solution = [| (2, 1); (2, 5); (3, 2); (4, 2); (5, 3); (5, 4); (6, 2) |] - Assert.AreEqual (6, DiGraph.getSize g1) - Assert.AreEqual (6, DiGraph.getSize g2) - Assert.AreEqual (21, s1) - Assert.AreEqual (21, s2) - CollectionAssert.AreEqual (edges, solution) - - [] - member __.``Dominator Test 1``() = - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v2 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v3 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v4 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v5 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v6 - Assert.AreEqual (2, getVertexVal v) - - [] - member __.``Dominator Test 2``() = - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v2 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v3 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v4 - Assert.AreEqual (3, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v5 - Assert.AreEqual (4, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v6 - Assert.AreEqual (4, getVertexVal v) - - [] - member __.``Post-Dominator Test``() = - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v1 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v2 - Assert.AreEqual (6, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v3 - Assert.AreEqual (5, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v4 - Assert.AreEqual (5, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v5 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v6 - Assert.IsTrue (v.IsNone) - - [] - member __.``Post-Dominator Test 2``() = - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v2 - Assert.AreEqual (4, getVertexVal v) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v3 - Assert.IsTrue (v.IsNone) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v4 - Assert.IsTrue (v.IsNone) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v5 - Assert.IsTrue (v.IsNone) - - [] - member __.``Dominance Frontier Test``() = - let df = - Dominator.frontier ctxt4 <| DiGraph.findVertexByData g4 v5 |> List.toArray - let df = df |> Array.map (fun v -> v.VData.Val) |> Array.sort - CollectionAssert.AreEqual (df, [|4; 5; 12; 13|]) - let df = - Dominator.frontier ctxt4 <| DiGraph.findVertexByData g4 v9 |> List.toArray - let df = df |> Array.map (fun v -> v.VData.Val) |> Array.sort - CollectionAssert.AreEqual (df, [|12|]) - - [] - member __.``Root Node Loop Test``() = - let g = RangedDiGraph.init -1 ImperativeGraph - let n1, g = DiGraph.addVertex g v1 // Node 1 - let n2, g = DiGraph.addVertex g v2 // Node 2 - let n3, g = DiGraph.addVertex g v3 // Node 3 - let n4, g = DiGraph.addVertex g v4 // Node 4 - let n5, g = DiGraph.addVertex g v5 // Node 5 - let n6, g = DiGraph.addVertex g v6 // Node 6 - let g = DiGraph.addEdge g n1 n2 1 - let g = DiGraph.addEdge g n1 n3 2 - let g = DiGraph.addEdge g n2 n4 3 - let g = DiGraph.addEdge g n3 n4 4 - let g = DiGraph.addEdge g n3 n5 5 - let g = DiGraph.addEdge g n4 n6 6 - let g = DiGraph.addEdge g n5 n6 7 - let g = DiGraph.addEdge g n6 n1 8 // Back edge to the root node. - let ctxt = Dominator.initDominatorContext g n1 - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v2 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v3 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v4 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v5 - Assert.AreEqual (3, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v6 - Assert.AreEqual (1, getVertexVal v) - - [] - member __.``Basic SCC Test``() = - let v = DiGraph.findVertexByData g3 v1 - let sccs = SCC.compute g3 v - Assert.AreEqual (5, Set.count sccs) - -[] -type ExtraImperativeDomTest () = - let v1 = V (1, (AddrRange (1UL, 2UL))) - let v2 = V (2, (AddrRange (2UL, 3UL))) - let v3 = V (3, (AddrRange (3UL, 4UL))) - let v4 = V (4, (AddrRange (4UL, 5UL))) - let v5 = V (5, (AddrRange (5UL, 6UL))) - let v6 = V (6, (AddrRange (6UL, 7UL))) - let v7 = V (7, (AddrRange (7UL, 8UL))) - let v8 = V (8, (AddrRange (8UL, 9UL))) - let v9 = V (9, (AddrRange (9UL, 10UL))) - let v10 = V (10, (AddrRange (10UL, 11UL))) - let v11 = V (11, (AddrRange (11UL, 12UL))) - let v12 = V (12, (AddrRange (12UL, 13UL))) - let v13 = V (13, (AddrRange (13UL, 14UL))) - let v14 = V (14, (AddrRange (14UL, 15UL))) - let v15 = V (15, (AddrRange (15UL, 16UL))) - let v16 = V (16, (AddrRange (16UL, 17UL))) - let v17 = V (17, (AddrRange (17UL, 18UL))) - let v18 = V (18, (AddrRange (18UL, 19UL))) - let v19 = V (19, (AddrRange (19UL, 20UL))) - let v20 = V (20, (AddrRange (20UL, 21UL))) - let v21 = V (21, (AddrRange (21UL, 22UL))) - let v22 = V (22, (AddrRange (22UL, 23UL))) - let v23 = V (23, (AddrRange (23UL, 24UL))) - - let g1 = RangedDiGraph.init -1 ImperativeGraph - let n1, g1 = DiGraph.addVertex g1 v1 - let n2, g1 = DiGraph.addVertex g1 v2 - let n3, g1 = DiGraph.addVertex g1 v3 - let n4, g1 = DiGraph.addVertex g1 v4 - let n5, g1 = DiGraph.addVertex g1 v5 - let n6, g1 = DiGraph.addVertex g1 v6 - let n7, g1 = DiGraph.addVertex g1 v7 - let n8, g1 = DiGraph.addVertex g1 v8 - let n9, g1 = DiGraph.addVertex g1 v9 - let n10, g1 = DiGraph.addVertex g1 v10 - let n11, g1 = DiGraph.addVertex g1 v11 - let n12, g1 = DiGraph.addVertex g1 v12 - let n13, g1 = DiGraph.addVertex g1 v13 - let n14, g1 = DiGraph.addVertex g1 v14 - let n15, g1 = DiGraph.addVertex g1 v15 - let n16, g1 = DiGraph.addVertex g1 v16 - let n17, g1 = DiGraph.addVertex g1 v17 - let n18, g1 = DiGraph.addVertex g1 v18 - let n19, g1 = DiGraph.addVertex g1 v19 - let n20, g1 = DiGraph.addVertex g1 v20 - let n21, g1 = DiGraph.addVertex g1 v21 - let n22, g1 = DiGraph.addVertex g1 v22 - let n23, g1 = DiGraph.addVertex g1 v23 - let g1 = DiGraph.addEdge g1 n1 n2 1 - let g1 = DiGraph.addEdge g1 n1 n3 2 - let g1 = DiGraph.addEdge g1 n2 n4 3 - let g1 = DiGraph.addEdge g1 n2 n7 4 - let g1 = DiGraph.addEdge g1 n3 n5 5 - let g1 = DiGraph.addEdge g1 n3 n6 6 - let g1 = DiGraph.addEdge g1 n4 n7 7 - let g1 = DiGraph.addEdge g1 n5 n8 8 - let g1 = DiGraph.addEdge g1 n5 n10 9 - let g1 = DiGraph.addEdge g1 n7 n9 10 - let g1 = DiGraph.addEdge g1 n7 n11 11 - let g1 = DiGraph.addEdge g1 n8 n10 12 - let g1 = DiGraph.addEdge g1 n9 n12 13 - let g1 = DiGraph.addEdge g1 n9 n13 14 - let g1 = DiGraph.addEdge g1 n10 n19 15 - let g1 = DiGraph.addEdge g1 n11 n22 16 - let g1 = DiGraph.addEdge g1 n12 n13 17 - let g1 = DiGraph.addEdge g1 n13 n14 18 - let g1 = DiGraph.addEdge g1 n13 n15 19 - let g1 = DiGraph.addEdge g1 n14 n16 20 - let g1 = DiGraph.addEdge g1 n15 n16 21 - let g1 = DiGraph.addEdge g1 n16 n17 22 - let g1 = DiGraph.addEdge g1 n16 n18 23 - let g1 = DiGraph.addEdge g1 n17 n18 24 - let g1 = DiGraph.addEdge g1 n18 n19 25 - let g1 = DiGraph.addEdge g1 n18 n20 26 - let g1 = DiGraph.addEdge g1 n19 n21 27 - let g1 = DiGraph.addEdge g1 n19 n23 28 - let g1 = DiGraph.addEdge g1 n20 n22 29 - let g1 = DiGraph.addEdge g1 n21 n22 30 - let g1root = n1 - let ctxt1 = Dominator.initDominatorContext g1 g1root - - let getVertexVal (v: Vertex option) = (Option.get v).VData.Val - - [] - member __.``Dominator Test``() = - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v19 - Assert.IsTrue (18 <> getVertexVal v) - -[] -type ImperativeSCCTest () = - let v1 = V (1, (AddrRange (1UL, 2UL))) - let v2 = V (2, (AddrRange (2UL, 3UL))) - let v3 = V (3, (AddrRange (3UL, 4UL))) - let v4 = V (4, (AddrRange (4UL, 5UL))) - let v5 = V (5, (AddrRange (5UL, 6UL))) - let v6 = V (6, (AddrRange (6UL, 7UL))) - let v7 = V (7, (AddrRange (7UL, 8UL))) - let v8 = V (8, (AddrRange (8UL, 9UL))) - - (* Example from article about Bourdoncle Components by Matt Elder *) - [] - member __.``Strongly Connected Component Test1`` () = - let g = RangedDiGraph.init -1 ImperativeGraph - let n1, g = DiGraph.addVertex g v1 - let n2, g = DiGraph.addVertex g v2 - let n3, g = DiGraph.addVertex g v3 - let n4, g = DiGraph.addVertex g v4 - let n5, g = DiGraph.addVertex g v5 - let n6, g = DiGraph.addVertex g v6 - let n7, g = DiGraph.addVertex g v7 - let n8, g = DiGraph.addVertex g v8 - let g = DiGraph.addEdge g n1 n2 1 - let g = DiGraph.addEdge g n2 n3 2 - let g = DiGraph.addEdge g n3 n4 3 - let g = DiGraph.addEdge g n4 n5 4 - let g = DiGraph.addEdge g n5 n2 5 - let g = DiGraph.addEdge g n5 n6 6 - let g = DiGraph.addEdge g n6 n3 7 - let g = DiGraph.addEdge g n6 n7 8 - let g = DiGraph.addEdge g n7 n2 9 - let g = DiGraph.addEdge g n7 n8 10 - let sccs = SCC.compute g n1 - Assert.AreEqual (3, Set.count sccs) - let scc1 = Set.singleton n1 - Assert.IsTrue (Set.contains scc1 sccs) - let scc2 = Set.singleton n8 - Assert.IsTrue (Set.contains scc2 sccs) - let scc3 = Set.ofList [ n2 ; n3 ; n4 ; n5 ; n6 ; n7 ] - Assert.IsTrue (Set.contains scc3 sccs) - - (* Example from Wikipedia *) - [] - member __.``Strongly Connected Component Test2`` () = - let g = RangedDiGraph.init -1 ImperativeGraph - let na, g = DiGraph.addVertex g v1 - let nb, g = DiGraph.addVertex g v2 - let nc, g = DiGraph.addVertex g v3 - let nd, g = DiGraph.addVertex g v4 - let ne, g = DiGraph.addVertex g v5 - let nf, g = DiGraph.addVertex g v6 - let ng, g = DiGraph.addVertex g v7 - let nh, g = DiGraph.addVertex g v8 - let g = DiGraph.addEdge g na nb 1 - let g = DiGraph.addEdge g nb nc 2 - let g = DiGraph.addEdge g nb ne 3 - let g = DiGraph.addEdge g nb nf 4 - let g = DiGraph.addEdge g nc nd 5 - let g = DiGraph.addEdge g nc ng 6 - let g = DiGraph.addEdge g nd nc 7 - let g = DiGraph.addEdge g nd nh 8 - let g = DiGraph.addEdge g ne na 9 - let g = DiGraph.addEdge g ne nf 10 - let g = DiGraph.addEdge g nf ng 11 - let g = DiGraph.addEdge g ng nf 12 - let g = DiGraph.addEdge g nh nd 13 - let g = DiGraph.addEdge g nh ng 14 - let sccs = SCC.compute g na - Assert.AreEqual (3, Set.count sccs) - let scc1 = Set.ofList [ na ; nb ; ne ] - Assert.IsTrue (Set.contains scc1 sccs) - let scc2 = Set.ofList [ nc ; nd ; nh ] - Assert.IsTrue (Set.contains scc2 sccs) - let scc3 = Set.ofList [ nf ; ng ] - Assert.IsTrue (Set.contains scc3 sccs) diff --git a/src/BinGraph.Tests/PersistentGraph.Tests.fs b/src/BinGraph.Tests/PersistentGraph.Tests.fs deleted file mode 100644 index ff14b41c..00000000 --- a/src/BinGraph.Tests/PersistentGraph.Tests.fs +++ /dev/null @@ -1,473 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinGraph.Tests - -open B2R2 -open B2R2.BinGraph -open Microsoft.VisualStudio.TestTools.UnitTesting - -[] -type BasicPersistentGraphTest () = - let v1 = V (1, (AddrRange (1UL, 2UL))) - let v2 = V (2, (AddrRange (2UL, 3UL))) - let v3 = V (3, (AddrRange (3UL, 4UL))) - let v4 = V (4, (AddrRange (4UL, 5UL))) - let v5 = V (5, (AddrRange (5UL, 6UL))) - let v6 = V (6, (AddrRange (6UL, 7UL))) - let v7 = V (7, (AddrRange (7UL, 8UL))) - let v8 = V (8, (AddrRange (8UL, 9UL))) - let v9 = V (9, (AddrRange (9UL, 10UL))) - let v10 = V (10, (AddrRange (10UL, 11UL))) - let v11 = V (11, (AddrRange (11UL, 12UL))) - let v12 = V (12, (AddrRange (12UL, 13UL))) - let v13 = V (13, (AddrRange (13UL, 14UL))) - - (* Graph example from Wikipedia. *) - let g1 = RangedDiGraph.init -1 PersistentGraph - let n1, g1 = DiGraph.addVertex g1 v1 // Node 1 - let n2, g1 = DiGraph.addVertex g1 v2 // Node 2 - let n3, g1 = DiGraph.addVertex g1 v3 // Node 3 - let n4, g1 = DiGraph.addVertex g1 v4 // Node 4 - let n5, g1 = DiGraph.addVertex g1 v5 // Node 5 - let n6, g1 = DiGraph.addVertex g1 v6 // Node 6 - let g1 = DiGraph.addEdge g1 n1 n2 1 - let g1 = DiGraph.addEdge g1 n2 n3 2 - let g1 = DiGraph.addEdge g1 n2 n4 3 - let g1 = DiGraph.addEdge g1 n2 n6 4 - let g1 = DiGraph.addEdge g1 n3 n5 5 - let g1 = DiGraph.addEdge g1 n4 n5 6 - let g1 = DiGraph.addEdge g1 n5 n2 7 - let g1root = n1 - let ctxt1 = Dominator.initDominatorContext g1 g1root - - (* Graph example from Tiger book. *) - let g2 = RangedDiGraph.init -1 PersistentGraph - let n1, g2 = DiGraph.addVertex g2 v1 // Node 1 - let n2, g2 = DiGraph.addVertex g2 v2 // Node 2 - let n3, g2 = DiGraph.addVertex g2 v3 // Node 3 - let n4, g2 = DiGraph.addVertex g2 v4 // Node 4 - let n5, g2 = DiGraph.addVertex g2 v5 // Node 5 - let n6, g2 = DiGraph.addVertex g2 v6 // Node 6 - let g2 = DiGraph.addEdge g2 n1 n2 1 - let g2 = DiGraph.addEdge g2 n1 n3 2 - let g2 = DiGraph.addEdge g2 n3 n4 3 - let g2 = DiGraph.addEdge g2 n4 n5 4 - let g2 = DiGraph.addEdge g2 n4 n6 5 - let g2 = DiGraph.addEdge g2 n6 n4 6 - let g2root = n1 - let ctxt2 = Dominator.initDominatorContext g2 g2root - - (* Arbitrary graph example *) - let g3 = RangedDiGraph.init -1 PersistentGraph - let n1, g3 = DiGraph.addVertex g3 v1 // Node 1 - let n2, g3 = DiGraph.addVertex g3 v2 // Node 2 - let n3, g3 = DiGraph.addVertex g3 v3 // Node 3 - let n4, g3 = DiGraph.addVertex g3 v4 // Node 4 - let n5, g3 = DiGraph.addVertex g3 v5 // Node 5 - let g3 = DiGraph.addEdge g3 n1 n2 1 - let g3 = DiGraph.addEdge g3 n1 n3 2 - let g3 = DiGraph.addEdge g3 n2 n4 3 - let g3 = DiGraph.addEdge g3 n3 n4 4 - let g3 = DiGraph.addEdge g3 n3 n5 5 - let g3root = n1 - let ctxt3 = Dominator.initDominatorContext g3 g3root - - (* Graph example from Tiger book (Fig. 19.5) *) - let g4 = RangedDiGraph.init -1 PersistentGraph - let n1, g4 = DiGraph.addVertex g4 v1 - let n2, g4 = DiGraph.addVertex g4 v2 - let n3, g4 = DiGraph.addVertex g4 v3 - let n4, g4 = DiGraph.addVertex g4 v4 - let n5, g4 = DiGraph.addVertex g4 v5 - let n6, g4 = DiGraph.addVertex g4 v6 - let n7, g4 = DiGraph.addVertex g4 v7 - let n8, g4 = DiGraph.addVertex g4 v8 - let n9, g4 = DiGraph.addVertex g4 v9 - let n10, g4 = DiGraph.addVertex g4 v10 - let n11, g4 = DiGraph.addVertex g4 v11 - let n12, g4 = DiGraph.addVertex g4 v12 - let n13, g4 = DiGraph.addVertex g4 v13 - let g4 = DiGraph.addEdge g4 n1 n2 1 - let g4 = DiGraph.addEdge g4 n1 n5 2 - let g4 = DiGraph.addEdge g4 n1 n9 3 - let g4 = DiGraph.addEdge g4 n2 n3 4 - let g4 = DiGraph.addEdge g4 n3 n3 5 - let g4 = DiGraph.addEdge g4 n3 n4 6 - let g4 = DiGraph.addEdge g4 n4 n13 7 - let g4 = DiGraph.addEdge g4 n5 n6 8 - let g4 = DiGraph.addEdge g4 n5 n7 9 - let g4 = DiGraph.addEdge g4 n6 n4 10 - let g4 = DiGraph.addEdge g4 n6 n8 11 - let g4 = DiGraph.addEdge g4 n7 n8 12 - let g4 = DiGraph.addEdge g4 n7 n12 13 - let g4 = DiGraph.addEdge g4 n8 n5 14 - let g4 = DiGraph.addEdge g4 n8 n13 15 - let g4 = DiGraph.addEdge g4 n9 n10 16 - let g4 = DiGraph.addEdge g4 n9 n11 17 - let g4 = DiGraph.addEdge g4 n10 n12 18 - let g4 = DiGraph.addEdge g4 n11 n12 19 - let g4 = DiGraph.addEdge g4 n12 n13 20 - let g4root = n1 - let ctxt4 = Dominator.initDominatorContext g4 g4root - - let getVertexVal (v: Vertex option) = (Option.get v).VData.Val - - let sum acc (v: Vertex) = v.VData.Val + acc - let inc acc _v1 _v2 e = acc + e - - [] - member __.``RangedDiGraph Traversal Test 1``() = - let s1 = Traversal.foldPostorder g1 g1root sum 0 - let s2 = Traversal.foldRevPostorder g1 g1root sum 0 - let s3 = Traversal.foldPreorder g1 g1root sum 0 - let s4 = DiGraph.foldVertex g1 sum 0 - let s5 = DiGraph.foldEdge g1 inc 0 - Assert.AreEqual (21, s1) - Assert.AreEqual (21, s2) - Assert.AreEqual (21, s3) - Assert.AreEqual (21, s4) - Assert.AreEqual (28, s5) - - [] - member __.``RangedDiGraph Traversal Test 2``() = - let s1 = - Traversal.foldPostorder g1 g1root (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - let s2 = - Traversal.foldPreorder g1 g1root (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - let s3 = - Traversal.foldPostorder g3 g3root (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - let s4 = - Traversal.foldPreorder g3 g3root (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - CollectionAssert.AreEqual ([| 5; 3; 4; 6; 2; 1 |], s1) - CollectionAssert.AreEqual ([| 1; 2; 3; 5; 4; 6 |], s2) - CollectionAssert.AreEqual ([| 4; 2; 5; 3; 1 |], s3) - CollectionAssert.AreEqual ([| 1; 2; 4; 3; 5 |], s4) - - [] - member __.``RangedDiGraph Removal Test``() = - let g2 = g1.Clone () - let g2root = DiGraph.findVertexByData g2 g1root.VData - let g2 = - (g2 :?> RangedDiGraph<_, _>).FindVertexByRange (AddrRange (3UL, 4UL)) - |> DiGraph.removeVertex g2 - let s1 = Traversal.foldPreorder g1 g1root sum 0 - let s2 = Traversal.foldPreorder g2 g2root sum 0 - Assert.AreEqual (6, DiGraph.getSize g1) - Assert.AreEqual (5, DiGraph.getSize g2) - Assert.AreEqual (21, s1) - Assert.AreEqual (18, s2) - - [] - member __.``Graph Transposition Test``() = - let g2 = DiGraph.reverse g1 - let g2root = DiGraph.findVertexByData g2 v6 - let s1 = Traversal.foldPreorder g1 g1root sum 0 - let s2 = Traversal.foldPreorder g2 g2root sum 0 - let lst = - g2.FoldEdge (fun acc s d _ -> (s.VData.Val, d.VData.Val) :: acc) [] - let edges = List.sort lst |> List.toArray - let solution = [| (2, 1); (2, 5); (3, 2); (4, 2); (5, 3); (5, 4); (6, 2) |] - Assert.AreEqual (6, DiGraph.getSize g1) - Assert.AreEqual (6, DiGraph.getSize g2) - Assert.AreEqual (21, s1) - Assert.AreEqual (21, s2) - CollectionAssert.AreEqual (edges, solution) - - [] - member __.``Dominator Test 1``() = - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v2 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v3 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v4 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v5 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v6 - Assert.AreEqual (2, getVertexVal v) - - [] - member __.``Dominator Test 2``() = - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v2 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v3 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v4 - Assert.AreEqual (3, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v5 - Assert.AreEqual (4, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v6 - Assert.AreEqual (4, getVertexVal v) - - [] - member __.``Post-Dominator Test``() = - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v1 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v2 - Assert.AreEqual (6, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v3 - Assert.AreEqual (5, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v4 - Assert.AreEqual (5, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v5 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v6 - Assert.IsTrue (v.IsNone) - - [] - member __.``Post-Dominator Test 2``() = - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v2 - Assert.AreEqual (4, getVertexVal v) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v3 - Assert.IsTrue (v.IsNone) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v4 - Assert.IsTrue (v.IsNone) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v5 - Assert.IsTrue (v.IsNone) - - [] - member __.``Dominance Frontier Test``() = - let df = - Dominator.frontier ctxt4 <| DiGraph.findVertexByData g4 v5 |> List.toArray - let df = df |> Array.map (fun v -> v.VData.Val) |> Array.sort - CollectionAssert.AreEqual (df, [|4; 5; 12; 13|]) - let df = - Dominator.frontier ctxt4 <| DiGraph.findVertexByData g4 v9 |> List.toArray - let df = df |> Array.map (fun v -> v.VData.Val) |> Array.sort - CollectionAssert.AreEqual (df, [|12|]) - - [] - member __.``Root Node Loop Test``() = - let g = RangedDiGraph.init -1 PersistentGraph - let n1, g = DiGraph.addVertex g v1 // Node 1 - let n2, g = DiGraph.addVertex g v2 // Node 2 - let n3, g = DiGraph.addVertex g v3 // Node 3 - let n4, g = DiGraph.addVertex g v4 // Node 4 - let n5, g = DiGraph.addVertex g v5 // Node 5 - let n6, g = DiGraph.addVertex g v6 // Node 6 - let g = DiGraph.addEdge g n1 n2 1 - let g = DiGraph.addEdge g n1 n3 2 - let g = DiGraph.addEdge g n2 n4 3 - let g = DiGraph.addEdge g n3 n4 4 - let g = DiGraph.addEdge g n3 n5 5 - let g = DiGraph.addEdge g n4 n6 6 - let g = DiGraph.addEdge g n5 n6 7 - let g = DiGraph.addEdge g n6 n1 8 // Back edge to the root node. - let ctxt = Dominator.initDominatorContext g n1 - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v2 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v3 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v4 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v5 - Assert.AreEqual (3, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v6 - Assert.AreEqual (1, getVertexVal v) - - [] - member __.``Basic SCC Test``() = - let v = DiGraph.findVertexByData g3 v1 - let sccs = SCC.compute g3 v - Assert.AreEqual (5, Set.count sccs) - -[] -type ExtraPersistentDomTest () = - let v1 = V (1, (AddrRange (1UL, 2UL))) - let v2 = V (2, (AddrRange (2UL, 3UL))) - let v3 = V (3, (AddrRange (3UL, 4UL))) - let v4 = V (4, (AddrRange (4UL, 5UL))) - let v5 = V (5, (AddrRange (5UL, 6UL))) - let v6 = V (6, (AddrRange (6UL, 7UL))) - let v7 = V (7, (AddrRange (7UL, 8UL))) - let v8 = V (8, (AddrRange (8UL, 9UL))) - let v9 = V (9, (AddrRange (9UL, 10UL))) - let v10 = V (10, (AddrRange (10UL, 11UL))) - let v11 = V (11, (AddrRange (11UL, 12UL))) - let v12 = V (12, (AddrRange (12UL, 13UL))) - let v13 = V (13, (AddrRange (13UL, 14UL))) - let v14 = V (14, (AddrRange (14UL, 15UL))) - let v15 = V (15, (AddrRange (15UL, 16UL))) - let v16 = V (16, (AddrRange (16UL, 17UL))) - let v17 = V (17, (AddrRange (17UL, 18UL))) - let v18 = V (18, (AddrRange (18UL, 19UL))) - let v19 = V (19, (AddrRange (19UL, 20UL))) - let v20 = V (20, (AddrRange (20UL, 21UL))) - let v21 = V (21, (AddrRange (21UL, 22UL))) - let v22 = V (22, (AddrRange (22UL, 23UL))) - let v23 = V (23, (AddrRange (23UL, 24UL))) - - let g1 = RangedDiGraph.init -1 PersistentGraph - let n1, g1 = DiGraph.addVertex g1 v1 - let n2, g1 = DiGraph.addVertex g1 v2 - let n3, g1 = DiGraph.addVertex g1 v3 - let n4, g1 = DiGraph.addVertex g1 v4 - let n5, g1 = DiGraph.addVertex g1 v5 - let n6, g1 = DiGraph.addVertex g1 v6 - let n7, g1 = DiGraph.addVertex g1 v7 - let n8, g1 = DiGraph.addVertex g1 v8 - let n9, g1 = DiGraph.addVertex g1 v9 - let n10, g1 = DiGraph.addVertex g1 v10 - let n11, g1 = DiGraph.addVertex g1 v11 - let n12, g1 = DiGraph.addVertex g1 v12 - let n13, g1 = DiGraph.addVertex g1 v13 - let n14, g1 = DiGraph.addVertex g1 v14 - let n15, g1 = DiGraph.addVertex g1 v15 - let n16, g1 = DiGraph.addVertex g1 v16 - let n17, g1 = DiGraph.addVertex g1 v17 - let n18, g1 = DiGraph.addVertex g1 v18 - let n19, g1 = DiGraph.addVertex g1 v19 - let n20, g1 = DiGraph.addVertex g1 v20 - let n21, g1 = DiGraph.addVertex g1 v21 - let n22, g1 = DiGraph.addVertex g1 v22 - let n23, g1 = DiGraph.addVertex g1 v23 - let g1 = DiGraph.addEdge g1 n1 n2 1 - let g1 = DiGraph.addEdge g1 n1 n3 2 - let g1 = DiGraph.addEdge g1 n2 n4 3 - let g1 = DiGraph.addEdge g1 n2 n7 4 - let g1 = DiGraph.addEdge g1 n3 n5 5 - let g1 = DiGraph.addEdge g1 n3 n6 6 - let g1 = DiGraph.addEdge g1 n4 n7 7 - let g1 = DiGraph.addEdge g1 n5 n8 8 - let g1 = DiGraph.addEdge g1 n5 n10 9 - let g1 = DiGraph.addEdge g1 n7 n9 10 - let g1 = DiGraph.addEdge g1 n7 n11 11 - let g1 = DiGraph.addEdge g1 n8 n10 12 - let g1 = DiGraph.addEdge g1 n9 n12 13 - let g1 = DiGraph.addEdge g1 n9 n13 14 - let g1 = DiGraph.addEdge g1 n10 n19 15 - let g1 = DiGraph.addEdge g1 n11 n22 16 - let g1 = DiGraph.addEdge g1 n12 n13 17 - let g1 = DiGraph.addEdge g1 n13 n14 18 - let g1 = DiGraph.addEdge g1 n13 n15 19 - let g1 = DiGraph.addEdge g1 n14 n16 20 - let g1 = DiGraph.addEdge g1 n15 n16 21 - let g1 = DiGraph.addEdge g1 n16 n17 22 - let g1 = DiGraph.addEdge g1 n16 n18 23 - let g1 = DiGraph.addEdge g1 n17 n18 24 - let g1 = DiGraph.addEdge g1 n18 n19 25 - let g1 = DiGraph.addEdge g1 n18 n20 26 - let g1 = DiGraph.addEdge g1 n19 n21 27 - let g1 = DiGraph.addEdge g1 n19 n23 28 - let g1 = DiGraph.addEdge g1 n20 n22 29 - let g1 = DiGraph.addEdge g1 n21 n22 30 - let g1root = n1 - let ctxt1 = Dominator.initDominatorContext g1 g1root - - let getVertexVal (v: Vertex option) = (Option.get v).VData.Val - - [] - member __.``Dominator Test``() = - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v19 - Assert.IsTrue (18 <> getVertexVal v) - -[] -type PersistentSCCTest () = - let v1 = V (1, (AddrRange (1UL, 2UL))) - let v2 = V (2, (AddrRange (2UL, 3UL))) - let v3 = V (3, (AddrRange (3UL, 4UL))) - let v4 = V (4, (AddrRange (4UL, 5UL))) - let v5 = V (5, (AddrRange (5UL, 6UL))) - let v6 = V (6, (AddrRange (6UL, 7UL))) - let v7 = V (7, (AddrRange (7UL, 8UL))) - let v8 = V (8, (AddrRange (8UL, 9UL))) - - (* Example from article about Bourdoncle Components by Matt Elder *) - [] - member __.``Strongly Connected Component Test1`` () = - let g = RangedDiGraph.init -1 PersistentGraph - let n1, g = DiGraph.addVertex g v1 - let n2, g = DiGraph.addVertex g v2 - let n3, g = DiGraph.addVertex g v3 - let n4, g = DiGraph.addVertex g v4 - let n5, g = DiGraph.addVertex g v5 - let n6, g = DiGraph.addVertex g v6 - let n7, g = DiGraph.addVertex g v7 - let n8, g = DiGraph.addVertex g v8 - let g = DiGraph.addEdge g n1 n2 1 - let g = DiGraph.addEdge g n2 n3 2 - let g = DiGraph.addEdge g n3 n4 3 - let g = DiGraph.addEdge g n4 n5 4 - let g = DiGraph.addEdge g n5 n2 5 - let g = DiGraph.addEdge g n5 n6 6 - let g = DiGraph.addEdge g n6 n3 7 - let g = DiGraph.addEdge g n6 n7 8 - let g = DiGraph.addEdge g n7 n2 9 - let g = DiGraph.addEdge g n7 n8 10 - let sccs = SCC.compute g n1 - Assert.AreEqual (3, Set.count sccs) - let scc1 = Set.singleton n1 - Assert.IsTrue (Set.contains scc1 sccs) - let scc2 = Set.singleton n8 - Assert.IsTrue (Set.contains scc2 sccs) - let scc3 = Set.ofList [ n2 ; n3 ; n4 ; n5 ; n6 ; n7 ] - Assert.IsTrue (Set.contains scc3 sccs) - - (* Example from Wikipedia *) - [] - member __.``Strongly Connected Component Test2`` () = - let g = RangedDiGraph.init -1 PersistentGraph - let na, g = DiGraph.addVertex g v1 - let nb, g = DiGraph.addVertex g v2 - let nc, g = DiGraph.addVertex g v3 - let nd, g = DiGraph.addVertex g v4 - let ne, g = DiGraph.addVertex g v5 - let nf, g = DiGraph.addVertex g v6 - let ng, g = DiGraph.addVertex g v7 - let nh, g = DiGraph.addVertex g v8 - let g = DiGraph.addEdge g na nb 1 - let g = DiGraph.addEdge g nb nc 2 - let g = DiGraph.addEdge g nb ne 3 - let g = DiGraph.addEdge g nb nf 4 - let g = DiGraph.addEdge g nc nd 5 - let g = DiGraph.addEdge g nc ng 6 - let g = DiGraph.addEdge g nd nc 7 - let g = DiGraph.addEdge g nd nh 8 - let g = DiGraph.addEdge g ne na 9 - let g = DiGraph.addEdge g ne nf 10 - let g = DiGraph.addEdge g nf ng 11 - let g = DiGraph.addEdge g ng nf 12 - let g = DiGraph.addEdge g nh nd 13 - let g = DiGraph.addEdge g nh ng 14 - let sccs = SCC.compute g na - Assert.AreEqual (3, Set.count sccs) - let scc1 = Set.ofList [ na ; nb ; ne ] - Assert.IsTrue (Set.contains scc1 sccs) - let scc2 = Set.ofList [ nc ; nd ; nh ] - Assert.IsTrue (Set.contains scc2 sccs) - let scc3 = Set.ofList [ nf ; ng ] - Assert.IsTrue (Set.contains scc3 sccs) diff --git a/src/BinGraph/B2R2.BinGraph.fsproj b/src/BinGraph/B2R2.BinGraph.fsproj deleted file mode 100644 index db1568c1..00000000 --- a/src/BinGraph/B2R2.BinGraph.fsproj +++ /dev/null @@ -1,39 +0,0 @@ - - - - netstandard2.1 - false - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/BinGraph/DiGraph.fs b/src/BinGraph/DiGraph.fs deleted file mode 100644 index be2e7205..00000000 --- a/src/BinGraph/DiGraph.fs +++ /dev/null @@ -1,283 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinGraph - -[] -type DiGraph<'D, 'E when 'D :> VertexData and 'D : equality> - (core: GraphCore<'D, 'E, DiGraph<'D, 'E>>) = - inherit Graph<'D, 'E, DiGraph<'D, 'E>> () - - override __.ImplementationType = core.ImplementationType - - override __.IsEmpty () = core.GetSize () = 0 - - override __.GetSize () = core.GetSize () - - override __.AddVertex data = - let v, g = core.AddVertex __ data - v, g - - override __.RemoveVertex vid = - core.RemoveVertex __ vid - - override __.GetVertices () = - core.Vertices - - override __.ExistsVertex vid = - match core.TryFindVertexBy (fun v -> v.GetID () = vid) with - | Some _ -> true - | None -> false - - override __.FindVertexByID vid = - core.FindVertexBy (fun v -> v.GetID () = vid) - - override __.TryFindVertexByID vid = - core.TryFindVertexBy (fun v -> v.GetID () = vid) - |> Option.bind (fun v -> v |> Some) - - override __.FindVertexByData data = - core.FindVertexBy (fun v -> - if v.IsDummy () then false else v.VData = data) - - override __.TryFindVertexByData data = - core.TryFindVertexBy (fun v -> - if v.IsDummy () then false else v.VData = data) - |> Option.bind (fun v -> v |> Some) - - override __.FindVertexBy fn = - core.FindVertexBy fn - - override __.TryFindVertexBy fn = - core.TryFindVertexBy fn |> Option.bind (fun v -> v |> Some) - - override __.AddEdge srcid dstid e = - core.AddEdge __ srcid dstid e - - override __.RemoveEdge srcid dstid = - core.RemoveEdge __ srcid dstid - - override __.FindEdgeData src dst = - core.FindEdge src dst - - override __.TryFindEdgeData src dst = - core.TryFindEdge src dst - - override __.FoldVertex fn acc = - core.FoldVertex fn acc - - override __.IterVertex fn = - core.IterVertex fn - - override __.FoldEdge fn acc = - core.FoldEdge fn acc - - override __.IterEdge fn = - core.IterEdge fn - - override __.Clone () = - core.InitGraph (Some core) - - override __.SubGraph vs = - let g = core.InitGraph None - (* Add vertices to new graph *) - let g = - vs |> Set.fold (fun (g: DiGraph<'D, 'E>) (v: Vertex<'D>) -> - g.AddVertex v.VData |> snd) g - (* Collect edges both ends are in vids *) - let es = - [] |> __.FoldEdge (fun acc src dst e -> - if Set.contains src vs && Set.contains dst vs then - (src, dst, e) :: acc - else acc) - (* Add edges to new graph *) - List.fold (fun g (src: Vertex<_>, dst: Vertex<_>, e) -> - let src = g.FindVertexByID <| src.GetID () - let dst = g.FindVertexByID <| dst.GetID () - g.AddEdge src dst e) g es - - override __.ToDOTStr name vToStrFn _eToStrFn = - let inline strAppend (s: string) (sb: System.Text.StringBuilder) = - sb.Append(s) - let folder sb src dst _edata = - strAppend (vToStrFn src) sb - |> strAppend " -> " - |> strAppend (vToStrFn dst) - |> strAppend " [label=\"" - |> strAppend "\"];\n" - let sb = System.Text.StringBuilder () - let sb = strAppend "digraph " sb |> strAppend name |> strAppend " {\n" - let sb = __.FoldEdge folder sb - sb.Append("}\n").ToString() - - /// A list of unreachable nodes. We always add nodes into this list first, and - /// then later remove it from the list when adding edges. - member __.Unreachables = core.Unreachables - - /// A list of exit nodes, which do not have any successors. - member __.Exits = core.Exits - - member __.GetPreds vid = core.GetPreds vid - - member __.GetSuccs vid = core.GetSuccs vid - - member __.AddDummyVertex () = - let v, g = core.AddDummyVertex __ - v, g - - member __.AddDummyEdge srcid dstid = - core.AddDummyEdge __ srcid dstid - - /// Return a new transposed (i.e., reversed) graph. - member __.Reverse () = - core.InitGraph None - |> __.FoldVertex (fun g v -> - if v.IsDummy () then g.AddDummyVertex () |> snd - else g.AddVertex v.VData |> snd) - |> __.FoldEdge (fun g src dst e -> - let src = g.FindVertexByID <| src.GetID () - let dst = g.FindVertexByID <| dst.GetID () - g.AddEdge dst src e) - - [] - static member isEmpty (g: DiGraph<'D, 'E>) = - g.IsEmpty () - - [] - static member getSize (g: DiGraph<'D, 'E>) = - g.GetSize () - - [] - static member addDummyVertex (g: DiGraph<'D, 'E>) = - g.AddDummyVertex () - - [] - static member addVertex (g: DiGraph<'D, 'E>) data = - g.AddVertex data - - [] - static member removeVertex (g: DiGraph<'D, 'E>) (v: Vertex<'D>)= - g.RemoveVertex v - - [] - static member getPreds (g: DiGraph<'D, 'E>) (v: Vertex<'D>) = - g.GetPreds v - - [] - static member getSuccs (g: DiGraph<'D, 'E>) (v: Vertex<'D>) = - g.GetSuccs v - - [] - static member getUnreachables (g: DiGraph<'D, 'E>) = - g.Unreachables - - [] - static member getExits (g: DiGraph<'D, 'E>) = - g.Exits - - [] - static member getVertices (g: DiGraph<'D, 'E>) = - g.GetVertices () - - [] - static member existsVertex (g: DiGraph<'D, 'E>) vid = - g.ExistsVertex vid - - [] - static member findVertexByID (g: DiGraph<'D, 'E>) vid = - g.FindVertexByID vid - - [] - static member tryFindVertexByID (g: DiGraph<'D, 'E>) vid = - g.TryFindVertexByID vid - - [] - static member findVertexByData (g: DiGraph<'D, 'E>) data = - g.FindVertexByData data - - [] - static member tryFindVertexByData (g: DiGraph<'D, 'E>) data = - g.TryFindVertexByData data - - [] - static member findVertexBy (g: DiGraph<'D, 'E>) fn = - g.FindVertexBy fn - - [] - static member tryFindVertexBy (g: DiGraph<'D, 'E>) fn = - g.TryFindVertexBy fn - - [] - static member addDummyEdge (g: DiGraph<'D, 'E>) src dst = - g.AddDummyEdge src dst - - [] - static member addEdge (g: DiGraph<'D, 'E>) src dst e = - g.AddEdge src dst e - - [] - static member removeEdge (g: DiGraph<'D, 'E>) src dst = - g.RemoveEdge src dst - - [] - static member findEdgeData (g: DiGraph<'D, 'E>) src dst = - g.FindEdgeData src dst - - [] - static member tryFindEdgeData (g: DiGraph<'D, 'E>) src dst = - g.TryFindEdgeData src dst - - [] - static member foldVertex (g: DiGraph<'D, 'E>) fn acc = - g.FoldVertex fn acc - - [] - static member iterVertex (g: DiGraph<'D, 'E>) fn = - g.IterVertex fn - - [] - static member foldEdge (g: DiGraph<'D, 'E>) fn acc = - g.FoldEdge fn acc - - [] - static member iterEdge (g: DiGraph<'D, 'E>) fn = - g.IterEdge fn - - [] - static member clone (g: DiGraph<'D, 'E>) = - g.Clone () - - [] - static member reverse (g: DiGraph<'D, 'E>) = - g.Reverse () - - [] - static member subGraph (g: DiGraph<'D, 'E>) vs = - g.SubGraph vs - - [] - static member toDOTStr (g: DiGraph<'D, 'E>) name vToStrfn eToStrFn = - g.ToDOTStr name vToStrfn eToStrFn - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/BinGraph/DiGraph.fsi b/src/BinGraph/DiGraph.fsi deleted file mode 100644 index c6a3d17a..00000000 --- a/src/BinGraph/DiGraph.fsi +++ /dev/null @@ -1,217 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinGraph - -/// Directedg graph inehrited from Graph. This type is mostly used by primary -/// graph algorithms, such as the dominator algorithm. We only expose static -/// members here to make code consistent for both persistent and imperative -/// graphs. -[] -type DiGraph<'D, 'E when 'D :> VertexData and 'D : equality> = - inherit Graph<'D, 'E, DiGraph<'D, 'E>> - - new: GraphCore<'D, 'E, DiGraph<'D, 'E>> -> DiGraph<'D, 'E> - override private ImplementationType: GraphImplementationType - override private IsEmpty: unit -> bool - override private GetSize: unit -> int - override private AddVertex: 'D -> Vertex<'D> * DiGraph<'D, 'E> - override private RemoveVertex: Vertex<'D> -> DiGraph<'D, 'E> - override private GetVertices: unit -> Set> - override private ExistsVertex: VertexID -> bool - override private FindVertexByID: VertexID -> Vertex<'D> - override private TryFindVertexByID: VertexID -> Vertex<'D> option - override private FindVertexByData: 'D -> Vertex<'D> - override private TryFindVertexByData: 'D -> Vertex<'D> option - override private FindVertexBy: (Vertex<'D> -> bool) -> Vertex<'D> - override private TryFindVertexBy: (Vertex<'D> -> bool) -> Vertex<'D> option - override private AddEdge: Vertex<'D> -> Vertex<'D> -> 'E -> DiGraph<'D, 'E> - override private RemoveEdge: Vertex<'D> -> Vertex<'D> -> DiGraph<'D, 'E> - override private FindEdgeData: Vertex<'D> -> Vertex<'D> -> 'E - override private TryFindEdgeData: Vertex<'D> -> Vertex<'D> -> 'E option - override private FoldVertex: ('a -> Vertex<'D> -> 'a) -> 'a -> 'a - override private IterVertex: (Vertex<'D> -> unit) -> unit - override private FoldEdge: - ('a -> Vertex<'D> -> Vertex<'D> -> 'E -> 'a) -> 'a -> 'a - override private IterEdge: (Vertex<'D> -> Vertex<'D> -> 'E -> unit) -> unit - override private Clone: unit -> DiGraph<'D, 'E> - override private SubGraph: Set> -> DiGraph<'D, 'E> - override private ToDOTStr: - string -> (Vertex<'D> -> string) -> (Edge<'E> -> string) -> string - - /// Check if the graph is empty. - [] - static member isEmpty: DiGraph<'D, 'E> -> bool - - /// Get the number of vertices of the graph. - [] - static member getSize: DiGraph<'D, 'E> -> int - - /// Add a dummy vertex to the graph. Dummy nodes are necessary when we run - /// some graph algorithms, and such nodes should be removed appropriately - /// before we return the final results. - [] - static member addDummyVertex: - DiGraph<'D, 'E> -> Vertex<'D> * DiGraph<'D, 'E> - - /// Add a vertex to the graph. - [] - static member addVertex: - DiGraph<'D, 'E> -> 'D -> Vertex<'D> * DiGraph<'D, 'E> - - /// Remove a vertex from the graph. - [] - static member removeVertex: - DiGraph<'D, 'E> -> Vertex<'D> -> DiGraph<'D, 'E> - - /// Get the predecessors of the given vertex in the graph. - [] - static member getPreds: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> list - - /// Get the successors of the given vertex in the graph. - [] - static member getSuccs: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> list - - /// Get unreachable nodes from the graph. - [] - static member getUnreachables: DiGraph<'D, 'E> -> Vertex<'D> list - - /// Get leaf (exit) nodes from the graph. - [] - static member getExits: DiGraph<'D, 'E> -> Vertex<'D> list - - /// Get the whole set of vertices from the graph. - [] - static member getVertices: DiGraph<'D, 'E> -> Set> - - /// Check if the given vertex exists in the graph. - [] - static member existsVertex: DiGraph<'D, 'E> -> VertexID -> bool - - /// Find vertex by VertexID. This function raises an exception when the given - /// ID does not exist in the graph. - [] - static member findVertexByID: - DiGraph<'D, 'E> -> VertexID -> Vertex<'D> - - /// Try to find vertex by VertexID. - [] - static member tryFindVertexByID: - DiGraph<'D, 'E> -> VertexID -> Vertex<'D> option - - /// Find vertex by given data. This function raises an exception when there is - /// no matching vertex in the graph. - [] - static member findVertexByData: - DiGraph<'D, 'E> -> 'D -> Vertex<'D> - - /// Try to find vertex by given data. - [] - static member tryFindVertexByData: - DiGraph<'D, 'E> -> 'D -> Vertex<'D> option - - /// Find vertex by the given predicate. This function raises an exception when - /// there is no matching vertex. - [] - static member findVertexBy: - DiGraph<'D, 'E> -> (Vertex<'D> -> bool) -> Vertex<'D> - - /// Try to find vertex by given data. - [] - static member tryFindVertexBy: - DiGraph<'D, 'E> -> (Vertex<'D> -> bool) -> Vertex<'D> option - - /// Add an edge to the graph without attaching data to it. - [] - static member addDummyEdge: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> -> DiGraph<'D, 'E> - - /// Add an edge to the graph. - [] - static member addEdge: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> -> 'E -> DiGraph<'D, 'E> - - /// Remove an edge from the graph. - [] - static member removeEdge: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> -> DiGraph<'D, 'E> - - /// Find an edge and return the data attached to it. This function raises an - /// exception when there is no matching edge. - [] - static member findEdgeData: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> -> 'E - - /// Try to find an edge and return the data attached to it. - [] - static member tryFindEdgeData: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> -> 'E option - - /// Fold vertices in the graph. - [] - static member foldVertex: - DiGraph<'D, 'E> -> ('a -> Vertex<'D> -> 'a) -> 'a -> 'a - - /// Iterate vertices in the graph. - [] - static member iterVertex: - DiGraph<'D, 'E> -> (Vertex<'D> -> unit) -> unit - - /// Fold edges in the graph. - [] - static member foldEdge: - DiGraph<'D, 'E> -> ('a -> Vertex<'D> -> Vertex<'D> -> 'E -> 'a) -> 'a -> 'a - - /// Iterate edges in the graph. - [] - static member iterEdge: - DiGraph<'D, 'E> -> (Vertex<'D> -> Vertex<'D> -> 'E -> unit) -> unit - - /// Clone a graph. For imperative graphs, this function involves deep copying. - [] - static member clone: - DiGraph<'D, 'E> -> DiGraph<'D, 'E> - - /// Create a reverse graph. - [] - static member reverse: - DiGraph<'D, 'E> -> DiGraph<'D, 'E> - - /// Return a subgraph of the given vertices. - [] - static member subGraph: - DiGraph<'D, 'E> -> Set> -> DiGraph<'D, 'E> - - /// Return a DOT-formatted string from the graph. - [] - static member toDOTStr: - DiGraph<'D, 'E> - -> string - -> (Vertex<'D> -> string) - -> (Edge<'E> -> string) - -> string - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/BinGraph/Dominator.fs b/src/BinGraph/Dominator.fs deleted file mode 100644 index 1bfec34f..00000000 --- a/src/BinGraph/Dominator.fs +++ /dev/null @@ -1,327 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.BinGraph.Dominator - -open B2R2.Utils -open System.Collections.Generic - -type DomInfo<'D when 'D :> VertexData> = { - /// Vertex ID -> DFNum - DFNumMap: Dictionary - /// DFNum -> Vertex - Vertex: Vertex<'D> [] - /// DFNum -> DFNum in the ancestor chain s.t. DFNum of its Semi is minimal. - Label: int [] - /// DFNum -> DFNum of the parent node (zero if not exists). - Parent: int [] - /// DFNum -> DFNum of the child node (zero if not exists). - Child: int [] - /// DFNum -> DFNum of an ancestor. - Ancestor: int [] - /// DFNum -> DFNum of a semidominator. - Semi: int [] - /// DFNum -> set of DFNums (vertices that share the same sdom). - Bucket: Set [] - /// DFNum -> Size - Size: int [] - /// DFNum -> DFNum of an immediate dominator. - IDom: int [] - /// Length of the arrays. - MaxLength: int -} - -/// Storing DomInfo of a graph. We use this to repeatedly compute doms/pdoms of -/// the same graph. -type DominatorContext<'D, 'E when 'D :> VertexData and 'D : equality> = { - ForwardGraph: DiGraph<'D, 'E> - ForwardRoot: Vertex<'D> - ForwardDomInfo: DomInfo<'D> - BackwardGraph: DiGraph<'D, 'E> - BackwardRoot: Vertex<'D> - BackwardDomInfo: DomInfo<'D> -} - -let initDomInfo g = - (* To reserve a room for entry (dummy) node. *) - let len = DiGraph.getSize g + 1 - { DFNumMap = Dictionary () - Vertex = Array.zeroCreate len - Label = Array.create len 0 - Parent = Array.create len 0 - Child = Array.create len 0 - Ancestor = Array.create len 0 - Semi = Array.create len 0 - Bucket = Array.create len Set.empty - Size = Array.create len 1 - IDom = Array.create len 0 - MaxLength = len } - -let inline dfnum (info: DomInfo<'D>) (v: Vertex<_>) = - info.DFNumMap.[v.GetID ()] - -let rec assignDFNum g (info: DomInfo<'D>) n = function - | (p, v : Vertex<_>) :: stack - when not <| info.DFNumMap.ContainsKey (v.GetID ()) -> - info.DFNumMap.Add (v.GetID (), n) - info.Semi.[n] <- n - info.Vertex.[n] <- v - info.Label.[n] <- n - info.Parent.[n] <- p - DiGraph.getSuccs g v - |> List.fold (fun acc s -> (n, s) :: acc) stack - |> assignDFNum g info (n+1) - | _ :: stack -> assignDFNum g info n stack - | [] -> n - 1 - -let rec compress info v = - let a = info.Ancestor.[v] - if info.Ancestor.[a] <> 0 then - compress info a - if info.Semi.[info.Label.[a]] < info.Semi.[info.Label.[v]] then - info.Label.[v] <- info.Label.[a] - else () - info.Ancestor.[v] <- info.Ancestor.[a] - -let eval info v = - if info.Ancestor.[v] = 0 then info.Label.[v] - else - compress info v - if info.Semi.[info.Label.[info.Ancestor.[v]]] >= info.Semi.[info.Label.[v]] - then info.Label.[v] - else info.Label.[info.Ancestor.[v]] - -/// Compute semidominator of v. -let rec computeSemiDom info v = function - | pred :: preds -> - let u = eval info pred - if info.Semi.[u] < info.Semi.[v] then info.Semi.[v] <- info.Semi.[u] - computeSemiDom info v preds - | [] -> () - -let link info v w = - let mutable s = w - while info.Semi.[info.Label.[w]] < info.Semi.[info.Label.[info.Child.[s]]] do - if info.Size.[s] + info.Size.[info.Child.[info.Child.[s]]] - >= 2 * info.Size.[info.Child.[s]] - then info.Ancestor.[info.Child.[s]] <- s - info.Child.[s] <- info.Child.[info.Child.[s]] - else info.Size.[info.Child.[s]] <- info.Size.[s] - info.Ancestor.[s] <- info.Child.[s] - s <- info.Ancestor.[s] - done - info.Label.[s] <- info.Label.[w] - info.Size.[v] <- info.Size.[v] + info.Size.[w] - if info.Size.[v] < 2 * info.Size.[w] then - let t = s - s <- info.Child.[v] - info.Child.[v] <- t - while s <> 0 do - info.Ancestor.[s] <- v - s <- info.Child.[s] - done - -let computeDom info p = - Set.iter (fun v -> - let u = eval info v - if info.Semi.[u] < info.Semi.[v] then info.IDom.[v] <- u - else info.IDom.[v] <- p) info.Bucket.[p] - info.Bucket.[p] <- Set.empty - -let rec computeDomOrDelay info parent = - if info.Bucket.[parent].IsEmpty then () - else computeDom info parent - -let initDominator g root = - let info = initDomInfo g - let dummyEntry, g = DummyEntry.Connect g root - let n = assignDFNum g info 0 [(0, dummyEntry)] - for i = n downto 1 do - let v = info.Vertex.[i] - let p = info.Parent.[i] - DiGraph.getPreds g v |> List.map (dfnum info) |> computeSemiDom info i - info.Bucket.[info.Semi.[i]] <- Set.add i info.Bucket.[info.Semi.[i]] - link info p i (* Link the parent (p) to the forest. *) - computeDomOrDelay info p - done - for i = 1 to n do - if info.IDom.[i] <> info.Semi.[i] then - info.IDom.[i] <- info.IDom.[info.IDom.[i]] - else () - done - DiGraph.removeVertex g dummyEntry |> ignore - info - -let updateReachMap g exits reachMap = - let rec loop reachMap = function - | [] -> reachMap - | (v: Vertex<_>) :: vs -> - let reachMap = Map.add (v.GetID ()) true reachMap - let vs = - DiGraph.getSuccs g v - |> List.fold (fun acc (w: Vertex<_>) -> - if Map.find (w.GetID ()) reachMap then acc else w :: acc) vs - loop reachMap vs - List.filter (fun (v: Vertex<_>) -> - not (Map.find (v.GetID ()) reachMap)) exits - |> loop reachMap - -let rec calculateExits (fg: DiGraph<_, _>) bg reachMap exits = - if Map.forall (fun _ b -> b) reachMap then exits - else - let reachMap = updateReachMap bg exits reachMap - let exits = - fg.FoldVertex (fun acc (v: Vertex<_>) -> - let isExit = DiGraph.getSuccs fg v |> List.length = 0 - if isExit && not <| Map.find (v.GetID ()) reachMap then - DiGraph.findVertexByID bg (v.GetID ()) :: acc - else acc) exits - calculateExits fg bg reachMap exits - -let preparePostDomAnalysis fg root (bg: DiGraph<_, _>) = - let _, orderMap = - Traversal.foldTopologically fg [root] (fun (cnt, map) v -> - cnt + 1, Map.add v cnt map) (0, Map.empty) - let fg, backEdges = - fg.FoldEdge (fun (fg, acc) (src: Vertex<_>) (dst: Vertex<_>) edge -> - if src.GetID () = dst.GetID () then - DiGraph.removeEdge fg src dst, (src, dst, edge) :: acc - else fg, acc) (fg, []) - let fg, backEdges = - fg.FoldEdge (fun (fg, acc) (src: Vertex<_>) (dst: Vertex<_>) edge -> - if Map.find src orderMap > Map.find dst orderMap then - DiGraph.removeEdge fg src dst, (src, dst, edge) :: acc - else fg, acc) (fg, backEdges) - let reachMap = - bg.FoldVertex (fun acc (v: Vertex<_>) -> - Map.add (v.GetID ()) false acc) Map.empty - let exits = - DiGraph.getUnreachables bg |> Seq.toList |> calculateExits fg bg reachMap - (* Restore backedges. This is needed for imperative graphs. *) - let _ = - backEdges - |> List.fold (fun fg (src, dst, e) -> DiGraph.addEdge fg src dst e) fg - let dummy, bg = DiGraph.addDummyVertex bg - let bg = exits |> List.fold (fun bg v -> DiGraph.addDummyEdge bg dummy v) bg - bg, dummy - -let initDominatorContext g root = - let forward = initDominator g root - let g', root' = DiGraph.reverse g |> preparePostDomAnalysis g root - let backward = initDominator g' root' - { ForwardGraph = g - ForwardRoot = root - ForwardDomInfo = forward - BackwardGraph = g' - BackwardRoot = root' - BackwardDomInfo = backward } - -let checkVertexInGraph g (v: Vertex<_>) = - let v' = DiGraph.findVertexByData g v.VData - if v === v' then () - else raise VertexNotFoundException - -let private idomAux info v = - let id = info.IDom.[dfnum info v] - if id >= 1 then Some info.Vertex.[id] else None - -let idom ctxt v = - let g = ctxt.ForwardGraph - checkVertexInGraph g v - idomAux ctxt.ForwardDomInfo v - -let ipdom ctxt (v: Vertex<_>) = - let g' = ctxt.BackwardGraph - let v = DiGraph.findVertexByData g' v.VData - idomAux ctxt.BackwardDomInfo v - -let rec domsAux acc v info = - let id = info.IDom.[dfnum info v] - if id > 0 then domsAux (info.Vertex.[id] :: acc) info.Vertex.[id] info - else List.rev acc - -let doms ctxt v = - let g = ctxt.ForwardGraph - checkVertexInGraph g v - domsAux [] v ctxt.ForwardDomInfo - -let pdoms ctxt v = - domsAux [] v ctxt.BackwardDomInfo - -let computeDomTree g info = - let domTree = Array.create info.MaxLength [] - DiGraph.iterVertex g (fun v -> - let idom = info.IDom.[dfnum info v] - domTree.[idom] <- v :: domTree.[idom]) - domTree - -let rec computeFrontierLocal s ctxt (parent: Vertex<_>) = function - | succ :: rest -> - let succID = dfnum ctxt succ - let d = ctxt.Vertex.[ctxt.IDom.[succID]] - let s = if d.GetID () = parent.GetID () then s else Set.add succID s - computeFrontierLocal s ctxt parent rest - | [] -> s - -let rec computeDF domTree (frontiers: Vertex<_> list []) g ctxt r = - let mutable s = Set.empty - for succ in DiGraph.getSuccs g r do - let succID = dfnum ctxt succ - let domID = ctxt.IDom.[succID] - let d = ctxt.Vertex.[ctxt.IDom.[succID]] - if domID <> 0 && d.GetID () <> r.GetID () then s <- Set.add succID s - done - for child in (domTree: Vertex<_> list []).[dfnum ctxt r] do - computeDF domTree frontiers g ctxt child - for node in frontiers.[dfnum ctxt child] do - let doms = domsAux [] node ctxt - let dominate = doms |> List.exists (fun d -> d.GetID () = r.GetID ()) - if not dominate then s <- Set.add (dfnum ctxt node) s - done - done - frontiers.[dfnum ctxt r] <- Set.fold (fun df n -> ctxt.Vertex.[n] :: df) [] s - -let frontier ctxt v = - let g = ctxt.ForwardGraph - checkVertexInGraph g v - let root = ctxt.ForwardRoot - let ctxt = ctxt.ForwardDomInfo - let frontiers = Array.create ctxt.MaxLength [] - let domTree = computeDomTree g ctxt - computeDF domTree frontiers g ctxt root - frontiers.[dfnum ctxt v] - -let dominatorTree ctxt = - let g = ctxt.ForwardGraph - let info = ctxt.ForwardDomInfo - let tree = computeDomTree g info - let tree = Array.sub tree 1 (Array.length tree - 1) // Remove a dummy node - let root = info.Vertex.[1] - let tree = - Array.mapi (fun dfNum vs -> dfNum, vs) tree - |> Array.fold (fun tree (dfNum, vs) -> - Map.add info.Vertex.[dfNum + 1] vs tree) Map.empty - tree, root - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/BinGraph/Dominator.fsi b/src/BinGraph/Dominator.fsi deleted file mode 100644 index c8ca11cc..00000000 --- a/src/BinGraph/Dominator.fsi +++ /dev/null @@ -1,81 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.BinGraph.Dominator - -open System.Collections.Generic - -type DomInfo<'D when 'D :> VertexData> = { - /// Vertex ID -> DFNum - DFNumMap: Dictionary - /// DFNum -> Vertex - Vertex: Vertex<'D> [] - /// DFNum -> DFNum in the ancestor chain s.t. DFNum of its Semi is minimal. - Label: int [] - /// DFNum -> DFNum of the parent node (zero if not exists). - Parent: int [] - /// DFNum -> DFNum of the child node (zero if not exists). - Child: int [] - /// DFNum -> DFNum of an ancestor. - Ancestor: int [] - /// DFNum -> DFNum of a semidominator. - Semi: int [] - /// DFNum -> set of DFNums (vertices that share the same sdom). - Bucket: Set [] - /// DFNum -> Size - Size: int [] - /// DFNum -> DFNum of an immediate dominator. - IDom: int [] - /// Length of the arrays. - MaxLength: int -} - -/// Storing DomInfo of a graph. We use this to repeatedly compute doms/pdoms of -/// the same graph. -type DominatorContext<'D, 'E when 'D :> VertexData and 'D : equality> = { - ForwardGraph: DiGraph<'D, 'E> - ForwardRoot: Vertex<'D> - ForwardDomInfo: DomInfo<'D> - BackwardGraph: DiGraph<'D, 'E> - BackwardRoot: Vertex<'D> - BackwardDomInfo: DomInfo<'D> -} - -val initDominatorContext: - DiGraph<'D, 'E> -> Vertex<'D> -> DominatorContext<'D, 'E> - -val idom: DominatorContext<'D, 'E> -> Vertex<'D> -> Vertex<'D> option - -val ipdom: DominatorContext<'D, 'E> -> Vertex<'D> -> Vertex<'D> option - -val doms: DominatorContext<'D, 'E> -> Vertex<'D> -> Vertex<'D> list - -val pdoms: DominatorContext<'D, 'E> -> Vertex<'D> -> Vertex<'D> list - -val frontier: DominatorContext<'D, 'E> -> Vertex<'D> -> Vertex<'D> list - -val dominatorTree: - DominatorContext<'D, 'E> -> Map, Vertex<'D> list> * Vertex<'D> - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/BinGraph/DummyVertex.fs b/src/BinGraph/DummyVertex.fs deleted file mode 100644 index 01c0bc71..00000000 --- a/src/BinGraph/DummyVertex.fs +++ /dev/null @@ -1,36 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinGraph - -type DummyEntry = - /// Temporarily connect entry dummy node with the given root node. We do not - /// touch the Graph, but simply connect two vertices temporarily for the - /// convenience of analysis. - static member Connect g (root: Vertex<_>) = - if root.IsDummy () then root, g - else - let dummyEntry, g = DiGraph.addDummyVertex g - let g = DiGraph.addDummyEdge g dummyEntry root - dummyEntry, g diff --git a/src/BinGraph/Graph.fs b/src/BinGraph/Graph.fs deleted file mode 100644 index 5b6016e5..00000000 --- a/src/BinGraph/Graph.fs +++ /dev/null @@ -1,114 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinGraph - -/// Either persistent or imperative graph. -type GraphImplementationType = - | PersistentGraph - | ImperativeGraph - -/// The top-level graph data type. This one can be both directed or undirected. -[] -type Graph<'D, 'E, 'G - when 'D :> VertexData - and 'G :> Graph<'D, 'E, 'G>> () = - - /// Graph implementation type. - abstract ImplementationType: GraphImplementationType - - /// Is this empty? A graph is empty when there is no vertex in the graph. - abstract IsEmpty: unit -> bool - - /// Number of vertices. - abstract GetSize: unit -> int - - /// Add a vertex into the graph, and return a reference to the added vertex. - abstract AddVertex: 'D -> Vertex<'D> * 'G - - /// Remove the given vertex from the graph. - abstract RemoveVertex: Vertex<'D> -> 'G - - /// Get a set of all vertices in the graph. - abstract GetVertices: unit -> Set> - - /// Check the existence of the given vertex from the graph. - abstract ExistsVertex: VertexID -> bool - - /// Find a vertex by its VertexID. This function raises an exception when - /// there is no such a vertex. - abstract FindVertexByID: VertexID -> Vertex<'D> - - /// Find a vertex by its VertexID. This function returns an Option type. - abstract TryFindVertexByID: VertexID -> Vertex<'D> option - - /// Find a vertex that has the given VertexData from the graph. It will raise - /// an exception if such a vertex does not exist. Note that this function can - /// be used only when each vertex always has unique VertexData. - abstract FindVertexByData: 'D -> Vertex<'D> - - /// Find a vertex that has the given VertexData from the graph. This function - /// does not raise an exception unlike FindVertexByData. - abstract TryFindVertexByData: 'D -> Vertex<'D> option - - /// Find a vertex by the given function. This function returns the first - /// element, in which the function returns true. When there is no such an - /// element, the function raises an exception. - abstract FindVertexBy: (Vertex<'D> -> bool) -> Vertex<'D> - - /// Find a vertex by the given function without raising an exception. - abstract TryFindVertexBy: (Vertex<'D> -> bool) -> Vertex<'D> option - - /// Add an edge from src to dst. - abstract AddEdge: src: Vertex<'D> -> dst: Vertex<'D> -> 'E -> 'G - - /// Remove the edge that spans from src to dst. - abstract RemoveEdge: src: Vertex<'D> -> dst: Vertex<'D> -> 'G - - /// Find the data of the edge that spans from src to dst. - abstract FindEdgeData: src: Vertex<'D> -> dst: Vertex<'D> -> 'E - - abstract TryFindEdgeData: src: Vertex<'D> -> dst: Vertex<'D> -> 'E option - - /// Fold every vertex (the order can be arbitrary). - abstract FoldVertex: ('a -> Vertex<'D> -> 'a) -> 'a -> 'a - - /// Iterate every vertex (the order can be arbitrary). - abstract IterVertex: (Vertex<'D> -> unit) -> unit - - /// Fold every edge in the graph (the order can be arbitrary). - abstract FoldEdge: ('a -> Vertex<'D> -> Vertex<'D> -> 'E -> 'a) -> 'a -> 'a - - /// Fold every edge in the graph (the order can be arbitrary). - abstract IterEdge: (Vertex<'D> -> Vertex<'D> -> 'E -> unit) -> unit - - /// Clone the graph and create a new one. - abstract Clone: unit -> 'G - - /// Return a subgraph that contains only the set of vertices. - abstract SubGraph: Set> -> 'G - - /// Return the DOT-representation of this graph. - abstract ToDOTStr: - string -> (Vertex<'D> -> string) -> (Edge<'E> -> string) -> string diff --git a/src/BinGraph/GraphCore.fs b/src/BinGraph/GraphCore.fs deleted file mode 100644 index 3cb6ee0d..00000000 --- a/src/BinGraph/GraphCore.fs +++ /dev/null @@ -1,81 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinGraph - -/// GraphCore is an internal representation for the core graph operations, and -/// this should not be directly accessed by the user. -[] -type GraphCore<'D, 'E, 'G - when 'D :> VertexData and 'G :> Graph<'D, 'E, 'G>> internal () = - - abstract ImplementationType: GraphImplementationType - - abstract InitGraph: GraphCore<'D, 'E, 'G> option -> 'G - - abstract Vertices: Set> - - abstract Unreachables: Vertex<'D> list - - abstract Exits: Vertex<'D> list - - abstract GetSize: unit -> int - - abstract AddDummyVertex: 'G -> Vertex<'D> * 'G - - abstract AddVertex: 'G -> 'D -> Vertex<'D> * 'G - - abstract GetVertex: VertexID -> Vertex<'D> - - abstract ContainsVertex: VertexID -> bool - - abstract RemoveVertex: 'G -> Vertex<'D> -> 'G - - abstract FoldVertex: ('a -> Vertex<'D> -> 'a) -> 'a -> 'a - - abstract IterVertex: (Vertex<'D> -> unit) -> unit - - abstract FindVertexBy: (Vertex<'D> -> bool) -> Vertex<'D> - - abstract TryFindVertexBy: (Vertex<'D> -> bool) -> Vertex<'D> option - - abstract GetPreds: Vertex<'D> -> Vertex<'D> list - - abstract GetSuccs: Vertex<'D> -> Vertex<'D> list - - abstract AddDummyEdge: 'G -> Vertex<'D> -> Vertex<'D> -> 'G - - abstract AddEdge: 'G -> Vertex<'D> -> Vertex<'D> -> 'E -> 'G - - abstract RemoveEdge: 'G -> Vertex<'D> -> Vertex<'D> -> 'G - - abstract FoldEdge: ('a -> Vertex<'D> -> Vertex<'D> -> 'E -> 'a) -> 'a -> 'a - - abstract IterEdge: (Vertex<'D> -> Vertex<'D> -> 'E -> unit) -> unit - - abstract FindEdge: Vertex<'D> -> Vertex<'D> -> 'E - - abstract TryFindEdge: Vertex<'D> -> Vertex<'D> -> 'E option - - abstract Clone: unit -> GraphCore<'D, 'E, 'G> diff --git a/src/BinGraph/Imperative.fs b/src/BinGraph/Imperative.fs deleted file mode 100644 index c132fd80..00000000 --- a/src/BinGraph/Imperative.fs +++ /dev/null @@ -1,352 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinGraph - -open B2R2 -open System.Collections.Generic - -/// Imperative vertex. -type ImpVertex<'D when 'D :> VertexData> (?v: 'D) = - inherit Vertex<'D> (v) - - let mutable preds = [] - let mutable succs = [] - - /// List of predecessors. - override __.Preds with get () = preds and set v = preds <- v - - /// List of successors. - override __.Succs with get () = succs and set v = succs <- v - - static member Init () : Vertex<'D> = upcast (ImpVertex<'D> ()) - - static member Init data : Vertex<'D> = upcast (ImpVertex<'D> (data)) - -/// Imperative GraphCore for directed graph (DiGraph). -type ImperativeCore<'D, 'E when 'D :> VertexData and 'D: equality> - (init, edgeData, ?vertices, ?edges, ?unreachables, ?exits) = - inherit GraphCore<'D, 'E, DiGraph<'D, 'E>> () - - let vertices = defaultArg vertices (HashSet ()) - let edges = defaultArg edges (Dictionary ()) - let unreachables = defaultArg unreachables (HashSet ()) - let exits = defaultArg exits (HashSet ()) - - member private __.CheckVertexExistence v = - if not <| vertices.Contains v then raise VertexNotFoundException - - override __.ImplementationType = ImperativeGraph - - override __.InitGraph core = - match core with - | Some core -> init <| core.Clone () - | None -> init <| ImperativeCore (init, edgeData) - - override __.Vertices with get () = - vertices |> Seq.fold (fun acc v -> Set.add v acc) Set.empty - - override __.Unreachables with get () = - unreachables |> Seq.fold (fun acc v -> v :: acc) [] - - override __.Exits with get () = - exits |> Seq.fold (fun acc v -> v :: acc) [] - - override __.GetSize () = vertices.Count - - member private __.AddVertexToCore v = - vertices.Add v |> ignore - unreachables.Add v |> ignore - exits.Add v |> ignore - - override __.AddDummyVertex g = - let v = ImpVertex.Init () - __.AddVertexToCore v - v, g - - override __.AddVertex g data = - let v = ImpVertex.Init data - __.AddVertexToCore v - v, g - - override __.GetVertex vid = - match Seq.tryFind (fun (v: Vertex<_>) -> v.GetID () = vid) vertices with - | Some v -> v - | None -> raise VertexNotFoundException - - override __.ContainsVertex vid = - vertices |> Seq.exists (fun (v: Vertex<_>) -> v.GetID () = vid) - - override __.RemoveVertex g v = - __.CheckVertexExistence v - v.Preds - |> List.iter (fun p -> __.RemoveEdge g p v |> ignore) - v.Succs - |> List.iter (fun s -> __.RemoveEdge g v s |> ignore) - vertices.Remove v |> ignore - unreachables.Remove v |> ignore - exits.Remove v |> ignore - g - - override __.FoldVertex fn acc = - vertices |> Seq.fold fn acc - - override __.IterVertex fn = - vertices |> Seq.iter fn - - override __.FindVertexBy fn = - vertices |> Seq.find fn - - override __.TryFindVertexBy fn = - vertices |> Seq.tryFind fn - - override __.GetPreds v = - __.CheckVertexExistence v - v.Preds - - override __.GetSuccs v = - __.CheckVertexExistence v - v.Succs - - member private __.AddEdgeToCore (src: Vertex<'D>) (dst: Vertex<'D>) e = - __.CheckVertexExistence src - __.CheckVertexExistence dst - let srcid = src.GetID () - let dstid = dst.GetID () - if edges.ContainsKey (srcid, dstid) then () - else - edges.[(srcid, dstid)] <- (src, dst, e) - src.Succs <- dst :: src.Succs - dst.Preds <- src :: dst.Preds - unreachables.Remove dst |> ignore - exits.Remove src |> ignore - - override __.AddDummyEdge g src dst = - __.AddEdgeToCore src dst edgeData - g - - override __.AddEdge g src dst e = - __.AddEdgeToCore src dst e - g - - override __.RemoveEdge g src dst = - __.CheckVertexExistence src - __.CheckVertexExistence dst - let srcid = src.GetID () - let dstid = dst.GetID () - src.Succs <- List.filter (fun s -> s.GetID () <> dstid) src.Succs - dst.Preds <- List.filter (fun p -> p.GetID () <> srcid) dst.Preds - if List.isEmpty dst.Preds then unreachables.Add dst |> ignore - if List.isEmpty src.Succs then exits.Add src |> ignore - edges.Remove ((srcid, dstid)) |> ignore - g - - override __.FoldEdge fn acc = - edges.Values - |> Seq.fold (fun acc (src, dst, e) -> fn acc src dst e) acc - - override __.IterEdge fn = - edges.Values - |> Seq.iter (fun (src, dst, e) -> fn src dst e) - - override __.FindEdge src dst = - if edges.ContainsKey (src.GetID (), dst.GetID ()) then - let _, _, e = edges.[(src.GetID (), dst.GetID ())] - e - else raise EdgeNotFoundException - - override __.TryFindEdge src dst = - if edges.ContainsKey (src.GetID (), dst.GetID ()) then - let _, _, e = edges.[(src.GetID (), dst.GetID ())] - Some e - else None - - override __.Clone () = - let g = __.InitGraph None - let core = ImperativeCore (init, edgeData) :> GraphCore<_, _, _> - __.IterVertex (fun v -> core.AddVertex g v.VData |> ignore) - __.IterEdge (fun src dst e -> - let src = core.GetVertex <| src.GetID () - let dst = core.GetVertex <| dst.GetID () - src.Succs <- dst :: src.Succs - dst.Preds <- src :: dst.Preds - core.AddEdge g src dst e |> ignore) - core - -/// Imperative GraphCore for directed graph (DiGraph) that uses AddrRange as key -/// for each vertex, which is useful for managing CFGs of a binary. -type ImperativeRangedCore<'D, 'E when 'D :> RangedVertexData and 'D: equality> - (init, edgeData, ?vertices, ?rangemap, ?edges, ?unreachables, ?exits) = - inherit GraphCore<'D, 'E, DiGraph<'D, 'E>> () - - let vertices = defaultArg vertices (HashSet ()) - let mutable rangemap = defaultArg rangemap IntervalMap.empty - let edges = defaultArg edges (Dictionary ()) - let unreachables = defaultArg unreachables (HashSet ()) - let exits = defaultArg exits (HashSet ()) - - member private __.CheckVertexExistence v = - if not <| vertices.Contains v then raise VertexNotFoundException - - override __.ImplementationType = ImperativeGraph - - override __.InitGraph core = - match core with - | Some core -> init <| core.Clone () - | None -> init <| ImperativeRangedCore (init, edgeData) - - override __.Vertices with get () = - vertices |> Seq.fold (fun acc v -> Set.add v acc) Set.empty - - override __.Unreachables with get () = - unreachables |> Seq.fold (fun acc v -> v :: acc) [] - - override __.Exits with get () = - exits |> Seq.fold (fun acc v -> v :: acc) [] - - override __.GetSize () = vertices.Count - - member private __.AddVertexToCore v = - vertices.Add v |> ignore - unreachables.Add v |> ignore - exits.Add v |> ignore - - override __.AddDummyVertex g = - let v = ImpVertex.Init () - __.AddVertexToCore v - v, g - - override __.AddVertex g data = - let v = ImpVertex.Init data - __.AddVertexToCore v - rangemap <- IntervalMap.add v.VData.AddrRange v rangemap - v, g - - override __.GetVertex vid = - match Seq.tryFind (fun (v: Vertex<_>) -> v.GetID () = vid) vertices with - | Some v -> v - | None -> raise VertexNotFoundException - - override __.ContainsVertex vid = - vertices |> Seq.exists (fun (v: Vertex<_>) -> v.GetID () = vid) - - override __.RemoveVertex g v = - __.CheckVertexExistence v - v.Preds - |> List.iter (fun p -> __.RemoveEdge g p v |> ignore) - v.Succs - |> List.iter (fun s -> __.RemoveEdge g v s |> ignore) - vertices.Remove v |> ignore - if v.IsDummy () |> not then - rangemap <- IntervalMap.remove v.VData.AddrRange rangemap - unreachables.Remove v |> ignore - exits.Remove v |> ignore - g - - override __.FoldVertex fn acc = - vertices |> Seq.fold fn acc - - override __.IterVertex fn = - vertices |> Seq.iter fn - - override __.FindVertexBy fn = - vertices |> Seq.find fn - - override __.TryFindVertexBy fn = - vertices |> Seq.tryFind fn - - override __.GetPreds v = - __.CheckVertexExistence v - v.Preds - - override __.GetSuccs v = - __.CheckVertexExistence v - v.Succs - - member private __.AddEdgeToCore (src: Vertex<'D>) (dst: Vertex<'D>) e = - __.CheckVertexExistence src - __.CheckVertexExistence dst - if not <| vertices.Contains src then failwith "No" - if not <| vertices.Contains dst then failwith "No" - let srcid = src.GetID () - let dstid = dst.GetID () - if edges.ContainsKey (srcid, dstid) then () - else - edges.[(src.GetID (), dst.GetID ())] <- (src, dst, e) - src.Succs <- dst :: src.Succs - dst.Preds <- src :: dst.Preds - unreachables.Remove dst |> ignore - exits.Remove src |> ignore - - override __.AddDummyEdge g src dst = - __.AddEdgeToCore src dst edgeData - g - - override __.AddEdge g src dst e = - __.AddEdgeToCore src dst e - g - - override __.RemoveEdge g src dst = - __.CheckVertexExistence src - __.CheckVertexExistence dst - let srcid = src.GetID () - let dstid = dst.GetID () - src.Succs <- List.filter (fun s -> s.GetID () <> dstid) src.Succs - dst.Preds <- List.filter (fun p -> p.GetID () <> srcid) dst.Preds - if List.isEmpty dst.Preds then unreachables.Add dst |> ignore - if List.isEmpty src.Succs then exits.Add src |> ignore - edges.Remove ((srcid, dstid)) |> ignore - g - - override __.FoldEdge fn acc = - edges.Values - |> Seq.fold (fun acc (src, dst, e) -> fn acc src dst e) acc - - override __.IterEdge fn = - edges.Values - |> Seq.iter (fun (src, dst, e) -> fn src dst e) - - override __.FindEdge src dst = - if edges.ContainsKey (src.GetID (), dst.GetID ()) then - let _, _, e = edges.[(src.GetID (), dst.GetID ())] - e - else raise EdgeNotFoundException - - override __.TryFindEdge src dst = - if edges.ContainsKey (src.GetID (), dst.GetID ()) then - let _, _, e = edges.[(src.GetID (), dst.GetID ())] - Some e - else None - - override __.Clone () = - let g = __.InitGraph None - let core = ImperativeRangedCore (init, edgeData) :> GraphCore<_, _, _> - __.IterVertex (fun v -> core.AddVertex g v.VData |> ignore) - __.IterEdge (fun src dst e -> - let src = core.GetVertex <| src.GetID () - let dst = core.GetVertex <| dst.GetID () - src.Succs <- dst :: src.Succs - dst.Preds <- src :: dst.Preds - core.AddEdge g src dst e |> ignore) - core diff --git a/src/BinGraph/Persistent.fs b/src/BinGraph/Persistent.fs deleted file mode 100644 index 0a283409..00000000 --- a/src/BinGraph/Persistent.fs +++ /dev/null @@ -1,361 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinGraph - -open B2R2 - -/// Persistent vertex. -type PerVertex<'D when 'D :> VertexData> (?v: 'D) = - inherit Vertex<'D> (v) - - override __.Preds - with get () = Utils.impossible () and set _ = Utils.impossible () - - override __.Succs - with get () = Utils.impossible () and set _ = Utils.impossible () - - static member Init () : Vertex<'D> = upcast (PerVertex<'D> ()) - - static member Init data : Vertex<'D> = upcast (PerVertex<'D> (data)) - -/// Persistent GraphCore for directed graph (DiGraph). -type PersistentCore<'D, 'E when 'D :> VertexData and 'D: equality> - (init, edgeData, ?vertices, ?preds, ?succs) = - inherit GraphCore<'D, 'E, DiGraph<'D, 'E>> () - - let vertices = defaultArg vertices Map.empty - let preds: Map * Vertex<'D> * 'E) list> = - defaultArg preds Map.empty - let succs: Map * Vertex<'D> * 'E) list> = - defaultArg succs Map.empty - - override __.ImplementationType = PersistentGraph - - override __.InitGraph core = - match core with - | Some core -> init core - | None -> init <| PersistentCore (init, edgeData) - - override __.Vertices with get () = - vertices |> Map.fold (fun acc _ v -> Set.add v acc) Set.empty - - override __.Unreachables with get () = - preds - |> Map.fold (fun acc vid ps -> - if List.isEmpty ps then (Map.find vid vertices) :: acc - else acc) [] - - override __.Exits with get () = - succs - |> Map.fold (fun acc vid ss -> - if List.isEmpty ss then (Map.find vid vertices) :: acc - else acc) [] - - override __.GetSize () = Map.count vertices - - member private __.InitGraphWithNewVertex (v: Vertex<'D>) = - let vid = v.GetID () - let vertices = Map.add vid v vertices - let preds = Map.add vid [] preds - let succs = Map.add vid [] succs - let core = PersistentCore (init, edgeData, vertices, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.AddDummyVertex _g = - let v = PerVertex.Init () - v, __.InitGraphWithNewVertex v - - override __.AddVertex _g data = - let v = PerVertex.Init data - v, __.InitGraphWithNewVertex v - - override __.GetVertex vid = - match Map.tryFind vid vertices with - | Some v -> v - | None -> raise VertexNotFoundException - - member inline private __.RemoveEdgeFromMap map srcId dstId = - let isChild (_, child: Vertex<_>, _) = child.GetID () <> dstId - map - |> Map.map (fun id ss -> - if srcId = id then List.filter isChild ss else ss) - - override __.RemoveVertex _g v = - let vid = v.GetID () - let succs = - Map.find vid preds - |> List.fold (fun succs (_, p, _) -> - __.RemoveEdgeFromMap succs (p.GetID ()) vid) succs - let preds = - Map.find vid succs - |> List.fold (fun preds (_, s, _) -> - __.RemoveEdgeFromMap preds (s.GetID ()) vid) preds - let vertices = Map.remove vid vertices - let preds = Map.remove vid preds - let succs = Map.remove vid succs - let core = PersistentCore (init, edgeData, vertices, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.ContainsVertex vid = - vertices |> Map.containsKey vid - - override __.FoldVertex fn acc = - vertices |> Map.fold (fun acc _ v -> fn acc v) acc - - override __.IterVertex fn = - vertices |> Map.iter (fun _ v -> fn v) - - override __.FindVertexBy fn = - vertices |> Map.pick (fun _ v -> if fn v then Some v else None) - - override __.TryFindVertexBy fn = - vertices |> Map.tryPick (fun _ v -> if fn v then Some v else None) - - member private __.Snd (_, e, _) = e - - member private __.Thrd (_, _, e) = e - - override __.GetPreds v = - Map.find (v.GetID ()) preds |> List.map __.Snd - - override __.GetSuccs v = - Map.find (v.GetID ()) succs |> List.map __.Snd - - member private __.InitGraphWithNewEdge (src: Vertex<'D>) (dst: Vertex<'D>) e = - let srcid = src.GetID () - let dstid = dst.GetID () - let existsEdge (src', dst', _) = src = src' && dst = dst' - match Map.tryFind srcid succs with - | Some ss when List.exists existsEdge ss -> __.InitGraph (Some (upcast __)) - | _ -> - let preds = Map.add dstid ((dst, src, e) :: Map.find dstid preds) preds - let succs = Map.add srcid ((src, dst, e) :: Map.find srcid succs) succs - let core = PersistentCore (init, edgeData, vertices, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.AddDummyEdge _g src dst = - __.InitGraphWithNewEdge src dst edgeData - - override __.AddEdge _g src dst e = - __.InitGraphWithNewEdge src dst e - - override __.RemoveEdge _g src dst = - let srcid = src.GetID () - let dstid = dst.GetID () - let preds = __.RemoveEdgeFromMap preds dstid srcid - let succs = __.RemoveEdgeFromMap succs srcid dstid - let core = PersistentCore (init, edgeData, vertices, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.FoldEdge fn acc = - let folder acc (s, d, e) = fn acc s d e - succs - |> Map.fold (fun acc _ lst -> - lst |> List.fold folder acc) acc - - override __.IterEdge fn = - let iterator (s, d, e) = fn s d e - succs - |> Map.iter (fun _ lst -> lst |> List.iter iterator) - - override __.FindEdge src dst = - let dstID = dst.GetID () - Map.find (src.GetID ()) succs - |> List.find (fun (_, v, _) -> v.GetID () = dstID) - |> __.Thrd - - override __.TryFindEdge src dst = - Map.tryFind (src.GetID ()) succs - |> Option.bind (fun lst -> - let dstID = dst.GetID () - lst |> List.tryFind (fun (_, v, _) -> v.GetID () = dstID)) - |> function - | Some (_, _, e) -> Some e - | None -> None - - override __.Clone () = - __ :> GraphCore<'D, 'E, DiGraph<'D, 'E>> - -/// Persistent GraphCore for directed graph (DiGraph) that uses AddrRange as a -/// key for each vertex. This is useful for handling CFGs of a binary. -type PersistentRangedCore<'D, 'E when 'D :> RangedVertexData and 'D: equality> - (init, edgeData, ?vertices, ?rangemap, ?edges, ?preds, ?succs) = - inherit GraphCore<'D, 'E, DiGraph<'D, 'E>> () - - let vertices = defaultArg vertices Map.empty - let rangemap = defaultArg rangemap IntervalMap.empty - let edges = defaultArg edges Map.empty - let preds: Map list> = defaultArg preds Map.empty - let succs: Map list> = defaultArg succs Map.empty - - override __.ImplementationType = PersistentGraph - - override __.InitGraph core = - match core with - | Some core -> init core - | None -> init <| PersistentRangedCore (init, edgeData) - - override __.Vertices with get () = - vertices |> Map.fold (fun acc _ v -> Set.add v acc) Set.empty - - override __.Unreachables with get () = - preds - |> Map.fold (fun acc vid ps -> - if List.isEmpty ps then (Map.find vid vertices) :: acc - else acc) [] - - override __.Exits with get () = - succs - |> Map.fold (fun acc vid ss -> - if List.isEmpty ss then (Map.find vid vertices) :: acc - else acc) [] - - override __.GetSize () = Map.count vertices - - member private __.InitGraphWithNewVertex (v: Vertex<'D>) = - let vid = v.GetID () - let vertices = Map.add vid v vertices - let rangemap = - if v.IsDummy () then rangemap - else IntervalMap.add v.VData.AddrRange v rangemap - let preds = Map.add vid [] preds - let succs = Map.add vid [] succs - let core = PersistentRangedCore (init, edgeData, - vertices, rangemap, edges, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.AddDummyVertex _g = - let v = PerVertex.Init () - v, __.InitGraphWithNewVertex v - - override __.AddVertex _g data = - let v = PerVertex.Init data - v, __.InitGraphWithNewVertex v - - override __.GetVertex vid = - match Map.tryFind vid vertices with - | Some v -> v - | None -> raise VertexNotFoundException - - member inline private __.RemoveEdgeFromMap map srcId dstId = - map - |> Map.map (fun id ss -> - if srcId = id then - List.filter (fun (child: Vertex<_>) -> child.GetID () <> dstId) ss - else ss) - - override __.RemoveVertex _g v = - let vid = v.GetID () - let edges, succs = - Map.find vid preds - |> List.fold (fun (edges, succs) p -> - let p = p.GetID () - Map.remove (p, vid) edges, - __.RemoveEdgeFromMap succs p vid) (edges, succs) - let edges, preds = - Map.find vid succs - |> List.fold (fun (edges, preds) s -> - let s = s.GetID () - Map.remove (vid, s) edges, - __.RemoveEdgeFromMap preds s vid) (edges, preds) - let vertices = Map.remove vid vertices - let rangemap = - if v.IsDummy () then rangemap - else IntervalMap.remove v.VData.AddrRange rangemap - let preds = Map.remove vid preds - let succs = Map.remove vid succs - let core = PersistentRangedCore (init, edgeData, - vertices, rangemap, edges, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.ContainsVertex vid = - vertices |> Map.containsKey vid - - override __.FoldVertex fn acc = - vertices |> Map.fold (fun acc _ v -> fn acc v) acc - - override __.IterVertex fn = - vertices |> Map.iter (fun _ v -> fn v) - - override __.FindVertexBy fn = - vertices |> Map.pick (fun _ v -> if fn v then Some v else None) - - override __.TryFindVertexBy fn = - vertices |> Map.tryPick (fun _ v -> if fn v then Some v else None) - - override __.GetPreds v = - Map.find (v.GetID ()) preds - - override __.GetSuccs v = - Map.find (v.GetID ()) succs - - member private __.InitGraphWithNewEdge (src: Vertex<'D>) (dst: Vertex<'D>) e = - let srcid = src.GetID () - let dstid = dst.GetID () - if Map.containsKey (srcid, dstid) edges then __.InitGraph (Some (upcast __)) - else - let edges = Map.add (srcid, dstid) (src, dst, e) edges - let preds = Map.add dstid (src :: Map.find dstid preds) preds - let succs = Map.add srcid (dst :: Map.find srcid succs) succs - let core = PersistentRangedCore (init, edgeData, - vertices, rangemap, edges, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.AddDummyEdge _g src dst = - __.InitGraphWithNewEdge src dst edgeData - - override __.AddEdge _g src dst e = - __.InitGraphWithNewEdge src dst e - - override __.RemoveEdge _g src dst = - let srcid = src.GetID () - let dstid = dst.GetID () - let preds = __.RemoveEdgeFromMap preds dstid srcid - let succs = __.RemoveEdgeFromMap succs srcid dstid - let edges = Map.remove (srcid, dstid) edges - let core = PersistentRangedCore (init, edgeData, - vertices, rangemap, edges, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.FoldEdge fn acc = - edges - |> Map.fold (fun acc _ (src, dst, e) -> fn acc src dst e) acc - - override __.IterEdge fn = - edges - |> Map.iter (fun _ (src, dst, e) -> fn src dst e) - - override __.FindEdge src dst = - match Map.tryFind (src.GetID (), dst.GetID ()) edges with - | Some (_, _, e) -> e - | None -> raise EdgeNotFoundException - - override __.TryFindEdge src dst = - match Map.tryFind (src.GetID (), dst.GetID ()) edges with - | Some (_, _, e) -> Some e - | None -> None - - override __.Clone () = - __ :> GraphCore<'D, 'E, DiGraph<'D, 'E>> diff --git a/src/BinGraph/RangedDiGraph.fs b/src/BinGraph/RangedDiGraph.fs deleted file mode 100644 index d91c2c99..00000000 --- a/src/BinGraph/RangedDiGraph.fs +++ /dev/null @@ -1,49 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinGraph - -type RangedDiGraph<'D, 'E - when 'D :> RangedVertexData and 'D : equality> (core) = - inherit DiGraph<'D, 'E> (core: GraphCore<'D, 'E, DiGraph<'D, 'E>>) - - member __.FindVertexByRange range = - core.FindVertexBy (fun (v: Vertex<'D>) -> v.VData.AddrRange = range) - -[] -module RangedDiGraph = - let private initializer core = RangedDiGraph<'D, 'E> (core) :> DiGraph<'D, 'E> - - let private initImperative edgeData = - let core = ImperativeRangedCore<'D, 'E> (initializer, edgeData) - RangedDiGraph<'D, 'E> (core) :> DiGraph<'D, 'E> - - let private initPersistent edgeData = - let core = PersistentRangedCore<'D, 'E> (initializer, edgeData) - RangedDiGraph<'D, 'E> (core) :> DiGraph<'D, 'E> - - /// Initialize RangedDiGraph based on the implementation type. - let init edgeData = function - | ImperativeGraph -> initImperative edgeData - | PersistentGraph -> initPersistent edgeData diff --git a/src/BinGraph/SCC.fs b/src/BinGraph/SCC.fs deleted file mode 100644 index 9007d147..00000000 --- a/src/BinGraph/SCC.fs +++ /dev/null @@ -1,130 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.BinGraph.SCC - -open System.Collections.Generic - -type SCC<'D when 'D :> VertexData> = Set> - -type SCCInfo<'D when 'D :> VertexData> = { - /// Vertex ID -> DFNum - DFNumMap: Dictionary - /// DFNum -> Vertex - Vertex: Vertex<'D> [] - /// DFNum -> LowLink - LowLink: int [] -} - -type CondensationBlock<'D when 'D :> VertexData> (scc: SCC<'D>) = - inherit VertexData(VertexData.genID ()) - - member __.SCC = scc - -type CondensationGraph<'D when 'D :> VertexData> = - DiGraph, unit> - -let initSCCInfo g = - let len = DiGraph.getSize g + 1 - { DFNumMap = Dictionary() - Vertex = Array.zeroCreate len - LowLink = Array.zeroCreate len } - -let inline dfnum ctxt (v: Vertex<_>) = - ctxt.DFNumMap.[v.GetID ()] - -let inline lowlink ctxt v = - ctxt.LowLink.[dfnum ctxt v] - -let rec assignSCC ctxt vNum stack scc = - if List.length stack <> 0 then - let wNum = List.head stack - if wNum >= vNum then - let stack = List.tail stack - let w = ctxt.Vertex.[wNum] - let scc = Set.add w scc - assignSCC ctxt vNum stack scc - else stack, scc - else stack, scc - -let createSCC ctxt v stack sccs = - let vNum = dfnum ctxt v - if lowlink ctxt v = vNum then - let stack, scc = assignSCC ctxt vNum stack Set.empty - stack, scc :: sccs - else stack, sccs - -let inline min x y = if x < y then x else y - -/// R.Tarjan. Depth-first search and linear graph algorithms -let rec computeSCC g ctxt (v: Vertex<_>) n stack sccs = - ctxt.DFNumMap.[v.GetID ()] <- n - ctxt.LowLink.[n] <- n - ctxt.Vertex.[n] <- v - let n, stack, sccs = - DiGraph.getSuccs g v - |> List.fold (computeLowLink g ctxt v) (n + 1, n :: stack, sccs) - let stack, sccs = createSCC ctxt v stack sccs - n, stack, sccs - -and computeLowLink g ctxt v (n, stack, sccs) (w: Vertex<_>) = - let vNum = dfnum ctxt v - let vLink = lowlink ctxt v - if ctxt.DFNumMap.ContainsKey <| w.GetID () then - let wNum = dfnum ctxt w - if List.contains wNum stack then ctxt.LowLink.[vNum] <- min vLink wNum - n, stack, sccs - else - let n, stack, sccs = computeSCC g ctxt w n stack sccs - let wLink = lowlink ctxt w - ctxt.LowLink.[vNum] <- min vLink wLink - n, stack, sccs - -let compute g root = - let ctxt = initSCCInfo g - DiGraph.getUnreachables g - |> Seq.fold (fun acc v -> Set.add v acc) Set.empty - |> Set.add root - |> Set.fold (fun (n, acc) root -> - let n, _, sccs = computeSCC g ctxt root n [] [] - let acc = sccs |> List.fold (fun acc scc -> Set.add scc acc) acc - n, acc) (1, Set.empty) - |> snd - -let condensation graphInit g root = - let sccs = compute g root - let cGraph = graphInit () - let vMap, cGraph = - sccs - |> Set.fold (fun (acc, cGraph) scc -> - let v, cGraph = DiGraph.addVertex cGraph <| CondensationBlock (scc) - let acc = Set.fold (fun acc w -> Map.add w v acc) acc scc - acc, cGraph) (Map.empty, cGraph) - Set.empty - |> DiGraph.foldEdge g (fun acc src dst _ -> - let src = Map.find src vMap - let dst = Map.find dst vMap - Set.add (src, dst) acc) - |> Set.fold (fun condensation (src, dst) -> - DiGraph.addEdge condensation src dst ()) cGraph diff --git a/src/BinGraph/Traversal.fs b/src/BinGraph/Traversal.fs deleted file mode 100644 index ab688689..00000000 --- a/src/BinGraph/Traversal.fs +++ /dev/null @@ -1,105 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.BinGraph.Traversal - -open System.Collections.Generic - -let inline private prependSuccessors g lst v = - DiGraph.getSuccs g v |> List.fold (fun lst s -> s :: lst) lst - -let rec foldPreorderLoop visited g fn acc = function - | [] -> acc - | v: Vertex<_> :: tovisit when v.GetID () |> (visited: HashSet<_>).Contains -> - foldPreorderLoop visited g fn acc tovisit - | v :: tovisit -> - v.GetID () |> visited.Add |> ignore - foldPreorderLoop visited g fn (fn acc v) (prependSuccessors g tovisit v) - -/// Fold vertices of the graph in a depth-first manner with the preorder -/// traversal. -let foldPreorder g v fn acc = - let visited = new HashSet () - foldPreorderLoop visited g fn acc [v] - -/// Iterate vertices of the graph in a depth-first manner with the preorder -/// traversal. -let iterPreorder g v fn = - foldPreorder g v (fun () v -> fn v) () - -let rec foldPostorderLoop visited g fn acc vstack = function - | [] -> acc - | v: Vertex<_> :: tovisit when v.GetID () |> (visited: HashSet<_>).Contains -> - foldPostorderLoop visited g fn acc vstack tovisit - | v :: tovisit -> - v.GetID () |> visited.Add |> ignore - let struct (acc, vstack) = consume visited g fn acc (v :: vstack) - foldPostorderLoop visited g fn acc vstack (prependSuccessors g tovisit v) -and consume visited g fn acc = function - | [] -> struct (acc, []) - | v :: rest -> - let allSuccsVisited = - DiGraph.getSuccs g v - |> List.forall (fun s -> s.GetID () |> visited.Contains) - if allSuccsVisited then consume visited g fn (fn acc v) rest - else struct (acc, v :: rest) - -/// Fold vertices of the graph in a depth-first manner with the postorder -/// traversal. -let foldPostorder g v fn acc = - let visited = new HashSet () - foldPostorderLoop visited g fn acc [] [v] - -/// Iterate vertices of the graph in a depth-first manner with the postorder -/// traversal. -let iterPostorder g v fn = - foldPostorder g v (fun () v -> fn v) () - -/// Fold vertices of the graph in a depth-first manner with the reverse -/// postorder traversal. -let foldRevPostorder g v fn acc = - foldPostorder g v (fun acc v -> v :: acc) [] - |> List.fold fn acc - -/// Iterate vertices of the graph in a depth-first manner with the reverse -/// postorder traversal. -let iterRevPostorder g v fn = - foldPostorder g v (fun acc v -> v :: acc) [] - |> List.iter fn - -/// Topologically fold every vertex of the given graph. For every unreachable -/// nodes, we accumulate vertices reachable from the node in a postorder -/// fashion. The accumulated list becomes the reverse postordered vertices, -/// which is essentially the same as a topologically sorted list of vertices. -/// We then simply fold the accumulated list. The second parameter (root) is for -/// providing root vertices in case there is no unreachable node, e.g., when -/// there is a loop to the root node. -let foldTopologically g roots fn acc = - let visited = new HashSet () - DiGraph.getUnreachables g - |> Set.ofSeq - |> List.foldBack Set.add roots - |> Set.toList - |> foldPostorderLoop visited g (fun acc v -> v :: acc) [] [] - |> List.fold fn acc diff --git a/src/BinGraph/Vertices.fs b/src/BinGraph/Vertices.fs deleted file mode 100644 index f8cf42f8..00000000 --- a/src/BinGraph/Vertices.fs +++ /dev/null @@ -1,109 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinGraph - -open B2R2 - -/// Missing vertex. -exception VertexNotFoundException - -/// Multiple vertices found when looking for a vertex containing certain data -exception MultipleVerticesFoundException - -/// Trying to access dummy node's data -exception DummyDataAccessException - -/// A unique ID for a vertex. -type VertexID = int - -/// A data type for vertex. A VertexData should have an ID. -[] -type VertexData (id) = - member __.ID: VertexID = id - -module VertexData = - let private freshID = ref 0 - - let genID () = System.Threading.Interlocked.Increment (freshID) - -type RangedVertexData (range: AddrRange) = - inherit VertexData(VertexData.genID ()) - member __.AddrRange = range - -/// A vertex of a graph. The vertex data (v) is optional, and if it is None, we -/// will consider the vertex as a dummy node. Dummy nodes are useful for -/// representing entry/exit node in a CFG. -[] -type Vertex<'V when 'V :> VertexData> (v: 'V option) = - /// Create a dummy vertex. - new () = Vertex (None) - /// Create a regular vertex. - new (v: 'V) = Vertex (Some v) - - abstract Preds : Vertex<'V> list with get, set - abstract Succs : Vertex<'V> list with get, set - - /// Data attached to the vertex. - member __.VData = - match v with - | Some v -> v - | None -> raise DummyDataAccessException - - /// Check whether vertex is a dummy node. - member __.IsDummy () = Option.isNone v - - /// Each vertex has a unique ID attached to it. We sometimes need to access ID - /// of dummy vertex for example calculating dominators. - member __.GetID () = - match v with - | Some v -> v.ID - | None -> 0 - - /// Return the ID of the given vertex. - static member GetID (v: Vertex<#VertexData>) = v.GetID () - - // Each vertex has a unique ID, so ID can be used to check equality. - override __.Equals obj = - match obj with - | :? Vertex<'V> as obj -> __.GetID () = obj.GetID () - | _ -> false - - override __.GetHashCode () = __.GetID () - - override __.ToString () = - match v with - | Some v -> sprintf "Vertex<%s>" <| v.ToString () - | None -> "DummyVertex" - - // Each vertex has a unique ID, so ID can be used for comparison. - interface System.IComparable with - member __.CompareTo obj = - match obj with - | :? Vertex<'V> as v -> compare (__.GetID ()) (v.GetID ()) - | _ -> failwith "Invalid comparison" - -type V<'V when 'V :> VertexData> = Vertex<'V> - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/BinIR.Tests/B2R2.BinIR.Tests.fsproj b/src/BinIR.Tests/B2R2.BinIR.Tests.fsproj new file mode 100644 index 00000000..97cb1acf --- /dev/null +++ b/src/BinIR.Tests/B2R2.BinIR.Tests.fsproj @@ -0,0 +1,25 @@ + + + + net5.0 + false + false + + + + + + + + + + + + + + + + + + + diff --git a/src/BinIR.Tests/Program.fs b/src/BinIR.Tests/Program.fs new file mode 100644 index 00000000..0695f84c --- /dev/null +++ b/src/BinIR.Tests/Program.fs @@ -0,0 +1 @@ +module Program = let [] main _ = 0 diff --git a/src/BinIR.Tests/Tests.fs b/src/BinIR.Tests/Tests.fs new file mode 100644 index 00000000..38f7abf6 --- /dev/null +++ b/src/BinIR.Tests/Tests.fs @@ -0,0 +1,75 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +namespace B2R2.BinIR.Tests + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.BinIR.LowUIR + +[] +type BinIRTest () = + + [] + member __.``Inline Optimization Test``() = + let n1 = AST.num <| BitVector.ofInt32 1 32 + let n2 = AST.num <| BitVector.ofInt32 2 32 + let n3 = AST.num <| BitVector.ofInt32 3 32 + let e1 = AST.add (AST.mul n1 n2) n3 + let e2 = AST.sub (AST.mul n2 n3) n1 + Assert.AreEqual (e1, e2) + + [] + member __.``Expr Commutative Equivalence Test 1``() = + let n1 = AST.tmpvar 32 0 + let n2 = AST.tmpvar 32 1 + let e1 = AST.add n1 n2 + let e2 = AST.add n2 n1 +#if ! HASHCONS + Assert.AreNotEqual (e1, e2) +#else + Assert.AreEqual (e1, e2) + Assert.AreEqual (e1.GetHashCode (), e2.GetHashCode ()) +#endif + + [] + member __.``Expr Commutative Equivalence Test 2``() = + let n1 = AST.tmpvar 32 0 + let n2 = AST.tmpvar 32 1 + let n3 = AST.tmpvar 32 2 + let e1 = AST.mul n3 (AST.div n1 n2) + let e2 = AST.mul (AST.div n1 n2) n3 +#if ! HASHCONS + Assert.AreNotEqual (e1, e2) +#else + Assert.AreEqual (e1, e2) + Assert.AreEqual (e1.GetHashCode (), e2.GetHashCode ()) +#endif + + [] + member __.``Consing Exception Test``() = + let n1 = AST.tmpvar 32 0 + let n2 = AST.nil + AST.cons n1 n2 |> ignore + Assert.IsTrue true diff --git a/src/BinIR/B2R2.BinIR.fsproj b/src/BinIR/B2R2.BinIR.fsproj index a84fc570..11e52a99 100644 --- a/src/BinIR/B2R2.BinIR.fsproj +++ b/src/BinIR/B2R2.BinIR.fsproj @@ -1,9 +1,12 @@ - + - netstandard2.1 - false - false + net5.0 + LICENSE.md + b2r2-240x240.png + $(OtherFlags)--warnon:3390 + README.md + B2R2 intermediate representation library. @@ -13,20 +16,25 @@ + - + - + + + + + - + diff --git a/src/BinIR/BinOpType.fs b/src/BinIR/BinOpType.fs index 7f67176d..9d533a01 100644 --- a/src/BinIR/BinOpType.fs +++ b/src/BinIR/BinOpType.fs @@ -93,6 +93,31 @@ module BinOpType = | BinOpType.FSUB -> "-." | BinOpType.FMUL -> "*." | BinOpType.FDIV -> "/." - | BinOpType.FPOW -> "^" - | BinOpType.FLOG -> "log" + | BinOpType.FPOW -> "^^" + | BinOpType.FLOG -> "lg" + | _ -> raise IllegalASTTypeException + + let ofString = function + | "+" -> BinOpType.ADD + | "-" -> BinOpType.SUB + | "*" -> BinOpType.MUL + | "/" -> BinOpType.DIV + | "?/" -> BinOpType.SDIV + | "%" -> BinOpType.MOD + | "?%" -> BinOpType. SMOD + | "<<" -> BinOpType.SHL + | ">>" -> BinOpType. SHR + | "?>>" -> BinOpType. SAR + | "&" -> BinOpType. AND + | "|" -> BinOpType. OR + | "^" -> BinOpType. XOR + | "++" -> BinOpType.CONCAT + | "-|" -> BinOpType.APP + | "::" -> BinOpType.CONS + | "+." -> BinOpType.FADD + | "-." -> BinOpType.FSUB + | "*." -> BinOpType.FMUL + | "/." -> BinOpType.FDIV + | "^^" -> BinOpType.FPOW + | "lg" -> BinOpType.FLOG | _ -> raise IllegalASTTypeException diff --git a/src/BinIR/CastKind.fs b/src/BinIR/CastKind.fs index aaddb130..b34b57cf 100644 --- a/src/BinIR/CastKind.fs +++ b/src/BinIR/CastKind.fs @@ -41,7 +41,7 @@ type CastKind = /// Float to Integer truncated conversion | FtoITrunc = 6 /// Float to Float conversion with different precisions - | FloatExt = 7 + | FloatCast = 7 module CastKind = let toString = function @@ -52,5 +52,16 @@ module CastKind = | CastKind.FtoICeil -> "ceil" | CastKind.FtoIFloor -> "floor" | CastKind.FtoITrunc -> "trunc" - | CastKind.FloatExt -> "fext" + | CastKind.FloatCast -> "fext" + | _ -> raise IllegalASTTypeException + + let ofString = function + | "sext" -> CastKind.SignExt + | "zext" -> CastKind.ZeroExt + | "float" -> CastKind.IntToFloat + | "round" -> CastKind.FtoIRound + | "ceil" -> CastKind.FtoICeil + | "floor" -> CastKind.FtoIFloor + | "trunc" -> CastKind.FtoITrunc + | "fext" -> CastKind.FloatCast | _ -> raise IllegalASTTypeException diff --git a/src/BinIR/Expr.fs b/src/BinIR/Expr.fs new file mode 100644 index 00000000..c606627a --- /dev/null +++ b/src/BinIR/Expr.fs @@ -0,0 +1,312 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.BinIR.LowUIR + +open System.Text +#if HASHCONS +open LanguagePrimitives +#endif +open B2R2 +open B2R2.BinIR + +/// ExprInfo summarizes several abstract information about the Expr. This is +/// useful for writing an efficient post analyses. +type ExprInfo = { + /// Is this expression contains memory load(s). + HasLoad: bool + /// A set of registers (their regids) used in this expression. + VarsUsed: RegisterSet + /// A set of temp variables (their IDs) used in this expression. + TempVarsUsed: Set +} + +/// IR Expressions. +/// NOTE: You MUST create Expr/Stmt through the AST module. *NEVER* directly +/// construct Expr nor Stmt. +#if ! HASHCONS +#else +[] +#endif +type E = + /// A number. For example, (0x42:I32) is a 32-bit number 0x42 + | Num of BitVector + + /// A variable that represents a register of a CPU. Var (t, r, n) indicates + /// a variable of type (t) that has RegisterID r and name (n). + /// For example, (EAX:I32) represents the EAX register (of type I32). + /// Note that name (n) is additional information that doesn't be used + /// internally. + | Var of RegType * RegisterID * string * RegisterSet + + /// Nil to represent cons cells. This should only be used with BinOpType.CONS. + | Nil + + /// A variable that represents a Program Counter (PC) of a CPU. + | PCVar of RegType * string + + /// A temporary variable represents an internal (imaginary) register. Names + /// of temporary variables should always be affixed by an underscore (_) and + /// a number. This is to make sure that any temporary variable is unique in + /// a CFG. For example, a temporary variable T can be represented as + /// (T_2:I32), where 2 is a unique number assigned to the variable. + | TempVar of RegType * int + + /// Unary operation such as negation. + | UnOp of UnOpType * Expr * ExprInfo + + /// Symbolic constant for labels. + | Name of Symbol + + /// Name of uninterpreted function. + | FuncName of string + + /// Binary operation such as add, sub, etc. The second argument is a result + /// type after applying BinOp. + | BinOp of BinOpType * RegType * Expr * Expr * ExprInfo + + /// Relative operation such as eq, lt, etc. + | RelOp of RelOpType * Expr * Expr * ExprInfo + + /// Memory loading such as LE:[T_1:I32] + | Load of Endian * RegType * Expr * ExprInfo + + /// If-then-else expression. The first expression is a condition, and the + /// second and the third are true and false expression respectively. + | Ite of Expr * Expr * Expr * ExprInfo + + /// Type casting expression. The first argument is a casting type, and the + /// second argument is a result type. + | Cast of CastKind * RegType * Expr * ExprInfo + + /// Extraction expression. The first argument is target expression, and the + /// second argument is the number of bits for extraction, and the third is + /// the start position. + | Extract of Expr * RegType * StartPos * ExprInfo + + /// Undefined expression. This is rarely used, and it is a fatal error when we + /// encounter this expression while evaluating a program. Some CPU manuals + /// explicitly say that a register value is undefined after a certain + /// operation. We model such cases with this expression. + | Undefined of RegType * string +#if ! HASHCONS +#else +with + override __.Equals rhs = + match rhs with + | :? E as rhs -> + match __, rhs with + | Num (n1), Num (n2) -> n1 = n2 + | Var (t1, r1, _, _), Var (t2, r2, _, _) -> t1 = t2 && r1 = r2 + | Nil, Nil -> true + | PCVar (t1, _), PCVar (t2, _) -> t1 = t2 + | TempVar (t1, n1), TempVar (t2, n2) -> t1 = t2 && n1 = n2 + | UnOp (t1, e1, _), UnOp (t2, e2, _) -> t1 = t2 && PhysicalEquality e1 e2 + | Name (s1), Name (s2) -> s1 = s2 + | FuncName (n1), FuncName (n2) -> n1 = n2 + | BinOp (o1, t1, lhs1, rhs1, _), BinOp (o2, t2, lhs2, rhs2, _) -> + o1 = o2 && t1 = t2 && + PhysicalEquality lhs1 lhs2 && PhysicalEquality rhs1 rhs2 + | RelOp (o1, lhs1, rhs1, _), RelOp (o2, lhs2, rhs2, _) -> + o1 = o2 && PhysicalEquality lhs1 lhs2 && PhysicalEquality rhs1 rhs2 + | Load (n1, t1, e1, _), Load (n2, t2, e2, _) -> + n1 = n2 && t1 = t2 && PhysicalEquality e1 e2 + | Ite (c1, t1, f1, _), Ite (c2, t2, f2, _) -> + PhysicalEquality c1 c2 && + PhysicalEquality t1 t2 && PhysicalEquality f1 f2 + | Cast (k1, t1, e1, _), Cast (k2, t2, e2, _) -> + k1 = k2 && t1 = t2 && PhysicalEquality e1 e2 + | Extract (e1, t1, p1, _), Extract (e2, t2, p2, _) -> + PhysicalEquality e1 e2 && t1 = t2 && p1 = p2 + | Undefined (t1, s1), Undefined (t2, s2) -> t1 = t2 && s1 = s2 + | _ -> false + | _ -> false + + static member inline HashVar (rt: RegType) (rid: RegisterID) = + 19 * (19 * int rt + int rid) + 1 + + static member inline HashPCVar (rt: RegType) = + 19 * int rt + 2 + + static member inline HashTempVar (rt: RegType) n = + 19 * (19 * int rt + n) + 3 + + static member inline HashUnOp (op: UnOpType) e = + 19 * (19 * int op + e.HashKey) + 4 + + static member inline HashName ((s, n): Symbol) = + 19 * (19 * s.GetHashCode () + n) + 5 + + static member inline HashFuncName (s: string) = + (19 * s.GetHashCode ()) + 6 + + static member inline HashBinOp (op: BinOpType) (rt: RegType) e1 e2 = + 19 * (19 * (19 * (19 * int op + int rt) + e1.HashKey) + e2.HashKey) + 7 + + static member inline HashRelOp (op: RelOpType) e1 e2 = + 19 * (19 * (19 * int op + e1.HashKey) + e2.HashKey) + 8 + + static member inline HashLoad (endian: Endian) (rt: RegType) e = + 19 * (19 * (19 * int endian + int rt) + e.HashKey) + 9 + + static member inline HashIte cond t f = + 19 * (19 * (19 * cond.HashKey + t.HashKey) + f.HashKey) + 10 + + static member inline HashCast (kind: CastKind) (rt: RegType) e = + 19 * (19 * (19 * int kind + int rt) + e.HashKey) + 11 + + static member inline HashExtract e (rt: RegType) pos = + 19 * (19 * (19 * e.HashKey + int rt) + pos) + 12 + + static member inline HashUndef (rt: RegType) (s: string) = + 19 * (19 * int rt + s.GetHashCode ()) + 13 + + override __.GetHashCode () = + match __ with + | Num n -> n.GetHashCode () + | Var (rt, rid, _, _) -> E.HashVar rt rid + | Nil -> 0 + | PCVar (rt, _) -> E.HashPCVar rt + | TempVar (rt, n) -> E.HashTempVar rt n + | UnOp (op, e, _) -> E.HashUnOp op e + | Name (s) -> E.HashName s + | FuncName (s) -> E.HashFuncName s + | BinOp (op, rt, e1, e2, _) -> E.HashBinOp op rt e1 e2 + | RelOp (op, e1, e2, _) -> E.HashRelOp op e1 e2 + | Load (endian, rt, e, _) -> E.HashLoad endian rt e + | Ite (cond, t, f, _) -> E.HashIte cond t f + | Cast (k, rt, e, _) -> E.HashCast k rt e + | Extract (e, rt, pos, _) -> E.HashExtract e rt pos + | Undefined (rt, s) -> E.HashUndef rt s +#endif + +#if ! HASHCONS +/// When hash-consing is not used, we simply create a wrapper for an AST node. +and [] Expr = { + /// The actual AST node. + E: E +} +#else +/// Hash-consed Expr. +and [] Expr = { + /// The actual AST node. + E: E + /// Unique id. + Tag: uint32 + /// Hash cache. + HashKey: int +} +with + override __.Equals rhs = + match rhs with + | :? Expr as rhs -> __.Tag = rhs.Tag + | _ -> false + + override __.GetHashCode () = __.HashKey + + interface IComparable with + member __.CompareTo rhs = + match rhs with + | :? Expr as rhs -> __.Tag.CompareTo rhs.Tag + | _ -> 1 +#endif + +module Expr = + let rec appendToString expr (sb: StringBuilder) = + match expr.E with + | Num n -> sb.Append (BitVector.toString n) |> ignore + | Var (_typ, _, n, _) -> sb.Append (n) |> ignore + | Nil -> sb.Append ("nil") |> ignore + | PCVar (_typ, n) -> sb.Append (n) |> ignore + | TempVar (typ, n) -> + sb.Append ("T_") |> ignore + sb.Append (n) |> ignore + sb.Append (":") |> ignore + sb.Append (RegType.toString typ) |> ignore + | Name (n) -> sb.Append (Symbol.getName n) |> ignore + | FuncName (n) -> sb.Append (n) |> ignore + | UnOp (op, e, _) -> + sb.Append ("(") |> ignore + sb.Append (UnOpType.toString op) |> ignore + sb.Append (" ") |> ignore + appendToString e sb + sb.Append (")") |> ignore + | BinOp (BinOpType.FLOG, _typ, e1, e2, _) -> (* The only prefix operator *) + sb.Append ("(lg (") |> ignore + appendToString e1 sb + sb.Append (", ") |> ignore + appendToString e2 sb + sb.Append ("))") |> ignore + | BinOp (op, _typ, e1, e2, _) -> + sb.Append ("(") |> ignore + appendToString e1 sb + sb.Append (" ") |> ignore + sb.Append (BinOpType.toString op) |> ignore + sb.Append (" ") |> ignore + appendToString e2 sb + sb.Append (")") |> ignore + | RelOp (op, e1, e2, _) -> + sb.Append ("(") |> ignore + appendToString e1 sb + sb.Append (" ") |> ignore + sb.Append (RelOpType.toString op) |> ignore + sb.Append (" ") |> ignore + appendToString e2 sb + sb.Append (")") |> ignore + | Load (_endian, typ, e, _) -> + sb.Append ("[") |> ignore + appendToString e sb + sb.Append ("]:") |> ignore + sb.Append (RegType.toString typ) |> ignore + | Ite (cond, e1, e2, _) -> + sb.Append ("((") |> ignore + appendToString cond sb + sb.Append (") ? (") |> ignore + appendToString e1 sb + sb.Append (") : (") |> ignore + appendToString e2 sb + sb.Append ("))") |> ignore + | Cast (cast, typ, e, _) -> + sb.Append (CastKind.toString cast) |> ignore + sb.Append (":") |> ignore + sb.Append (RegType.toString typ) |> ignore + sb.Append ("(") |> ignore + appendToString e sb + sb.Append (")") |> ignore + | Extract (e, typ, p, _) -> + sb.Append ("(") |> ignore + appendToString e sb + sb.Append ("[") |> ignore + sb.Append ((int typ + p - 1).ToString () + ":" + p.ToString ())|> ignore + sb.Append ("]") |> ignore + sb.Append (")") |> ignore + | Undefined (_, reason) -> + sb.Append ("?? (") |> ignore + sb.Append (reason) |> ignore + sb.Append (")") |> ignore + + let toString expr = + let sb = new StringBuilder () + appendToString expr sb + sb.ToString () \ No newline at end of file diff --git a/src/BinIR/LowUIR.AST.fs b/src/BinIR/LowUIR.AST.fs index e76c3e87..994da953 100644 --- a/src/BinIR/LowUIR.AST.fs +++ b/src/BinIR/LowUIR.AST.fs @@ -22,551 +22,1064 @@ SOFTWARE. *) -namespace B2R2.BinIR.LowUIR +/// LowUIR AST construction must be done through this module. +module B2R2.BinIR.LowUIR.AST open B2R2 open B2R2.BinIR -module TypeCheck = - - let rec typeOf = function - | Num n -> BitVector.getType n - | Var (t, _, _, _) - | PCVar (t, _) - | TempVar (t, _) -> t - | UnOp (_, e, _, _) -> typeOf e - | BinOp (_, t, _, _, _, _) -> t - | RelOp (_) -> 1 - | Load (_, t, _, _, _) -> t - | Ite (_, e1, _e2, _, _) -> typeOf e1 - | Cast (_, t, _, _, _) -> t - | Extract (_, t, _, _, _) -> t - | Undefined (t, _) -> t - | FuncName (_) | Name (_) | Nil -> raise InvalidExprException - - let concatType e1 e2 = typeOf e1 + typeOf e2 - - let checkTypeIsBool e = - let t = typeOf e - if t <> 1 then - raise <| TypeCheckException (Pp.expToString e + "must be boolean.") - - let checkTypeIsEquivalent t1 t2 = - if t1 = t2 then () - else raise <| TypeCheckException "Inconsistent types." - - let getCommonType e1 e2 = - let t1 = typeOf e1 - let t2 = typeOf e2 - checkTypeIsEquivalent t1 t2 - t1 - - let castErr (newType: RegType) (oldType: RegType) = - let errMsg = - "Cannot cast from " + oldType.ToString () + " to " + newType.ToString () - raise <| TypeCheckException errMsg - - let isFloatValid = function - | 32 | 64 | 80 -> true - | _ -> false - - let isCastingValid kind newType e = - let oldType = typeOf e - match kind with - | CastKind.SignExt - | CastKind.ZeroExt -> - if oldType < newType then true - else if oldType = newType then false - else castErr newType oldType - | CastKind.IntToFloat -> - if isFloatValid newType then true else raise InvalidFloatTypeException - | CastKind.FloatExt -> - if isFloatValid oldType && isFloatValid newType then true - else raise InvalidFloatTypeException - | _ -> true - - let extractTypeCheck (t: RegType) pos (t2: RegType) = - if (RegType.toBitWidth t + pos) <= RegType.toBitWidth t2 && pos >= 0 then () - else raise <| TypeCheckException "Inconsistent types." - -module ConcreteEvaluator = - let takeHigh n t = - let vTyp = BitVector.getType n - let shiftAmount = (RegType.toBitWidth vTyp) - (RegType.toBitWidth t) - BitVector.cast (BitVector.shr n (BitVector.ofInt32 shiftAmount vTyp)) t - - let inline evalUnOp n = function - | UnOpType.NEG -> BitVector.neg n |> Num - | UnOpType.NOT -> BitVector.bnot n |> Num - | UnOpType.FSQRT -> BitVector.fsqrt n |> Num - | UnOpType.FCOS -> BitVector.fcos n |> Num - | UnOpType.FSIN -> BitVector.fsin n |> Num - | UnOpType.FTAN -> BitVector.ftan n |> Num - | UnOpType.FATAN -> BitVector.fatan n |> Num - | _ -> failwith "Invalid" - - let inline evalBinOp n1 n2 = function - | BinOpType.ADD -> BitVector.add n1 n2 |> Num - | BinOpType.SUB -> BitVector.sub n1 n2 |> Num - | BinOpType.MUL -> BitVector.mul n1 n2 |> Num - | BinOpType.DIV -> BitVector.div n1 n2 |> Num - | BinOpType.SDIV -> BitVector.sdiv n1 n2 |> Num - | BinOpType.MOD -> BitVector.modulo n1 n2 |> Num - | BinOpType.SMOD -> BitVector.smodulo n1 n2 |> Num - | BinOpType.SHL -> BitVector.shl n1 n2 |> Num - | BinOpType.SAR -> BitVector.sar n1 n2 |> Num - | BinOpType.SHR -> BitVector.shr n1 n2 |> Num - | BinOpType.AND -> BitVector.band n1 n2 |> Num - | BinOpType.OR -> BitVector.bor n1 n2 |> Num - | BinOpType.XOR -> BitVector.bxor n1 n2 |> Num - | BinOpType.CONCAT -> BitVector.concat n1 n2 |> Num - | BinOpType.FADD -> BitVector.fadd n1 n2 |> Num - | BinOpType.FSUB -> BitVector.fsub n1 n2 |> Num - | BinOpType.FMUL -> BitVector.fmul n1 n2 |> Num - | BinOpType.FDIV -> BitVector.fdiv n1 n2 |> Num - | BinOpType.FPOW -> BitVector.fpow n1 n2 |> Num - | BinOpType.FLOG -> BitVector.flog n1 n2 |> Num - | _ -> failwith "Invalid" - - let inline evalRelOp n1 n2 = function - | RelOpType.EQ -> BitVector.eq n1 n2 |> Num - | RelOpType.NEQ -> BitVector.neq n1 n2 |> Num - | RelOpType.GT -> BitVector.gt n1 n2 |> Num - | RelOpType.GE -> BitVector.ge n1 n2 |> Num - | RelOpType.SGT -> BitVector.sgt n1 n2 |> Num - | RelOpType.SGE -> BitVector.sge n1 n2 |> Num - | RelOpType.LT -> BitVector.lt n1 n2 |> Num - | RelOpType.LE -> BitVector.le n1 n2 |> Num - | RelOpType.SLT -> BitVector.slt n1 n2 |> Num - | RelOpType.SLE -> BitVector.sle n1 n2 |> Num - | RelOpType.FLT -> BitVector.flt n1 n2 |> Num - | RelOpType.FLE -> BitVector.fle n1 n2 |> Num - | RelOpType.FGT -> BitVector.fgt n1 n2 |> Num - | RelOpType.FGE -> BitVector.fge n1 n2 |> Num - | _ -> failwith "Invalid" - - let inline evalCast t n = function - | CastKind.SignExt -> BitVector.sext n t |> Num - | CastKind.ZeroExt -> BitVector.zext n t |> Num - | CastKind.FloatExt -> BitVector.fext n t |> Num - | CastKind.IntToFloat -> BitVector.itof n t |> Num - | CastKind.FtoICeil -> BitVector.ftoiceil n t |> Num - | CastKind.FtoIFloor -> BitVector.ftoifloor n t |> Num - | CastKind.FtoIRound -> BitVector.ftoiround n t |> Num - | CastKind.FtoITrunc -> BitVector.ftoitrunc n t |> Num - | _ -> failwith "Invalid" - - let inline evalExtract e t pos = BitVector.extract e t pos |> Num - -module AST = - open TypeCheck - open ConcreteEvaluator - - let private emptyInfo = - { HasLoad = false; VarInfo = RegisterSet.empty; TempVarInfo = Set.empty } - - let getExprInfo = function - | Num _ | PCVar _ | Nil | Name _ | FuncName _ | Undefined _ -> emptyInfo - | Var (_, _, _, x) -> - { HasLoad = false; VarInfo = x; TempVarInfo = Set.empty } - | TempVar (_, name) -> { HasLoad = false - VarInfo = RegisterSet.empty - TempVarInfo = Set.singleton name } - | UnOp (_, _, ei, _) | BinOp (_, _, _, _, ei, _) | RelOp (_, _, _, ei, _) - | Load (_, _, _, ei, _) | Ite (_, _, _, ei, _) | Cast (_, _, _, ei, _) - | Extract (_, _, _, ei, _) -> ei - - let mergeTwoInfo e1 e2 = - let ei1 = getExprInfo e1 - let ei2 = getExprInfo e2 - { HasLoad = ei1.HasLoad || ei2.HasLoad - VarInfo = RegisterSet.union ei1.VarInfo ei2.VarInfo - TempVarInfo = Set.union ei1.TempVarInfo ei2.TempVarInfo } - - let mergeThreeInfo e1 e2 e3 = - let ei1 = getExprInfo e1 - let ei2 = getExprInfo e2 - let ei3 = getExprInfo e3 - let vInfo = RegisterSet.union ei1.VarInfo ei2.VarInfo - |> RegisterSet.union ei3.VarInfo - let tvInfo = Set.union ei1.TempVarInfo ei2.TempVarInfo - |> Set.union ei3.TempVarInfo - { HasLoad = ei1.HasLoad || ei2.HasLoad || ei3.HasLoad - VarInfo = vInfo; TempVarInfo = tvInfo } - - let num (num: BitVector) = Num (num) - - let var (t: RegType) (id: RegisterID) (name: string) (rs: RegisterSet) = - Var (t, id, name, rs) - - let pcVar (t: RegType) (name: string) = PCVar (t, name) - - let private varCnt = ref -1 - - let tmpVar (t: RegType) = - let i = System.Threading.Interlocked.Increment (varCnt) - if i >= 0 then TempVar (t, i) - else failwith "temporary variable counter wrapped around" - - let private lblCnt = ref -1 - - let lblSymbol n : Symbol = - let i = System.Threading.Interlocked.Increment (lblCnt) - if i >= 0 then (n, i) - else failwith "label counter wrapped around" - - let inline unopBuilder (t: UnOpType) e proc = - match e with - | Num n -> evalUnOp n t - | _ -> UnOp (t, e, getExprInfo e, None) |> proc - - let unop (t: UnOpType) e = unopBuilder t e (fun x -> x) - - let binopErr () = failwith "BinOp typecheck failure" - - let inline (===) e1 e2 = LanguagePrimitives.PhysicalEquality e1 e2 - - let inline binopBuilder (op: BinOpType) e1 e2 proc = -#if DEBUG - let t = - match op with - | BinOpType.CONCAT -> concatType e1 e2 - | _ -> getCommonType e1 e2 -#else - let t = - match op with - | BinOpType.CONCAT -> concatType e1 e2 - | _ -> typeOf e1 -#endif - match op, e1, e2 with - | _, Num n1, Num n2 -> evalBinOp n1 n2 op - | BinOpType.XOR, _, _ when e1 === e2 -> BitVector.zero t |> Num - (* TODO: add more cases for optimization *) - | _ -> BinOp (op, t, e1, e2, mergeTwoInfo e1 e2, None) |> proc - - let binop op e1 e2 = binopBuilder op e1 e2 (fun x -> x) - - let cons a b = - match b with - | Nil -> - BinOp (BinOpType.CONS, typeOf a, a, b, getExprInfo a, None) +#if HASHCONS +open System +open System.Collections.Concurrent + +let private eTagCnt = ref 0u +let private sTagCnt = ref 0u + +(* As we use a dictionary with WeakReference values, only the "values" will be + collected in the end. This will produce some garbage entries (with a null + value). We could use MemoryCache to handle the problem, but the memory leak + is not severe enough to trade-off the performance. *) +let private exprs = ConcurrentDictionary> () +let private stmts = ConcurrentDictionary> () +let private newETag () = Threading.Interlocked.Increment eTagCnt +let private newSTag () = Threading.Interlocked.Increment sTagCnt + +let inline private tryGetExpr (k: E) = + match exprs.TryGetValue k with + | true, e -> + match e.TryGetTarget () with + | true, e -> Ok e + | false, _ -> Error true + | _ -> Error false + +let inline private tryGetStmt (k: S) = + match stmts.TryGetValue k with + | true, s -> + match s.TryGetTarget () with + | true, s -> Ok s + | false, _ -> Error true + | _ -> Error false +#endif + +/// Get the expression info from the given expression (Expr). +[] +let getExprInfo e = ASTHelper.getExprInfo e + +/// Construct a number (Num). +[] +let num bv = +#if ! HASHCONS + Num (bv) |> ASTHelper.buildExpr +#else + let k = Num bv + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = bv.GetHashCode () } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + +/// Construct a variable (Var). +[] +let var t id name rs = +#if ! HASHCONS + Var (t, id, name, rs) |> ASTHelper.buildExpr +#else + let k = Var (t, id, name, rs) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashVar t id } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + +/// Construct a pc variable (PCVar). +[] +let pcvar t name = +#if ! HASHCONS + PCVar (t, name) |> ASTHelper.buildExpr +#else + let k = PCVar (t, name) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashPCVar t } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + +/// Construct a temporary variable (TempVar) with the given ID. +[] +let tmpvar t id = +#if ! HASHCONS + TempVar (t, id) |> ASTHelper.buildExpr +#else + let k = TempVar (t, id) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashTempVar t id } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + +/// Construct a symbol (for a label) from a string and a IDCounter. +[] +let inline symbol name id = + Symbol (name, id) + +/// Construct an unary operator (UnOp). +[] +let unop op e = + match e.E with + | Num n -> ValueOptimizer.unop n op |> num +#if ! HASHCONS + | _ -> UnOp (op, e, getExprInfo e) |> ASTHelper.buildExpr +#else + | _ -> + let k = UnOp (op, e, getExprInfo e) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashUnOp op e } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + +/// Construct a symbolic name (Name). +[] +let name symb = +#if ! HASHCONS + Name symb |> ASTHelper.buildExpr +#else + let k = Name symb + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashName symb } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + +let inline private (===) e1 e2 = + LanguagePrimitives.PhysicalEquality e1.E e2.E + +let binopWithType op t e1 e2 = + match op, e1.E, e2.E with + | _, Num n1, Num n2 -> ValueOptimizer.binop n1 n2 op |> num + | BinOpType.XOR, _, _ when e1 === e2 -> BitVector.zero t |> num +#if ! HASHCONS + | _ -> + BinOp (op, t, e1, e2, ASTHelper.mergeTwoExprInfo e1 e2) + |> ASTHelper.buildExpr +#else + | _ -> + let k = BinOp (op, t, e1, e2, ASTHelper.mergeTwoExprInfo e1 e2) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashBinOp op t e1 e2 } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + +/// Construct a binary operator (BinOp). +[] +let binop op e1 e2 = + let t = + match op with + | BinOpType.CONCAT -> TypeCheck.concat e1 e2 | _ -> - let t = getCommonType a b - BinOp (BinOpType.CONS, t, a, b, mergeTwoInfo a b, None) +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType op t e1 e2 + +/// Consing two expr. +[] +let cons a b = + match b.E with + | Nil -> + let t = TypeCheck.typeOf a +#if ! HASHCONS + BinOp (BinOpType.CONS, t, a, b, ASTHelper.getExprInfo a) + |> ASTHelper.buildExpr +#else + let k = BinOp (BinOpType.CONS, t, a, b, ASTHelper.getExprInfo a) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag () + HashKey = E.HashBinOp BinOpType.CONS t a b } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + | _ -> binop BinOpType.CONS a b - let app name args retType = - let funName = FuncName (name) - List.reduceBack cons (args @ [ Nil ]) - |> fun cons -> - BinOp (BinOpType.APP, retType, funName, cons, getExprInfo cons, None) +/// Nil. +[] +let nil = +#if ! HASHCONS + Nil |> ASTHelper.buildExpr +#else + { E = Nil; Tag = newETag (); HashKey = 0 } +#endif + +/// Function name. +[] +let funcName name = +#if ! HASHCONS + FuncName (name) |> ASTHelper.buildExpr +#else + let k = FuncName (name) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashFuncName name } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + +/// Construct a function application. +[] +let app name args retType = + let funName = funcName name + List.reduceBack cons (args @ [ nil ]) +#if ! HASHCONS + |> fun cons -> + BinOp (BinOpType.APP, retType, funName, cons, getExprInfo cons) + |> ASTHelper.buildExpr +#else + |> fun cons -> + let k = BinOp (BinOpType.APP, retType, funName, cons, getExprInfo cons) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag () + HashKey = E.HashBinOp BinOpType.APP retType funName cons } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + +/// Construct a relative operator (RelOp). +[] +let relop op e1 e2 = +#if DEBUG + TypeCheck.binop e1 e2 |> ignore +#endif + match e1.E, e2.E with + | Num n1, Num n2 -> ValueOptimizer.relop n1 n2 op |> num +#if ! HASHCONS + | _ -> + RelOp (op, e1, e2, ASTHelper.mergeTwoExprInfo e1 e2)|> ASTHelper.buildExpr +#else + | _ -> + let k = RelOp (op, e1, e2, ASTHelper.mergeTwoExprInfo e1 e2) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashRelOp op e1 e2 } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif - let inline relopBuilder (op: RelOpType) e1 e2 proc = +/// Construct a load expression (Load). +[] +let load endian rt addr = #if DEBUG - getCommonType e1 e2 |> ignore + match addr.E with + | Name _ -> raise InvalidExprException + | _ -> +#endif +#if ! HASHCONS + Load (endian, rt, addr, { getExprInfo addr with HasLoad = true }) + |> ASTHelper.buildExpr +#else + let k = Load (endian, rt, addr, { getExprInfo addr with HasLoad = true }) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashLoad endian rt addr } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' #endif - match e1, e2 with - | Num n1, Num n2 -> evalRelOp n1 n2 op - | _ -> RelOp (op, e1, e2, mergeTwoInfo e1 e2, None) |> proc - let relop (op: RelOpType) e1 e2 = relopBuilder op e1 e2 (fun x -> x) +/// Construct a load expression in little-endian. +[] +let loadLE t expr = load Endian.Little t expr - let inline loadBuilder (e: Endian) (t: RegType) addr (proc: Expr -> Expr) = +/// Construct a load expression in big-endian. +[] +let loadBE t expr = load Endian.Big t expr + +/// Construct an ITE (if-then-else) expression (Ite). +[] +let ite cond e1 e2 = #if DEBUG - match addr with - | Name _ -> raise InvalidExprException - | expr -> - Load (e, t, expr, { getExprInfo expr with HasLoad = true }, None) |> proc + TypeCheck.bool cond + TypeCheck.checkEquivalence (TypeCheck.typeOf e1) (TypeCheck.typeOf e2) +#endif + match cond.E with + | Num (n) -> if BitVector.isOne n then e1 else e2 (* Assume valid cond *) + | _ -> +#if ! HASHCONS + Ite (cond, e1, e2, ASTHelper.mergeThreeExprInfo cond e1 e2) + |> ASTHelper.buildExpr #else - Load (e, t, addr, { getExprInfo addr with HasLoad = true }, None) |> proc + let k = Ite (cond, e1, e2, ASTHelper.mergeThreeExprInfo cond e1 e2) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashIte cond e1 e2 } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' #endif - let load (e: Endian) (t: RegType) addr = loadBuilder e t addr (fun x -> x) - let inline iteBuilder cond e1 e2 proc = +/// Construct a cast expression (Cast). +[] +let cast kind rt e = + match e.E with + | Num n -> ValueOptimizer.cast rt n kind |> num + | _ -> + if TypeCheck.canCast kind rt e then +#if ! HASHCONS + Cast (kind, rt, e, getExprInfo e) |> ASTHelper.buildExpr +#else + let k = Cast (kind, rt, e, getExprInfo e) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashCast kind rt e } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + else e (* Remove unnecessary casting . *) + +/// Construct a extract expression (Extract). +[] +let extract expr rt pos = + TypeCheck.extract rt pos (TypeCheck.typeOf expr) + match expr.E with + | Num n -> ValueOptimizer.extract n rt pos |> num + | Extract (e, _, p, ei) -> + let pos = p + pos +#if ! HASHCONS + Extract (e, rt, pos, ei) |> ASTHelper.buildExpr +#else + let k = Extract (e, rt, pos, ei) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashExtract e rt pos } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + | _ -> +#if ! HASHCONS + Extract (expr, rt, pos, getExprInfo expr) |> ASTHelper.buildExpr +#else + let k = Extract (expr, rt, pos, getExprInfo expr) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashExtract expr rt pos } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + +/// Undefined expression. +[] +let undef rt s = +#if ! HASHCONS + Undefined (rt, s) |> ASTHelper.buildExpr +#else + let k = Undefined (rt, s) + match tryGetExpr k with + | Ok e -> e + | Error isReclaimed -> + let e' = { E = k; Tag = newETag (); HashKey = E.HashUndef rt s } + if isReclaimed then exprs.[k].SetTarget e' + else exprs.[k] <- WeakReference e' + e' +#endif + +/// Construct a (Num 0) of size t. +[] +let num0 rt = num (BitVector.zero rt) + +/// Construct a (Num 1) of size t. +[] +let num1 rt = num (BitVector.one rt) + +/// Num expression for a one-bit number zero. +[] +let b0 = num (BitVector.zero 1) + +/// Num expression for a one-bit number one. +[] +let b1 = num (BitVector.one 1) + +/// Concatenation. +[] +let concat e1 e2 = + let t = TypeCheck.concat e1 e2 + binopWithType BinOpType.CONCAT t e1 e2 + +let rec private concatLoop (arr: Expr []) sPos ePos = + let diff = ePos - sPos + if diff > 0 then concat (concatLoop arr (sPos + diff / 2 + 1) ePos) + (concatLoop arr sPos (sPos + diff / 2)) + elif diff = 0 then arr.[sPos] + else Utils.impossible () + +/// Concatenate an array of expressions. +[] +let concatArr (arr: Expr[]) = + concatLoop arr 0 (Array.length arr - 1) + +/// Unwrap (casted) expression. +[] +let rec unwrap e = + match e.E with + | Cast (_, _, e, _) + | Extract (e, _, _, _) -> unwrap e + | _ -> e + +/// Zero-extend an expression. +[] +let zext addrSize expr = cast CastKind.ZeroExt addrSize expr + +/// Sign-extend an expression. +[] +let sext addrSize expr = cast CastKind.SignExt addrSize expr + +/// Take the low half bits of an expression. +[] +let xtlo addrSize expr = + extract expr addrSize 0 + +/// Take the high half bits of an expression. +[] +let xthi addrSize expr = + extract expr addrSize (int (TypeCheck.typeOf expr - addrSize)) + +/// Add two expressions. +[] +let add e1 e2 = + let t = #if DEBUG - checkTypeIsBool cond - checkTypeIsEquivalent (typeOf e1) (typeOf e2) -#endif - match cond with - | Num (n) -> if BitVector.isOne n then e1 else e2 (* Assume valid cond *) - | _ -> Ite (cond, e1, e2, mergeThreeInfo cond e1 e2, None) |> proc - - let ite cond e1 e2 = iteBuilder cond e1 e2 (fun x -> x) - - let inline castBuilder kind (t: RegType) (e: Expr) proc = - match e with - | Num n -> evalCast t n kind - | _ when isCastingValid kind t e -> - Cast (kind, t, e, getExprInfo e, None) |> proc - | _ -> e - - let cast kind (t: RegType) (e: Expr) = castBuilder kind t e (fun x -> x) - - let inline extractBuilder (expr: Expr) (t: RegType) (pos: StartPos) proc = - extractTypeCheck t pos (typeOf expr) - match expr with - | Num n -> evalExtract n t pos - | Extract (e, _, p, ei, _) -> Extract (e, t, p + pos, ei, None) |> proc - | _ -> Extract (expr, t, pos, getExprInfo expr, None) |> proc - - let extract (expr: Expr) (t: RegType) (pos: StartPos) = - extractBuilder expr t pos (fun x -> x) - - let unDef (t: RegType) (s: string) = - Undefined (t, s) - - let num0 t = num <| BitVector.zero t - let num1 t = num <| BitVector.one t - - let b0 = num0 1 - let b1 = num1 1 - - let concat e1 e2 = binop BinOpType.CONCAT e1 e2 - - /// Concatenate an array of expressions. - let concatExprs (arr: Expr []) = - let rec concatLoop sPos ePos = - let diff = ePos - sPos - if diff > 0 then concat (concatLoop (sPos + diff / 2 + 1) ePos) - (concatLoop sPos (sPos + diff / 2)) - elif diff = 0 then arr.[sPos] - else failwith "Invalid positions." - concatLoop 0 (Array.length arr - 1) - - let assignForExtractDst e1 e2 = - match e1 with - | Extract ((Var (t, _, _, _) as e1), eTyp, 0, _, _) - | Extract ((TempVar (t, _) as e1), eTyp, 0, _, _)-> - let nMask = RegType.getMask t - RegType.getMask eTyp - let mask = num <| BitVector.ofUBInt nMask t - let src = cast CastKind.ZeroExt t e2 - Put (e1, binop BinOpType.OR (binop BinOpType.AND e1 mask) src) - | Extract ((Var (t, _, _, _) as e1), eTyp, pos, _, _) - | Extract ((TempVar (t, _) as e1), eTyp, pos, _, _) -> - let nMask = RegType.getMask t - (RegType.getMask eTyp <<< pos) - let mask = num <| BitVector.ofUBInt nMask t - let src = cast CastKind.ZeroExt t e2 - let shift = (num <| BitVector.ofInt32 pos t) - let src = binop BinOpType.SHL src shift - Put (e1, binop BinOpType.OR (binop BinOpType.AND e1 mask) src) - | _ -> raise InvalidAssignmentException - - let (:=) e1 e2 = (* Assignment *) + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif +#if ! HASHCONS + binopWithType BinOpType.ADD t e1 e2 +#else + if e1 < e2 then binopWithType BinOpType.ADD t e1 e2 + else binopWithType BinOpType.ADD t e2 e1 +#endif + +/// Subtract two expressions. +[] +let sub e1 e2 = + let t = #if DEBUG - checkTypeIsEquivalent (typeOf e1) (typeOf e2) + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 #endif - match e1 with - | Load (_, _, e, _, _) -> Store (Endian.Little, e, e2) - | Var _ | PCVar _ | TempVar _ -> Put (e1, e2) - | Extract (_) as e1 -> assignForExtractDst e1 e2 - | _ -> raise InvalidAssignmentException + binopWithType BinOpType.SUB t e1 e2 - let (.+) e1 e2 = binop BinOpType.ADD e1 e2 +/// Multiply two expressions. +[] +let mul e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif +#if ! HASHCONS + binopWithType BinOpType.MUL t e1 e2 +#else + if e1 < e2 then binopWithType BinOpType.MUL t e1 e2 + else binopWithType BinOpType.MUL t e2 e1 +#endif - let (.-) e1 e2 = binop BinOpType.SUB e1 e2 +/// Unsigned division. +[] +let div e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType BinOpType.DIV t e1 e2 - let (.*) e1 e2 = binop BinOpType.MUL e1 e2 +/// Signed division. +[] +let sdiv e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType BinOpType.SDIV t e1 e2 - let (./) e1 e2 = binop BinOpType.DIV e1 e2 +/// Unsigned modulus. +[] +let ``mod`` e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType BinOpType.MOD t e1 e2 - let (?/) e1 e2 = binop BinOpType.SDIV e1 e2 +/// Signed modulus. +[] +let smod e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType BinOpType.SMOD t e1 e2 - let (.%) e1 e2 = binop BinOpType.MOD e1 e2 +/// Equal. +[] +let eq e1 e2 = +#if ! HASHCONS + relop RelOpType.EQ e1 e2 +#else + if e1 < e2 then relop RelOpType.EQ e1 e2 + else relop RelOpType.EQ e2 e1 +#endif - let (?%) e1 e2 = binop BinOpType.SMOD e1 e2 +/// Not equal. +[] +let neq e1 e2 = +#if ! HASHCONS + relop RelOpType.NEQ e2 e1 +#else + if e1 < e2 then relop RelOpType.NEQ e1 e2 + else relop RelOpType.NEQ e2 e1 +#endif - let (==) e1 e2 = relop RelOpType.EQ e1 e2 +/// Unsigned greater than. +[] +let gt e1 e2 = relop RelOpType.GT e1 e2 - let (!=) e1 e2 = relop RelOpType.NEQ e1 e2 +/// Unsigned greater than or equal. +[] +let ge e1 e2 = relop RelOpType.GE e1 e2 - let gt e1 e2 = relop RelOpType.GT e1 e2 +/// Signed greater than. +[] +let sgt e1 e2 = relop RelOpType.SGT e1 e2 - let ge e1 e2 = relop RelOpType.GE e1 e2 +/// Signed greater than or equal. +[] +let sge e1 e2 = relop RelOpType.SGE e1 e2 - let sgt e1 e2 = relop RelOpType.SGT e1 e2 +/// Unsigned less than. +[] +let lt e1 e2 = relop RelOpType.LT e1 e2 - let sge e1 e2 = relop RelOpType.SGE e1 e2 +/// Unsigned less than or equal. +[] +let le e1 e2 = relop RelOpType.LE e1 e2 - let lt e1 e2 = relop RelOpType.LT e1 e2 +/// Signed less than. +[] +let slt e1 e2 = relop RelOpType.SLT e1 e2 - let le e1 e2 = relop RelOpType.LE e1 e2 +/// Signed less than or equal. +[] +let sle e1 e2 = relop RelOpType.SLE e1 e2 - let slt e1 e2 = relop RelOpType.SLT e1 e2 +/// Bitwise AND. +[] +let ``and`` e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType BinOpType.AND t e1 e2 - let sle e1 e2 = relop RelOpType.SLE e1 e2 +/// Bitwise OR. +[] +let ``or`` e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif +#if ! HASHCONS + binopWithType BinOpType.OR t e2 e1 +#else + if e1 < e2 then binopWithType BinOpType.OR t e1 e2 + else binopWithType BinOpType.OR t e2 e1 +#endif - let (.&) e1 e2 = binop BinOpType.AND e1 e2 +/// Bitwise XOR. +[] +let xor e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif +#if ! HASHCONS + binopWithType BinOpType.XOR t e2 e1 +#else + if e1 < e2 then binopWithType BinOpType.XOR t e1 e2 + else binopWithType BinOpType.XOR t e2 e1 +#endif + +/// Shift arithmetic right. +[] +let sar e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType BinOpType.SAR t e1 e2 - let (.|) e1 e2 = binop BinOpType.OR e1 e2 +/// Shift logical right. +[] +let shr e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType BinOpType.SHR t e1 e2 - let (<+>) e1 e2 = binop BinOpType.XOR e1 e2 +/// Shift logical left. +[] +let shl e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType BinOpType.SHL t e1 e2 - let (?>>) e1 e2 = binop BinOpType.SAR e1 e2 +/// Negation (Two's complement). +[] +let neg e = unop UnOpType.NEG e - let (>>) e1 e2 = binop BinOpType.SHR e1 e2 +/// Logical not. +[] +let not e = unop UnOpType.NOT e - let (<<) e1 e2 = binop BinOpType.SHL e1 e2 +/// Floating point add two expressions. +[] +let fadd e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif +#if ! HASHCONS + binopWithType BinOpType.FADD t e2 e1 +#else + if e1 < e2 then binopWithType BinOpType.FADD t e1 e2 + else binopWithType BinOpType.FADD t e2 e1 +#endif - let neg e = unop UnOpType.NEG e +/// Floating point subtract two expressions. +[] +let fsub e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType BinOpType.FSUB t e1 e2 - let not e = unop UnOpType.NOT e +/// Floating point multiplication. +[] +let fmul e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif +#if ! HASHCONS + binopWithType BinOpType.FMUL t e2 e1 +#else + if e1 < e2 then binopWithType BinOpType.FMUL t e1 e2 + else binopWithType BinOpType.FMUL t e2 e1 +#endif - let fadd e1 e2 = binop BinOpType.FADD e1 e2 +/// Floating point division. +[] +let fdiv e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType BinOpType.FDIV t e1 e2 - let fsub e1 e2 = binop BinOpType.FSUB e1 e2 +/// Floating point greater than. +[] +let fgt e1 e2 = relop RelOpType.FGT e1 e2 - let fmul e1 e2 = binop BinOpType.FMUL e1 e2 +/// Floating point greater than or equal. +[] +let fge e1 e2 = relop RelOpType.FGE e1 e2 - let fdiv e1 e2 = binop BinOpType.FDIV e1 e2 +/// Floating point less than. +[] +let flt e1 e2 = relop RelOpType.FLT e1 e2 - let fpow e1 e2 = binop BinOpType.FPOW e1 e2 +/// Floating point less than or equal. +[] +let fle e1 e2 = relop RelOpType.FLE e1 e2 - let flog e1 e2 = binop BinOpType.FLOG e1 e2 +/// Floating point power. +[] +let fpow e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType BinOpType.FPOW t e1 e2 + +/// Floating point logarithm. +[] +let flog e1 e2 = + let t = +#if DEBUG + TypeCheck.binop e1 e2 +#else + TypeCheck.typeOf e1 +#endif + binopWithType BinOpType.FLOG t e1 e2 + +/// Floating point square root. +[] +let fsqrt e = unop UnOpType.FSQRT e + +/// Floating point sine. +[] +let fsin e = unop UnOpType.FSIN e + +/// Floating point cosine. +[] +let fcos e = unop UnOpType.FCOS e + +/// Floating point tangent. +[] +let ftan e = unop UnOpType.FTAN e + +/// Floating point arc tangent. +[] +let fatan e = unop UnOpType.FATAN e + +/// An ISMark statement. +[] +let ismark nBytes = +#if ! HASHCONS + ISMark nBytes |> ASTHelper.buildStmt +#else + let k = ISMark nBytes + match tryGetStmt k with + | Ok s -> s + | Error isReclaimed -> + let s' = { S = k; Tag = newSTag (); HashKey = S.HashISMark nBytes } + if isReclaimed then stmts.[k].SetTarget s' + else stmts.[k] <- WeakReference s' + s' +#endif + +/// An IEMark statement. +[] +let iemark nBytes = +#if ! HASHCONS + IEMark nBytes |> ASTHelper.buildStmt +#else + let k = IEMark nBytes + match tryGetStmt k with + | Ok s -> s + | Error isReclaimed -> + let s' = { S = k; Tag = newSTag (); HashKey = S.HashIEMark nBytes } + if isReclaimed then stmts.[k].SetTarget s' + else stmts.[k] <- WeakReference s' + s' +#endif + +/// An LMark statement. +[] +let lmark s = +#if ! HASHCONS + LMark s |> ASTHelper.buildStmt +#else + let k = LMark s + match tryGetStmt k with + | Ok s -> s + | Error isReclaimed -> + let s' = { S = k; Tag = newSTag (); HashKey = S.HashLMark s } + if isReclaimed then stmts.[k].SetTarget s' + else stmts.[k] <- WeakReference s' + s' +#endif + +/// A Put statement. +[] +let put dst src = +#if ! HASHCONS + Put (dst, src) |> ASTHelper.buildStmt +#else + let k = Put (dst, src) + match tryGetStmt k with + | Ok s -> s + | Error isReclaimed -> + let s' = { S = k; Tag = newSTag (); HashKey = S.HashPut dst src } + if isReclaimed then stmts.[k].SetTarget s' + else stmts.[k] <- WeakReference s' + s' +#endif + +let assignForExtractDst e1 e2 = + match e1.E with + | Extract ({ E = Var (t, _, _, _) } as e1, eTyp, 0, _) + | Extract ({ E = TempVar (t, _) } as e1, eTyp, 0, _)-> + let nMask = RegType.getMask t - RegType.getMask eTyp + let mask = BitVector.ofBInt nMask t |> num + let src = cast CastKind.ZeroExt t e2 + put e1 (binopWithType BinOpType.OR t + (binopWithType BinOpType.AND t e1 mask) src) + | Extract ({ E = Var (t, _, _, _) } as e1, eTyp, pos, _) + | Extract ({ E = TempVar (t, _) } as e1, eTyp, pos, _) -> + let nMask = RegType.getMask t - (RegType.getMask eTyp <<< pos) + let mask = BitVector.ofBInt nMask t |> num + let src = cast CastKind.ZeroExt t e2 + let shift = BitVector.ofInt32 pos t |> num + let src = binopWithType BinOpType.SHL t src shift + put e1 (binopWithType BinOpType.OR t + (binopWithType BinOpType.AND t e1 mask) src) + | e -> printfn "%A" e; raise InvalidAssignmentException + +/// A Store statement. +[] +let store endian addr v = +#if ! HASHCONS + Store (endian, addr, v) |> ASTHelper.buildStmt +#else + let k = Store (endian, addr, v) + match tryGetStmt k with + | Ok s -> s + | Error isReclaimed -> + let s' = { S = k; Tag = newSTag (); HashKey = S.HashStore endian addr v } + if isReclaimed then stmts.[k].SetTarget s' + else stmts.[k] <- WeakReference s' + s' +#endif + +/// An assignment statement. +[] +let assign dst src = +#if DEBUG + TypeCheck.checkEquivalence (TypeCheck.typeOf dst) (TypeCheck.typeOf src) +#endif + match dst.E with + | Var _ | TempVar _ | PCVar _ -> put dst src + | Load (_, _, e, _) -> store Endian.Little e src + | Extract (_) -> assignForExtractDst dst src + | _ -> raise InvalidAssignmentException + +/// A Jmp statement. +[] +let jmp target = +#if ! HASHCONS + Jmp (target) |> ASTHelper.buildStmt +#else + let k = Jmp (target) + match tryGetStmt k with + | Ok s -> s + | Error isReclaimed -> + let s' = { S = k; Tag = newSTag (); HashKey = S.HashJmp target } + if isReclaimed then stmts.[k].SetTarget s' + else stmts.[k] <- WeakReference s' + s' +#endif + +/// A CJmp statement. +[] +let cjmp cond dst1 dst2 = +#if ! HASHCONS + CJmp (cond, dst1, dst2) |> ASTHelper.buildStmt +#else + let k = CJmp (cond, dst1, dst2) + match tryGetStmt k with + | Ok s -> s + | Error isReclaimed -> + let s' = { S = k; Tag = newSTag (); HashKey = S.HashCJmp cond dst1 dst2 } + if isReclaimed then stmts.[k].SetTarget s' + else stmts.[k] <- WeakReference s' + s' +#endif + +/// An InterJmp statement. +[] +let interjmp dst kind = +#if ! HASHCONS + InterJmp (dst, kind) |> ASTHelper.buildStmt +#else + let k = InterJmp (dst, kind) + match tryGetStmt k with + | Ok s -> s + | Error isReclaimed -> + let s' = { S = k; Tag = newSTag (); HashKey = S.HashInterJmp dst kind } + if isReclaimed then stmts.[k].SetTarget s' + else stmts.[k] <- WeakReference s' + s' +#endif + +/// A InterCJmp statement. +[] +let intercjmp cond d1 d2 = +#if ! HASHCONS + InterCJmp (cond, d1, d2) |> ASTHelper.buildStmt +#else + let k = InterCJmp (cond, d1, d2) + match tryGetStmt k with + | Ok s -> s + | Error isReclaimed -> + let s' = { S = k; Tag = newSTag (); HashKey = S.HashInterCJmp cond d1 d2 } + if isReclaimed then stmts.[k].SetTarget s' + else stmts.[k] <- WeakReference s' + s' +#endif + +/// A SideEffect statement. +[] +let sideEffect eff = +#if ! HASHCONS + SideEffect eff |> ASTHelper.buildStmt +#else + let k = SideEffect eff + match tryGetStmt k with + | Ok s -> s + | Error isReclaimed -> + let s' = { S = k; Tag = newSTag (); HashKey = S.HashSideEffect eff } + if isReclaimed then stmts.[k].SetTarget s' + else stmts.[k] <- WeakReference s' + s' +#endif - let fgt e1 e2 = relop RelOpType.FGT e1 e2 +module InfixOp = + /// Assignment. + let inline (:=) e1 e2 = assign e1 e2 - let fge e1 e2 = relop RelOpType.FGE e1 e2 + /// Addition. + let inline (.+) e1 e2 = add e1 e2 - let flt e1 e2 = relop RelOpType.FLT e1 e2 + /// Subtraction. + let inline (.-) e1 e2 = sub e1 e2 - let fle e1 e2 = relop RelOpType.FLE e1 e2 + /// Multiplication. + let inline (.*) e1 e2 = mul e1 e2 - let fSqrt e = unop UnOpType.FSQRT e + /// Unsigned division. + let inline (./) e1 e2 = div e1 e2 - let fSin e = unop UnOpType.FSIN e + /// Signed division. + let inline (?/) e1 e2 = sdiv e1 e2 - let fCos e = unop UnOpType.FCOS e + /// Unsigned modulus. + let inline (.%) e1 e2 = ``mod`` e1 e2 - let fTan e = unop UnOpType.FTAN e + /// Signed modulus. + let inline (?%) e1 e2 = smod e1 e2 - let fAtan e = unop UnOpType.FATAN e + /// Equal. + let inline (==) e1 e2 = eq e1 e2 - let rec unwrapExpr = function - | Cast (_, _, e, _, _) - | Extract (e, _, _, _, _) -> unwrapExpr e - | e -> e + /// Not equal. + let inline (!=) e1 e2 = neq e1 e2 - /// Zero padding (extension). - let zExt addrSize expr = cast CastKind.ZeroExt addrSize expr + /// Unsigned greater than. + let inline (.>) e1 e2 = gt e1 e2 - /// Sign extension. - let sExt addrSize expr = cast CastKind.SignExt addrSize expr + /// Unsigned greater than or equal. + let inline (.>=) e1 e2 = ge e1 e2 - /// Take low. - let extractLow addrSize expr = extract expr addrSize 0 + /// Signed greater than. + let inline (?>) e1 e2 = sgt e1 e2 - /// Take high. - let extractHigh addrSize expr = - extract expr addrSize (int (typeOf expr - addrSize)) + /// Signed greater than or equal. + let inline (?>=) e1 e2 = sge e1 e2 - /// Load expression in little-endian. - let loadLE t expr = load Endian.Little t expr + /// Signed less than. + let inline (.<) e1 e2 = lt e1 e2 - let typeOf e = TypeCheck.typeOf e + /// Signed less than or equal. + let inline (.<=) e1 e2 = le e1 e2 - let rec private typeCheckExpr = function - | UnOp (_, e, _, _) -> typeCheckExpr e - | BinOp (BinOpType.CONCAT, t, e1, e2, _, _) -> - typeCheckExpr e1 && typeCheckExpr e2 && concatType e1 e2 = t - | BinOp (_, t, e1, e2, _, _) -> - typeCheckExpr e1 && typeCheckExpr e2 && getCommonType e1 e2 = t - | RelOp (_, e1, e2, _, _) -> - typeCheckExpr e1 && typeCheckExpr e2 && typeOf e1 = typeOf e2 - | Load (_, _, addr, _, _) -> typeCheckExpr addr - | Ite (cond, e1, e2, _, _) -> - typeOf cond = 1 - && typeCheckExpr e1 && typeCheckExpr e2 && typeOf e1 = typeOf e2 - | Cast (CastKind.SignExt, t, e, _, _) - | Cast (CastKind.ZeroExt, t, e, _, _) -> typeCheckExpr e && t >= typeOf e - | Extract (e, t, p, _, _) -> - typeCheckExpr e && ((t + RegType.fromBitWidth p) <= typeOf e) - | _ -> true + /// Signed less than. + let inline (?<) e1 e2 = slt e1 e2 - let typeCheck = function - | Put (v, e) -> (typeOf v) = (typeOf e) - | Store (_, a, v) -> typeCheckExpr a && typeCheckExpr v - | Jmp (a) -> typeCheckExpr a - | CJmp (cond, e1, e2) -> - typeCheckExpr cond && typeCheckExpr e1 && typeCheckExpr e2 - | InterJmp (pc, addr, _) -> typeCheckExpr pc && typeCheckExpr addr - | InterCJmp (cond, pc, a1, a2) -> - typeCheckExpr cond && typeCheckExpr pc - && typeCheckExpr a1 && typeCheckExpr a2 - | _ -> true + /// Signed less than or equal. + let inline (?<=) e1 e2 = sle e1 e2 -module HashCons = - exception ConsistencyFailException of string - exception TagNotExistException + /// Bitwise AND. + let inline (.&) e1 e2 = ``and`` e1 e2 - let private tag = ref 0L + /// Bitwise OR. + let inline (.|) e1 e2 = ``or`` e1 e2 - let private wrt = new ConcurrentWeakReferenceTable () + /// Bitwise XOR. + let inline (<+>) e1 e2 = xor e1 e2 - let inline private genMeta expr = - { Tag = System.Threading.Interlocked.Increment (tag) - Hash = expr.GetHashCode () } |> Some + /// Shift arithmetic right. + let inline (?>>) e1 e2 = sar e1 e2 - let private factory expr = - match expr with - | UnOp (op, e, ei, None) -> UnOp (op, e, ei, genMeta expr) - | BinOp (op, typ, e1, e2, ei, None) -> - BinOp (op, typ, e1, e2, ei, genMeta expr) - | RelOp (op, e1, e2, ei, None) -> RelOp (op, e1, e2, ei, genMeta expr) - | Load (edn, typ, e, ei, None) -> Load (edn, typ, e, ei, genMeta expr) - | Ite (cond, e1, e2, ei, None) -> Ite (cond, e1, e2, ei, genMeta expr) - | Cast (cast, typ, e, ei, None) -> Cast (cast, typ, e, ei, genMeta expr) - | Extract (e, rt, st, ei, None) -> Extract (e, rt, st, ei, genMeta expr) - | Num (_) | Var (_) | PCVar (_) | TempVar (_) | Name (_) | Undefined (_) -> - raise <| ConsistencyFailException ("ConcurrentWeakReferenceTable: - This expr cannot be hash-consed.") - | _ -> raise <| ConsistencyFailException ("ConcurrentWeakReferenceTable: - This expr already hash-consed.") + /// Shift logical right. + let inline (>>) e1 e2 = shr e1 e2 - let isHashConsable = function - | Num _ | Var _ | PCVar _ | TempVar _ | Name _ | FuncName _ | Undefined _ -> - false - | _ -> true - - let isHashConsed = function - | Num _ | Var _ | PCVar _ | TempVar _ | FuncName _ | Name _ | Undefined _ - | UnOp (_, _, _, Some _) | BinOp (_, _, _, _, _, Some _) - | RelOp (_, _, _, _, Some _) | Load (_, _, _, _, Some _) - | Ite (_, _, _, _, Some _) | Cast (_, _, _, _, Some _) - | Extract (_, _, _, _, Some _) -> true - | _ -> false - - let getTag = function - | UnOp (_, _, _, Some x) | BinOp (_, _, _, _, _, Some x) - | RelOp (_, _, _, _, Some x) | Load (_, _, _, _, Some x) - | Ite (_, _, _, _, Some x) | Cast (_, _, _, _, Some x) - | Extract (_, _, _, _, Some x) -> x.Tag - | _ -> raise TagNotExistException - - let hashCons expr = wrt.GetOrApplyAndAdd expr factory - - let cons x y = AST.cons x y |> hashCons - - /// Hash-consed App constructor. - let app name args retType = - let funName = FuncName (name) - if List.isEmpty args then [ Nil ] else args - |> List.reduceBack cons - |> fun cons -> - BinOp (BinOpType.APP, retType, funName, cons, AST.getExprInfo cons, None) - |> hashCons - - let unop t e = AST.unopBuilder t e hashCons - - let binop op e1 e2 = AST.binopBuilder op e1 e2 hashCons - - let relop op e1 e2 = AST.relopBuilder op e1 e2 hashCons - - let load endian t e = AST.loadBuilder endian t e hashCons - - let ite cond e1 e2 = AST.iteBuilder cond e1 e2 hashCons - - let cast kind t e = AST.castBuilder kind t e hashCons - - let extract e t pos = AST.extractBuilder e t pos hashCons - -// vim: set tw=80 sts=2 sw=2: + /// Shift logical left. + let inline (<<) e1 e2 = shl e1 e2 diff --git a/src/BinIR/LowUIR.AST.fsi b/src/BinIR/LowUIR.AST.fsi deleted file mode 100644 index b52f997b..00000000 --- a/src/BinIR/LowUIR.AST.fsi +++ /dev/null @@ -1,293 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinIR.LowUIR - -open B2R2 -open B2R2.BinIR - -module TypeCheck = begin - - val typeOf : Expr -> RegType - -end - -/// This module defines functions for handling the AST of LowUIR. -module AST = begin - /// Get Expression Information - val getExprInfo : Expr -> ExprInfo - - /// Construct a number (Num). - val num : BitVector -> Expr - - /// Construct a variable (Var). - val var : RegType -> RegisterID -> string -> RegisterSet -> Expr - - /// Construct a pc variable (PCVar). - val pcVar : RegType -> string -> Expr - - /// Construct a temporary variable (TempVar). - val tmpVar : RegType -> Expr - - /// Construct a symbol (for a label) from a string. - val lblSymbol : string -> Symbol - - /// Construct an unary operator (UnOp). - val unop : UnOpType -> Expr -> Expr - - /// Construct a binary operator (BinOp). - val binop : BinOpType -> Expr -> Expr -> Expr - - /// Consing two expr - val cons: Expr -> Expr -> Expr - - /// Construct a app - val app : string -> Expr list -> RegType -> Expr - - /// Construct a relative operator (RelOp). - val relop : RelOpType -> Expr -> Expr -> Expr - - /// Construct a load expression (Load). - val load : Endian -> RegType -> Expr -> Expr - - /// Construct an ITE (if-then-else) expression (Ite). - val ite : Expr -> Expr -> Expr -> Expr - - /// Construct a cast expression (Cast). - val cast : CastKind -> RegType -> Expr -> Expr - - /// Construct a extract expression (Extract). - val extract : Expr -> RegType -> StartPos -> Expr - - /// Undefined expression. - val unDef : RegType -> string -> Expr - - /// Construct a (Num 0) of size t. - val num0 : t: RegType -> Expr - - /// Construct a (Num 1) of size t. - val num1 : t: RegType -> Expr - - /// Num expression for a one-bit number zero. - val b0 : Expr - - /// Num expression for a one-bit number one. - val b1 : Expr - - /// An assignment statement. - val (:=) : Expr -> Expr -> Stmt - - /// Add two expressions. - val (.+) : Expr -> Expr -> Expr - - /// Subtract two expressions. - val (.-) : Expr -> Expr -> Expr - - /// Multiplication. - val (.*) : Expr -> Expr -> Expr - - /// Unsigned division. - val (./) : Expr -> Expr -> Expr - - /// Signed division. - val (?/) : Expr -> Expr -> Expr - - /// Unsigned modulus. - val (.%) : Expr -> Expr -> Expr - - /// Signed modulus. - val (?%) : Expr -> Expr -> Expr - - /// Equal. - val (==) : Expr -> Expr -> Expr - - /// Not equal. - val (!=) : Expr -> Expr -> Expr - - /// Unsigned greater than. - val gt : Expr -> Expr -> Expr - - /// Unsigned greater than or equal. - val ge : Expr -> Expr -> Expr - - /// Signed greater than. - val sgt : Expr -> Expr -> Expr - - /// Signed greater than or equal. - val sge : Expr -> Expr -> Expr - - /// Unsigned less than. - val lt : Expr -> Expr -> Expr - - /// Unsigned less than or equal. - val le : Expr -> Expr -> Expr - - /// Signed less than. - val slt : Expr -> Expr -> Expr - - /// Signed less than or equal. - val sle : Expr -> Expr -> Expr - - /// Bitwise AND. - val (.&) : Expr -> Expr -> Expr - - /// Bitwise OR. - val (.|) : Expr -> Expr -> Expr - - /// Bitwise XOR. - val (<+>) : Expr -> Expr -> Expr - - /// Shift arithmetic right. - val (?>>) : Expr -> Expr -> Expr - - /// Shift logical right. - val (>>) : Expr -> Expr -> Expr - - /// Shift logical left. - val (<<) : Expr -> Expr -> Expr - - /// Negation (Two's complement). - val neg : Expr -> Expr - - /// Logical not. - val not : Expr -> Expr - - /// Floating point add two expressions. - val fadd: Expr -> Expr -> Expr - - /// Floating point subtract two expressions. - val fsub: Expr -> Expr -> Expr - - /// Floating point multiplication. - val fmul : Expr -> Expr -> Expr - - /// Floating point division. - val fdiv : Expr -> Expr -> Expr - - /// Floating point greater than. - val fgt : Expr -> Expr -> Expr - - /// Floating point greater than or equal. - val fge : Expr -> Expr -> Expr - - /// Floating point less than. - val flt : Expr -> Expr -> Expr - - /// Floating point less than or equal. - val fle : Expr -> Expr -> Expr - - /// Floating point power. - val fpow : Expr -> Expr -> Expr - - /// Floating point logarithm. - val flog : Expr -> Expr -> Expr - - /// Floating point square root. - val fSqrt : Expr -> Expr - - /// Floating point cosine. - val fCos : Expr -> Expr - - /// Floating point sine. - val fSin : Expr -> Expr - - /// Floating point tangent. - val fTan : Expr -> Expr - - /// Floating point arc tangent. - val fAtan : Expr -> Expr - - /// Concatenation. - val concat : Expr -> Expr -> Expr - - /// Concatenate an array of expressions. - val concatExprs : Expr[] -> Expr - - /// Unwrap (casted) expression. - val unwrapExpr : Expr -> Expr - - /// Zero-extend an expression. - val zExt : RegType -> Expr -> Expr - - /// Sign-extend an expression. - val sExt : RegType -> Expr -> Expr - - /// Take the low half bits of an expression. - val extractLow : RegType -> Expr -> Expr - - /// Take the high half bits of an expression. - val extractHigh : RegType -> Expr -> Expr - - /// Load expression in little-endian. - val loadLE : RegType -> Expr -> Expr - - /// Get the type of an expression. - val typeOf : Expr -> RegType - - /// Return true if the given statement type checks. - val typeCheck : Stmt -> bool - -end - -module HashCons = begin - - exception ConsistencyFailException of string - exception TagNotExistException - - /// Return true if the given expression is hash-consable. - val isHashConsable : Expr -> bool - - /// Return true if the given expression is hash-consed. - val isHashConsed : Expr -> bool - - /// Return the tag of hash-consed expression. - val getTag : Expr -> int64 - - /// Hash-consed UnOp constructor. - val unop : UnOpType -> Expr -> Expr - - /// Hash-consed BinOp constructor. - val binop : BinOpType -> Expr -> Expr -> Expr - - /// Hash-consed App constructor. - val app : string -> Expr list -> RegType -> Expr - - /// Hash-consed RelOp constructor. - val relop : RelOpType -> Expr -> Expr -> Expr - - /// Hash-consed Load constructor. - val load : Endian -> RegType -> Expr -> Expr - - /// Hash-consed Ite constructor. - val ite : Expr -> Expr -> Expr -> Expr - - /// Hash-consed Cast constructor. N.B. Type checking is not performed. - val cast : CastKind -> RegType -> Expr -> Expr - - /// Hash-consed Extract constructor. - val extract : Expr -> RegType -> StartPos -> Expr - -end - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/BinIR/LowUIR.ASTHelper.fs b/src/BinIR/LowUIR.ASTHelper.fs new file mode 100644 index 00000000..28791964 --- /dev/null +++ b/src/BinIR/LowUIR.ASTHelper.fs @@ -0,0 +1,147 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.BinIR.LowUIR + +open B2R2 +open B2R2.BinIR + +/// Concrete value optimization. +[] +module internal ValueOptimizer = + let inline unop n = function + | UnOpType.NEG -> BitVector.neg n + | UnOpType.NOT -> BitVector.bnot n + | UnOpType.FSQRT -> BitVector.fsqrt n + | UnOpType.FCOS -> BitVector.fcos n + | UnOpType.FSIN -> BitVector.fsin n + | UnOpType.FTAN -> BitVector.ftan n + | UnOpType.FATAN -> BitVector.fatan n + | _ -> Utils.impossible () + + let inline binop n1 n2 = function + | BinOpType.ADD -> BitVector.add n1 n2 + | BinOpType.SUB -> BitVector.sub n1 n2 + | BinOpType.MUL -> BitVector.mul n1 n2 + | BinOpType.DIV -> BitVector.div n1 n2 + | BinOpType.SDIV -> BitVector.sdiv n1 n2 + | BinOpType.MOD -> BitVector.modulo n1 n2 + | BinOpType.SMOD -> BitVector.smodulo n1 n2 + | BinOpType.SHL -> BitVector.shl n1 n2 + | BinOpType.SAR -> BitVector.sar n1 n2 + | BinOpType.SHR -> BitVector.shr n1 n2 + | BinOpType.AND -> BitVector.band n1 n2 + | BinOpType.OR -> BitVector.bor n1 n2 + | BinOpType.XOR -> BitVector.bxor n1 n2 + | BinOpType.CONCAT -> BitVector.concat n1 n2 + | BinOpType.FADD -> BitVector.fadd n1 n2 + | BinOpType.FSUB -> BitVector.fsub n1 n2 + | BinOpType.FMUL -> BitVector.fmul n1 n2 + | BinOpType.FDIV -> BitVector.fdiv n1 n2 + | BinOpType.FPOW -> BitVector.fpow n1 n2 + | BinOpType.FLOG -> BitVector.flog n1 n2 + | _ -> Utils.impossible () + + let inline relop n1 n2 = function + | RelOpType.EQ -> BitVector.eq n1 n2 + | RelOpType.NEQ -> BitVector.neq n1 n2 + | RelOpType.GT -> BitVector.gt n1 n2 + | RelOpType.GE -> BitVector.ge n1 n2 + | RelOpType.SGT -> BitVector.sgt n1 n2 + | RelOpType.SGE -> BitVector.sge n1 n2 + | RelOpType.LT -> BitVector.lt n1 n2 + | RelOpType.LE -> BitVector.le n1 n2 + | RelOpType.SLT -> BitVector.slt n1 n2 + | RelOpType.SLE -> BitVector.sle n1 n2 + | RelOpType.FLT -> BitVector.flt n1 n2 + | RelOpType.FLE -> BitVector.fle n1 n2 + | RelOpType.FGT -> BitVector.fgt n1 n2 + | RelOpType.FGE -> BitVector.fge n1 n2 + | _ -> Utils.impossible () + + let inline cast t n = function + | CastKind.SignExt -> BitVector.sext n t + | CastKind.ZeroExt -> BitVector.zext n t + | CastKind.FloatCast -> BitVector.fcast n t + | CastKind.IntToFloat -> BitVector.itof n t + | CastKind.FtoICeil -> BitVector.ftoiceil n t + | CastKind.FtoIFloor -> BitVector.ftoifloor n t + | CastKind.FtoIRound -> BitVector.ftoiround n t + | CastKind.FtoITrunc -> BitVector.ftoitrunc n t + | _ -> Utils.impossible () + + let inline extract e t pos = BitVector.extract e t pos + +[] +module internal ASTHelper = +#if ! HASHCONS + let inline buildExpr e = + { E = e } + + let inline buildStmt s = + { S = s } +#endif + + let emptyExprInfo = + { HasLoad = false + VarsUsed = RegisterSet.empty + TempVarsUsed = Set.empty } + + let getExprInfo e = + match e.E with + | Num _ | PCVar _ | Nil | Name _ | FuncName _ | Undefined _ -> emptyExprInfo + | Var (_, _, _, rset) -> + { HasLoad = false; VarsUsed = rset; TempVarsUsed = Set.empty } + | TempVar (_, name) -> + { HasLoad = false + VarsUsed = RegisterSet.empty + TempVarsUsed = Set.singleton name } + | UnOp (_, _, ei) + | BinOp (_, _, _, _, ei) + | RelOp (_, _, _, ei) + | Load (_, _, _, ei) + | Ite (_, _, _, ei) + | Cast (_, _, _, ei) + | Extract (_, _, _, ei) -> ei + + let mergeTwoExprInfo e1 e2 = + let ei1 = getExprInfo e1 + let ei2 = getExprInfo e2 + { HasLoad = ei1.HasLoad || ei2.HasLoad + VarsUsed = RegisterSet.union ei1.VarsUsed ei2.VarsUsed + TempVarsUsed = Set.union ei1.TempVarsUsed ei2.TempVarsUsed } + + let mergeThreeExprInfo e1 e2 e3 = + let ei1 = getExprInfo e1 + let ei2 = getExprInfo e2 + let ei3 = getExprInfo e3 + let vars = + RegisterSet.union ei1.VarsUsed ei2.VarsUsed + |> RegisterSet.union ei3.VarsUsed + let tmps = + Set.union ei1.TempVarsUsed ei2.TempVarsUsed + |> Set.union ei3.TempVarsUsed + { HasLoad = ei1.HasLoad || ei2.HasLoad || ei3.HasLoad + VarsUsed = vars + TempVarsUsed = tmps } diff --git a/src/BinIR/LowUIR.Pp.fs b/src/BinIR/LowUIR.Pp.fs index a9bd8a1e..951840c8 100644 --- a/src/BinIR/LowUIR.Pp.fs +++ b/src/BinIR/LowUIR.Pp.fs @@ -22,140 +22,20 @@ SOFTWARE. *) -/// Pretty printer for LowUIR. +/// Wrapper of pretty printer for LowUIR. module B2R2.BinIR.LowUIR.Pp open System open System.Text open B2R2 -open B2R2.BinIR -let rec private expToStringAux expr (sb: StringBuilder) = - match expr with - | Num n -> sb.Append (BitVector.toString n) |> ignore - | Var (_typ, _, n, _) -> sb.Append (n) |> ignore - | Nil -> sb.Append ("nil") |> ignore - | PCVar (_typ, n) -> sb.Append (n) |> ignore - | TempVar (typ, n) -> - sb.Append ("T_") |> ignore - sb.Append (n) |> ignore - sb.Append (":") |> ignore - sb.Append (RegType.toString typ) |> ignore - | Name (n) -> sb.Append (Symbol.getName n) |> ignore - | FuncName (n) -> sb.Append (n) |> ignore - | UnOp (op, e, _, _) -> - sb.Append ("(") |> ignore - sb.Append (UnOpType.toString op) |> ignore - sb.Append (" ") |> ignore - expToStringAux e sb - sb.Append (")") |> ignore - | BinOp (op, _typ, e1, e2, _, _) -> - sb.Append ("(") |> ignore - expToStringAux e1 sb - sb.Append (" ") |> ignore - sb.Append (BinOpType.toString op) |> ignore - sb.Append (" ") |> ignore - expToStringAux e2 sb - sb.Append (")") |> ignore - | RelOp (op, e1, e2, _, _) -> - sb.Append ("(") |> ignore - expToStringAux e1 sb - sb.Append (" ") |> ignore - sb.Append (RelOpType.toString op) |> ignore - sb.Append (" ") |> ignore - expToStringAux e2 sb - sb.Append (")") |> ignore - | Load (_endian, typ, e, _, _) -> - sb.Append ("[") |> ignore - expToStringAux e sb - sb.Append ("]:") |> ignore - sb.Append (RegType.toString typ) |> ignore - | Ite (cond, e1, e2, _, _) -> - sb.Append ("(ite (") |> ignore - expToStringAux cond sb - sb.Append (") (") |> ignore - expToStringAux e1 sb - sb.Append (") (") |> ignore - expToStringAux e2 sb - sb.Append ("))") |> ignore - | Cast (cast, typ, e, _, _) -> - sb.Append (CastKind.toString cast) |> ignore - sb.Append (":") |> ignore - sb.Append (RegType.toString typ) |> ignore - sb.Append ("(") |> ignore - expToStringAux e sb - sb.Append (")") |> ignore - | Extract (e, typ, p, _, _) -> - sb.Append ("(") |> ignore - expToStringAux e sb - sb.Append ("[") |> ignore - sb.Append ((int typ + p - 1).ToString () + ":" + p.ToString ())|> ignore - sb.Append ("]") |> ignore - sb.Append (")") |> ignore - | Undefined (_, reason) -> - sb.Append ("Undefined expression (") |> ignore - sb.Append (reason) |> ignore - sb.Append (")") |> ignore +let expToString = Expr.toString -let private stmtToStringAux stmt (sb: StringBuilder) = - match stmt with - | ISMark (addr, _) -> - sb.Append ("=== ISMark (") |> ignore - sb.Append (addr.ToString("X")) |> ignore - sb.Append (")") |> ignore - | IEMark (addr) -> - sb.Append ("=== IEMark (pc := ") |> ignore - sb.Append (addr.ToString("X")) |> ignore - sb.Append (")") |> ignore - | LMark lbl -> - sb.Append ("=== LMark (") |> ignore - sb.Append (Symbol.getName lbl) |> ignore - sb.Append (")") |> ignore - | Put (exp1, exp2) -> - expToStringAux exp1 sb - sb.Append (" := ") |> ignore - expToStringAux exp2 sb - | Jmp exp -> - sb.Append ("JmpLbl ") |> ignore - expToStringAux exp sb - | InterJmp (_pc, exp, _) -> - sb.Append ("Jmp ") |> ignore - expToStringAux exp sb - | Store (_endian, exp1, exp2) -> - sb.Append ("[") |> ignore - expToStringAux exp1 sb - sb.Append ("] := ") |> ignore - expToStringAux exp2 sb - | CJmp (cond, t, f) -> - sb.Append ("if ") |> ignore - expToStringAux cond sb - sb.Append (" then JmpLbl ") |> ignore - expToStringAux t sb - sb.Append (" else JmpLbl ") |> ignore - expToStringAux f sb - | InterCJmp (cond, _pc, t, f) -> - sb.Append ("if ") |> ignore - expToStringAux cond sb - sb.Append (" then Jmp ") |> ignore - expToStringAux t sb - sb.Append (" else Jmp ") |> ignore - expToStringAux f sb - | SideEffect eff -> - sb.Append ("SideEffect " + SideEffect.toString eff) |> ignore - -let expToString expr = - let sb = new StringBuilder () - expToStringAux expr sb - sb.ToString () - -let stmtToString expr = - let sb = new StringBuilder () - stmtToStringAux expr sb - sb.ToString () +let stmtToString = Stmt.toString let stmtsToString stmts = let sb = StringBuilder() - Array.iter (fun stmt -> stmtToStringAux stmt sb - sb.Append (Environment.NewLine) |> ignore) stmts + Array.iter (fun stmt -> + Stmt.appendToString stmt sb + sb.Append (Environment.NewLine) |> ignore) stmts sb.ToString () - diff --git a/src/BinIR/LowUIR.TypeCheck.fs b/src/BinIR/LowUIR.TypeCheck.fs new file mode 100644 index 00000000..8c7a2f60 --- /dev/null +++ b/src/BinIR/LowUIR.TypeCheck.fs @@ -0,0 +1,120 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +[] +module B2R2.BinIR.LowUIR.TypeCheck + +open B2R2 +open B2R2.BinIR + +/// Get the type of an expression. +let rec typeOf e = + match e.E with + | Num n -> n.Length + | Var (t, _, _, _) + | PCVar (t, _) + | TempVar (t, _) -> t + | UnOp (_, e, _) -> typeOf e + | BinOp (_, t, _, _, _) -> t + | RelOp (_) -> 1 + | Load (_, t, _, _) -> t + | Ite (_, e1, _, _) -> typeOf e1 + | Cast (_, t, _, _) -> t + | Extract (_, t, _, _) -> t + | Undefined (t, _) -> t + | FuncName (_) | Name (_) | Nil -> raise InvalidExprException + +#if DEBUG +let internal bool e = + let t = typeOf e + if t <> 1 then + raise <| TypeCheckException (Pp.expToString e + "must be boolean.") + else () +#endif + +let inline internal checkEquivalence t1 t2 = + if t1 = t2 then () + else raise <| TypeCheckException "Inconsistent types." + +let internal concat e1 e2 = typeOf e1 + typeOf e2 + +let internal binop e1 e2 = + let t1 = typeOf e1 + let t2 = typeOf e2 + checkEquivalence t1 t2 + t1 + +let private castErr (newType: RegType) (oldType: RegType) = + let errMsg = + "Cannot cast from " + oldType.ToString () + " to " + newType.ToString () + raise <| TypeCheckException errMsg + +let private isValidFloatType = function + | 32 | 64 | 80 -> true + | _ -> false + +let internal canCast kind newType e = + let oldType = typeOf e + match kind with + | CastKind.SignExt + | CastKind.ZeroExt -> + if oldType < newType then true + else if oldType = newType then false + else castErr newType oldType + | CastKind.IntToFloat -> + if isValidFloatType newType then true else raise InvalidFloatTypeException + | CastKind.FloatCast -> + if isValidFloatType oldType && isValidFloatType newType then true + else raise InvalidFloatTypeException + | _ -> true + +let internal extract (t: RegType) pos (t2: RegType) = + if (RegType.toBitWidth t + pos) <= RegType.toBitWidth t2 && pos >= 0 then () + else raise <| TypeCheckException "Inconsistent types." + +let rec expr e = + match e.E with + | UnOp (_, e, _) -> expr e + | BinOp (BinOpType.CONCAT, t, e1, e2, _) -> + expr e1 && expr e2 && concat e1 e2 = t + | BinOp (_, t, e1, e2, _) -> expr e1 && expr e2 && binop e1 e2 = t + | RelOp (_, e1, e2, _) -> expr e1 && expr e2 && typeOf e1 = typeOf e2 + | Load (_, _, addr, _) -> expr addr + | Ite (cond, e1, e2, _) -> + typeOf cond = 1 && expr e1 && expr e2 && typeOf e1 = typeOf e2 + | Cast (CastKind.SignExt, t, e, _) + | Cast (CastKind.ZeroExt, t, e, _) -> expr e && t >= typeOf e + | Extract (e, t, p, _) -> + expr e && ((t + LanguagePrimitives.Int32WithMeasure p) <= typeOf e) + | _ -> true + +let stmt s = + match s.S with + | Put (v, e) -> (typeOf v) = (typeOf e) + | Store (_, a, v) -> expr a && expr v + | Jmp (a) -> expr a + | CJmp (cond, e1, e2) -> expr cond && expr e1 && expr e2 + | InterJmp (addr, _) -> expr addr + | InterCJmp (cond, a1, a2) -> expr cond && expr a1 && expr a2 + | _ -> true diff --git a/src/BinIR/LowUIR.fs b/src/BinIR/LowUIR.fs deleted file mode 100644 index d9639738..00000000 --- a/src/BinIR/LowUIR.fs +++ /dev/null @@ -1,261 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.BinIR.LowUIR - -open B2R2 -open B2R2.BinIR -open B2R2.Utils - -type [] InterJmpInfo = - | Base = 0 - | IsCall = 1 - | IsRet = 2 - | IsExit = 4 - | SwitchToARM = 8 - | SwitchToThumb = 16 - -[] -type ConsInfo = { - Tag : int64 - Hash : int -} - -/// ExprInfo summarizes several abstract information about the Expr. This is -/// useful for writing an efficient post analyses. -type ExprInfo = { - HasLoad : bool - VarInfo : RegisterSet - TempVarInfo : Set -} - -/// IR Expressions. -/// NOTE: You SHOULD NOT create Expr without using functions in -/// B2R2.BinIR.LowUIR.HashCons or B2R2.BinIR.LowUIR.AST. -[] -type Expr = - /// A number. For example, (0x42:I32) is a 32-bit number 0x42 - | Num of BitVector - - /// A variable that represents a register of a CPU. Var (t, r, n) indicates - /// a variable of type (t) that has RegisterID r and name (n). - /// For example, (EAX:I32) represents the EAX register (of type I32). - /// Note that name (n) is additional information that doesn't be used - /// internally. - | Var of RegType * RegisterID * string * RegisterSet - - /// Nil to represent cons cells. This should only be used with BinOpType.CONS. - | Nil - - /// A variable that represents a Program Counter (PC) of a CPU. - | PCVar of RegType * string - - /// A temporary variable represents an internal (imaginary) register. Names - /// of temporary variables should always be affixed by an underscore (_) and - /// a number. This is to make sure that any temporary variable is unique in - /// a CFG. For example, a temporary variable T can be represented as - /// (T_2:I32), where 2 is a unique number assigned to the variable. - | TempVar of RegType * int - - /// Unary operation such as negation. - | UnOp of UnOpType * Expr * ExprInfo * ConsInfo option - - /// Symbolic constant for labels. - | Name of Symbol - - /// Name of uninterpreted function. - | FuncName of string - - /// Binary operation such as add, sub, etc. The second argument is a result - /// type after applying BinOp. - | BinOp of BinOpType * RegType * Expr * Expr * ExprInfo * ConsInfo option - - /// Relative operation such as eq, lt, etc. - | RelOp of RelOpType * Expr * Expr * ExprInfo * ConsInfo option - - /// Memory loading such as LE:[T_1:I32] - | Load of Endian * RegType * Expr * ExprInfo * ConsInfo option - - /// If-then-else expression. The first expression is a condition, and the - /// second and the third are true and false expression respectively. - | Ite of Expr * Expr * Expr * ExprInfo * ConsInfo option - - /// Type casting expression. The first argument is a casting type, and the - /// second argument is a result type. - | Cast of CastKind * RegType * Expr * ExprInfo * ConsInfo option - - /// Extraction expression. The first argument is target expression, and the - /// second argument is the number of bits for extraction, and the third is - /// the start position. - | Extract of Expr * RegType * StartPos * ExprInfo * ConsInfo option - - /// Undefined expression. It is a fatal error when we encounter this - /// expression while evaluating a program. This expression is useful when we - /// encode a label that should not really jump to (e.g., divide-by-zero case). - | Undefined of RegType * string - - member inline private __.DoHash v phash = (phash * 16777619) ^^^ v - - member inline private __.Hash2 h1 h2 = - __.DoHash h1 -2128831035 |> __.DoHash h2 - - member inline private __.Hash3 h1 h2 h3 = - __.Hash2 h1 h2 |> __.DoHash h3 - - member inline private __.Hash4 h1 h2 h3 h4 = - __.Hash3 h1 h2 h3 |> __.DoHash h4 - - override __.Equals lhs = - match lhs with - | :? Expr as x -> - match __, x with - (* Primitive comparison. *) - | Num n1, Num n2 -> n1 = n2 - | Name s1, Name s2 -> s1 = s2 - | FuncName s1, FuncName s2 -> s1 = s2 - | Var (typ1, r1, _, _), Var (typ2, r2, _, _) -> typ1 = typ2 && r1 = r2 - | TempVar (typ1, n1), TempVar (typ2, n2) -> typ1 = typ2 && n1 = n2 - | PCVar (typ1, n1), PCVar (typ2, n2) - | Undefined (typ1, n1), Undefined (typ2, n2) -> typ1 = typ2 && n1 = n2 - (* Non-Primitive Comparison. - If both of arguments are hash-consed, use physical equality. *) - | UnOp (_, _, _, Some _), UnOp (_, _, _, Some _) - | BinOp (_, _, _, _, _, Some _), BinOp (_, _, _, _, _, Some _) - | RelOp (_, _, _, _, Some _), RelOp (_, _, _, _, Some _) - | Load (_, _, _, _, Some _), Load (_, _, _, _, Some _) - | Ite (_, _, _, _, Some _), Ite (_, _, _, _, Some _) - | Cast (_, _, _, _, Some _), Cast (_, _, _, _, Some _) - | Extract (_, _, _, _, Some _), Extract (_, _, _, _, Some _) -> - __ === x - (* Otherwise, use structure equality *) - | UnOp (op1, e1, _, _), UnOp (op2, e2, _, _) -> op1 = op2 && e1 = e2 - | BinOp (op1, typ1, e11, e12, _, _), BinOp (op2, typ2, e21, e22, _, _) -> - op1 = op2 && typ1 = typ2 && e11 = e21 && e12 = e22 - | RelOp (op1, e11, e12, _, _), RelOp (op2, e21, e22, _, _) -> - op1 = op2 && e11 = e21 && e12 = e22 - | Load (_endian1, typ1, e1, _, _), Load (_endian2, typ2, e2, _, _) -> - _endian1 = _endian2 && typ1 = typ2 && e1 = e2 - | Ite (cond1, e11, e12, _, _), Ite (cond2, e21, e22, _, _) -> - cond1 = cond2 && e11 = e21 && e12 = e22 - | Cast (cast1, typ1, e1, _, _), Cast (cast2, typ2, e2, _, _) -> - cast1 = cast2 && typ1 = typ2 && e1 = e2 - | Extract (e1, typ1, p1, _, _), Extract (e2, typ2, p2, _, _) -> - e1 = e2 && typ1 = typ2 && p1 = p2 - | _ -> false - | _ -> false - - /// If cached hash exists, then take it. Otherwise, calculate it. - override __.GetHashCode () = - match __ with - | Num n -> n.GetHashCode () - | Var (_typ, n, _, _) -> n.GetHashCode () - | Nil -> 0 - | PCVar (_typ, n) -> __.Hash2 (_typ.GetHashCode ()) (n.GetHashCode ()) - | TempVar (_typ, n) -> __.Hash2 (_typ.GetHashCode ()) (n.GetHashCode ()) - | UnOp (_, _, _, Some x) -> x.Hash - | UnOp (op, e, _, None) -> __.Hash2 (op.GetHashCode ()) (e.GetHashCode ()) - | Name s -> s.GetHashCode () - | FuncName s -> s.GetHashCode () - | BinOp (_, _, _, _, _, Some x) -> x.Hash - | BinOp (op, typ, e1, e2, _, None) -> - __.Hash4 (op.GetHashCode ()) (typ.GetHashCode ()) - (e1.GetHashCode ()) (e2.GetHashCode ()) - | RelOp (_, _, _, _, Some x) -> x.Hash - | RelOp (op, e1, e2, _, None) -> - __.Hash3 (op.GetHashCode ()) (e1.GetHashCode ()) (e2.GetHashCode ()) - | Load (_endian, _, _, _, Some x) -> x.Hash - | Load (_endian, typ, e, _, None) -> - __.Hash3 (_endian.GetHashCode ()) (typ.GetHashCode ()) (e.GetHashCode ()) - | Ite (_, _, _, _, Some x) -> x.Hash - | Ite (cond, e1, e2, _, None) -> - __.Hash3 (cond.GetHashCode ()) (e1.GetHashCode ()) (e2.GetHashCode ()) - | Cast (_, _, _, _, Some x) -> x.Hash - | Cast (cast, typ, e, _, None) -> - __.Hash3 (cast.GetHashCode ()) (typ.GetHashCode ()) (e.GetHashCode ()) - | Extract (_, _, _, _, Some x) -> x.Hash - | Extract (e, typ, pos, _, None) -> - __.Hash3 (e.GetHashCode ()) (typ.GetHashCode ()) (pos.GetHashCode ()) - | Undefined (typ, r) -> __.Hash2 (typ.GetHashCode ()) (r.GetHashCode ()) - -/// IL Statements. -type Stmt = - /// ConsInfo data representing the start of a machine instruction. More - /// specifically, it contains the address and the length of the instruction. - /// There is a single IMark per machine instruction. - /// - /// Example: [IMark(, )] - /// represents a machine instruction of bytes located at - | ISMark of Addr * uint32 - - /// ConsInfo data representing the end of a machine instruction. It contains the - /// next fall-through address. - | IEMark of Addr - - /// ConsInfo data representing a label (as in an assembly language). LMark is - /// only valid within a machine instruction. - | LMark of Symbol - - /// This statement puts a value into a register. The first argument is a - /// destination operand, and the second argument is a source operand. The - /// destination operand should have either a Var or a TempVar. - /// - /// Example: [Put(T_1:I32, Load(LE, T_2:I32))] - /// loads a 32-bit value from the address T2, and store the value to the - /// temporary register T1. - | Put of Expr * Expr - - /// This statement stores a value into a memory. The first argument - /// represents the endianness, the second argument is a destination operand, - /// and the third argument is a value to store. - /// - /// Example: Store(LE, T_1:I32, T_2:I32) - /// stores a 32-bit value T_2 into the address T_1 - | Store of Endian * Expr * Expr - - /// This statement represents a jump (unconditional) to an LMark. The first - /// argument specifies the target address. - | Jmp of Expr - - /// This statement represents a conditional jump to an LMark. The first - /// argument specifies a jump condition. If the condition is true, jump to - /// the address specified by the second argument. Otherwise, jump to the - /// address specified by the third argument. - | CJmp of Expr * Expr * Expr - - /// This is an unconditional jump instruction to another instruction. This - /// is an inter-instruction jump unlike Jmp statement. The first argument - /// represents the program counter, and the second is the target address. - | InterJmp of Expr * Expr * InterJmpInfo - - /// This is a conditional jump instruction to another instruction. The first - /// argument specifies a jump condition, and the second argument represents - /// the program counter. If the condition is true, change the program - /// counter to jump to the address specified by the third argument. - /// Otherwise, jump to the address specified by the fourth argument. - | InterCJmp of Expr * Expr * Expr * Expr - - /// This represents an instruction with side effects such as a system call. - | SideEffect of SideEffect - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/BinIR/README.md b/src/BinIR/README.md new file mode 100644 index 00000000..5235ff86 --- /dev/null +++ b/src/BinIR/README.md @@ -0,0 +1,12 @@ +# B2R2.BinIR + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.BinIR Package? + +`B2R2.BinIR` defines intermediate representations (and their ASTs) that we use +in our analyses. diff --git a/src/BinIR/RelOpType.fs b/src/BinIR/RelOpType.fs index 336f21bf..f7b2ea62 100644 --- a/src/BinIR/RelOpType.fs +++ b/src/BinIR/RelOpType.fs @@ -72,3 +72,20 @@ module RelOpType = | RelOpType.FLT -> "<." | RelOpType.FLE -> "<=." | _ -> raise IllegalASTTypeException + + let ofString = function + | "=" -> RelOpType.EQ + | "!=" -> RelOpType.NEQ + | ">" -> RelOpType.GT + | ">=" -> RelOpType.GE + | "?>" -> RelOpType.SGT + | "?>=" -> RelOpType.SGE + | "<" -> RelOpType.LT + | "<=" -> RelOpType.LE + | "?<" -> RelOpType.SLT + | "?<=" -> RelOpType.SLE + | ">." -> RelOpType.FGT + | ">=." -> RelOpType.FGE + | "<." -> RelOpType.FLT + | "<=." -> RelOpType.FLE + | _ -> raise IllegalASTTypeException diff --git a/src/BinIR/SSA.AST.fs b/src/BinIR/SSA.AST.fs index 929eedcb..1ef9444f 100644 --- a/src/BinIR/SSA.AST.fs +++ b/src/BinIR/SSA.AST.fs @@ -55,40 +55,42 @@ let private translateLabel addr = function | LowUIR.Undefined (_, s) -> addr, (s, -1) | _ -> raise InvalidExprException -let rec translateExpr = function +let rec translateExpr (e: LowUIR.Expr) = + match e.E with | LowUIR.Num bv -> Num bv | (LowUIR.Var _ as e) | (LowUIR.PCVar _ as e) | (LowUIR.TempVar _ as e) -> Var <| translateDest e - | LowUIR.UnOp (op, e, _, _) -> + | LowUIR.UnOp (op, e, _) -> let ty = LowUIR.TypeCheck.typeOf e UnOp (op, ty, translateExpr e) | LowUIR.FuncName s -> FuncName s - | LowUIR.BinOp (op, ty, e1, e2, _, _) -> + | LowUIR.BinOp (op, ty, e1, e2, _) -> BinOp (op, ty, translateExpr e1, translateExpr e2) - | LowUIR.RelOp (op, e1, e2, _, _) -> + | LowUIR.RelOp (op, e1, e2, _) -> RelOp (op, 1, translateExpr e1, translateExpr e2) - | LowUIR.Load (_, ty, e, _, _) -> + | LowUIR.Load (_, ty, e, _) -> Load ({ Kind = MemVar; Identifier = -1 }, ty, translateExpr e) - | LowUIR.Ite (e1, e2, e3, _, _) -> + | LowUIR.Ite (e1, e2, e3, _) -> let ty = LowUIR.TypeCheck.typeOf e2 Ite (translateExpr e1, ty, translateExpr e2, translateExpr e3) - | LowUIR.Cast (op, ty, e, _, _) -> Cast (op, ty, translateExpr e) - | LowUIR.Extract (e, ty, pos, _, _) -> Extract (translateExpr e, ty, pos) + | LowUIR.Cast (op, ty, e, _) -> Cast (op, ty, translateExpr e) + | LowUIR.Extract (e, ty, pos, _) -> Extract (translateExpr e, ty, pos) | LowUIR.Undefined (ty, s) -> Undefined (ty, s) | LowUIR.Nil -> Nil | _ -> raise InvalidExprException /// Name -let rec internal translateStmtAux defaultRegType addr = function - | LowUIR.ISMark _ -> None - | LowUIR.IEMark addr -> +let rec internal translateStmtAux defaultRegType addr (s: LowUIR.Stmt) = + match s.S with + | LowUIR.ISMark _ -> let pc = { Kind = PCVar (defaultRegType); Identifier = -1 } - let num = Num <| BitVector.ofUInt64 addr defaultRegType - Def (pc, num) |> Some + let n = Num <| BitVector.ofUInt64 addr defaultRegType + Def (pc, n) |> Some + | LowUIR.IEMark _ -> None | LowUIR.LMark symb -> LMark (addr, symb) |> Some | LowUIR.Put (var, expr) -> - let dest = translateDest var + let dest = translateDest var.E let expr = translateExpr expr Def (dest, expr) |> Some | LowUIR.Store (_, addr, expr) -> @@ -100,20 +102,20 @@ let rec internal translateStmtAux defaultRegType addr = function let store = Store (srcMem, ty, addr, expr) Def (dstMem, store) |> Some | LowUIR.Jmp (expr) -> - let label = translateLabel addr expr + let label = translateLabel addr expr.E let jmp = IntraJmp label Jmp jmp |> Some | LowUIR.CJmp (expr, label1, label2) -> let expr = translateExpr expr - let label1 = translateLabel addr label1 - let label2 = translateLabel addr label2 + let label1 = translateLabel addr label1.E + let label2 = translateLabel addr label2.E let jmp = IntraCJmp (expr, label1, label2) Jmp jmp |> Some - | LowUIR.InterJmp (_, expr, _) -> + | LowUIR.InterJmp (expr, _) -> let expr = translateExpr expr let jmp = InterJmp (expr) Jmp jmp |> Some - | LowUIR.InterCJmp (expr1, _, expr2, expr3) -> + | LowUIR.InterCJmp (expr1, expr2, expr3) -> let expr1 = translateExpr expr1 let expr2 = translateExpr expr2 let expr3 = translateExpr expr3 diff --git a/src/BinIR/SSA.Pp.fs b/src/BinIR/SSA.Pp.fs index c3fe7504..c1c94831 100644 --- a/src/BinIR/SSA.Pp.fs +++ b/src/BinIR/SSA.Pp.fs @@ -58,12 +58,14 @@ let rec private expToStringAux expr (sb: StringBuilder) = sb.Append (" ") |> ignore expToStringAux e2 sb sb.Append (")") |> ignore - | Load (_endian, typ, e) -> + | Load (v, typ, e) -> + sb.Append (Variable.toString v) |> ignore sb.Append ("[") |> ignore expToStringAux e sb sb.Append ("]:") |> ignore sb.Append (RegType.toString typ) |> ignore - | Store (_, _, addr, e) -> + | Store (v, _, addr, e) -> + sb.Append (Variable.toString v) |> ignore sb.Append ("[") |> ignore expToStringAux addr sb sb.Append (" <- ") |> ignore @@ -97,15 +99,15 @@ let rec private expToStringAux expr (sb: StringBuilder) = sb.Append (")") |> ignore | ReturnVal (addr, ret, _) -> sb.Append ("RetFromFunc(") |> ignore - sb.Append (addr.ToString ("X")) |> ignore + sb.Append (String.u64ToHexNoPrefix addr) |> ignore sb.Append (",") |> ignore - sb.Append (ret.ToString ("X")) |> ignore + sb.Append (String.u64ToHexNoPrefix ret) |> ignore sb.Append (")") |> ignore let private labelToString (addr: Addr, symb) (sb: StringBuilder) = sb.Append (Symbol.getName symb) |> ignore sb.Append (" @ ") |> ignore - sb.Append (addr.ToString ("X")) |> ignore + sb.Append (String.u64ToHexNoPrefix addr) |> ignore let private stmtToStringAux stmt (sb: StringBuilder) = match stmt with diff --git a/src/BinIR/SSA.fs b/src/BinIR/SSA.fs index f4a62a04..06f6d45f 100644 --- a/src/BinIR/SSA.fs +++ b/src/BinIR/SSA.fs @@ -29,16 +29,30 @@ open B2R2.BinIR /// Type representing destination of an assignment. type VariableKind = + /// Register. | RegVar of RegType * RegisterID * string + /// PC. | PCVar of RegType + /// Temporary variables. | TempVar of RegType * int + /// The whole memory as a var (an over-approximated instance). Whenever there + /// is a memory store op, we update MemVar. | MemVar + /// Stack variables. This variable is available only after the SSA promotion, + /// which basically translates every memory load/store expression with a + /// concrete address into either a StackVar or a GlobalVar. + | StackVar of RegType * offset: int + /// Global variables. This variable is available only after the SSA promotion. + | GlobalVar of RegType * Addr with + [] static member toString = function | RegVar (_, _, n) -> n | PCVar (_) -> "PC" | TempVar (_, n) -> "T_" + n.ToString() | MemVar -> "MEM" + | StackVar (_, offset) -> "V_" + offset.ToString () + | GlobalVar (_, addr) -> "G_" + addr.ToString () /// SSA variables always have their own identifier. type Variable = { @@ -46,10 +60,12 @@ type Variable = { mutable Identifier: int } with + [] static member toString ({ Kind = k; Identifier = i }) = VariableKind.toString k + "_" + i.ToString () - static member IsPC ({ Kind = k }) = + [] + static member isPC ({ Kind = k }) = match k with | PCVar (_) -> true | _ -> false @@ -106,10 +122,11 @@ type Expr = /// case). | Undefined of RegType * string - /// Value returned from a function located at the address. The second argument - /// indicates the return address, and the third argument indicates the live - /// definition of previously defined variable. - | ReturnVal of Addr * Addr * Variable + /// Value returned from a function located at the address (fnAddr). The second + /// argument indicates the return address (the fall-through address of the + /// call instruction), and the third argument indicates the live definition of + /// previously defined variable. A fake bbl will contain this expression. + | ReturnVal of fnAddr: Addr * retAddr: Addr * Variable /// IR Label. Since we don't distinguish instruction boundary in SSA level, we /// want to specify where the label comes from. diff --git a/src/BinIR/SideEffect.fs b/src/BinIR/SideEffect.fs index 46007603..551202e9 100644 --- a/src/BinIR/SideEffect.fs +++ b/src/BinIR/SideEffect.fs @@ -24,6 +24,8 @@ namespace B2R2.BinIR +open B2R2.BinIR.LowUIR + /// Side effect kinds. type SideEffect = /// Software breakpoint. @@ -32,14 +34,16 @@ type SideEffect = | ClockCounter /// Memory fence operations, e.g., LFENCE/MFENCE/SFENCE on x86. | Fence - /// Process halt, e.g., HLT on x86. - | Halt - /// Interrupt, e.g., INT on x86. + /// Delay the execution for a while, e.g. HLT, PAUSE on x86. + | Delay + /// Terminate the execution. + | Terminate + /// Asynchronous event triggered by software (e.g. INT on x86) or hardware. | Interrupt of int + /// Synchronous event generated when the execution encounters error condition. + | Exception of string /// Locking, e.g., LOCK prefix on x86. | Lock - /// Give a hint about a spin-wait loop, e.g., PAUSE on x86. - | Pause /// Access CPU details, e.g., CPUID on x86. | ProcessorID /// System call. @@ -52,18 +56,21 @@ type SideEffect = | UnsupportedPrivInstr /// Unsupported FAR branching. | UnsupportedFAR - /// Unsupported processor extension + /// Unsupported processor extension. | UnsupportedExtension + /// External function call. + | ExternalCall of Expr module SideEffect = let toString = function | Breakpoint -> "Breakpoint" | ClockCounter -> "CLK" | Fence -> "Fence" - | Halt -> "Halt" - | Interrupt (n) -> "Int " + n.ToString () + | Delay -> "Delay" + | Terminate -> "Terminate" + | Interrupt (n) -> "Int" + n.ToString () + | Exception s -> "Exception(" + s + ")" | Lock -> "Lock" - | Pause -> "Pause" | ProcessorID -> "PID" | SysCall -> "SysCall" | UndefinedInstr -> "Undef" @@ -71,3 +78,4 @@ module SideEffect = | UnsupportedPrivInstr -> "PrivInstr" | UnsupportedFAR -> "FAR" | UnsupportedExtension -> "CPU extension" + | ExternalCall expr -> "Call " + Expr.toString expr diff --git a/src/BinIR/Stmt.fs b/src/BinIR/Stmt.fs new file mode 100644 index 00000000..82507c7a --- /dev/null +++ b/src/BinIR/Stmt.fs @@ -0,0 +1,251 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.BinIR.LowUIR + +open System +open System.Text +#if HASHCONS +open LanguagePrimitives +#endif +open B2R2 +open B2R2.BinIR + +/// The kind of an InterJmp. Multiple kinds can present for a jump instruction. +[] +type InterJmpKind = + /// The base case, i.e., a simple jump instruction. + | Base = 0 + /// A call to a function. + | IsCall = 1 + /// A return from a function. + | IsRet = 2 + /// An exit, which will terminate the process. + | IsExit = 4 + /// A branch instructino that modifies the operation mode from Thumb to ARM. + | SwitchToARM = 8 + /// A branch instructino that modifies the operation mode from ARM to Thumb. + | SwitchToThumb = 16 + +/// IL Statements. +/// NOTE: You MUST create Expr/Stmt through the AST module. *NEVER* directly +/// construct Expr nor Stmt. +#if ! HASHCONS +#else +[] +#endif +type S = + /// Metadata representing the start of a machine instruction. More + /// specifically, it contains the length of the instruction. There must be a + /// single IMark per a machine instruction. + | ISMark of uint32 + + /// Metadata representing the end of a machine instruction. It contains the + /// length of the current instruction. + | IEMark of uint32 + + /// Metadata representing a label (as in an assembly language). LMark is only + /// valid within a machine instruction. + | LMark of Symbol + + /// This statement puts a value into a register. The first argument is a + /// destination operand, and the second argument is a source operand. The + /// destination operand should have either a Var or a TempVar. + /// + /// Example: [Put(T_1:I32, Load(LE, T_2:I32))] + /// loads a 32-bit value from the address T2, and store the value to the + /// temporary register T1. + | Put of Expr * Expr + + /// This statement stores a value into a memory. The first argument + /// represents the endianness, the second argument is a destination operand, + /// and the third argument is a value to store. + /// + /// Example: Store(LE, T_1:I32, T_2:I32) + /// stores a 32-bit value T_2 into the address T_1 + | Store of Endian * Expr * Expr + + /// This statement represents a jump (unconditional) to an LMark. The first + /// argument specifies the target address. + | Jmp of Expr + + /// This statement represents a conditional jump to an LMark. The first + /// argument specifies a jump condition. If the condition is true, jump to + /// the address specified by the second argument. Otherwise, jump to the + /// address specified by the third argument. + | CJmp of Expr * Expr * Expr + + /// This is an unconditional jump instruction to another instruction. This is + /// an inter-instruction jump unlike Jmp statement. The first argument is the + /// jump target address. + | InterJmp of Expr * InterJmpKind + + /// This is a conditional jump instruction to another instruction. The first + /// argument specifies a jump condition. If the condition is true, change the + /// program counter to jump to the address specified by the second argument. + /// Otherwise, jump to the address specified by the third argument. + | InterCJmp of Expr * Expr * Expr + + /// This represents an instruction with side effects such as a system call. + | SideEffect of SideEffect +#if ! HASHCONS +#else +with + override __.Equals rhs = + match rhs with + | :? S as rhs -> + match __, rhs with + | ISMark len1, ISMark len2 -> len1 = len2 + | IEMark len1, IEMark len2 -> len1 = len2 + | LMark s1, LMark s2 -> s1 = s2 + | Put (dst1, src1), Put (dst2, src2) -> + dst1.Tag = dst2.Tag && src1.Tag = src2.Tag + | Store (n1, addr1, e1), Store (n2, addr2, e2) -> + n1 = n2 && addr1 = addr2 && e1.Tag = e2.Tag + | Jmp (e1), Jmp (e2) -> e1.Tag = e2.Tag + | CJmp (c1, t1, f1), CJmp (c2, t2, f2) -> + c1.Tag = c2.Tag && t1.Tag = t2.Tag && f1.Tag = f2.Tag + | InterJmp (e1, k1), InterJmp (e2, k2) -> e1.Tag = e2.Tag && k1 = k2 + | InterCJmp (c1, t1, f1), InterCJmp (c2, t2, f2) -> + c1.Tag = c2.Tag && t1.Tag = t2.Tag && f1.Tag = f2.Tag + | SideEffect e1, SideEffect e2 -> e1 = e2 + | _ -> false + | _ -> false + + static member inline HashISMark (len: uint32) = len.GetHashCode () + 1 + + static member inline HashIEMark (len: uint32) = 19 * len.GetHashCode () + 2 + + static member inline HashLMark ((s, n): Symbol) = + 19 * (19 * s.GetHashCode () + n) + 3 + + static member inline HashPut (dst: Expr) (src: Expr) = + 19 * (19 * dst.HashKey + src.HashKey) + 4 + + static member inline HashStore (n: Endian) (addr: Expr) (e: Expr) = + 19 * (19 * (19 * int n + addr.HashKey) + e.HashKey) + 5 + + static member inline HashJmp (e: Expr) = + 19 * (19 * e.HashKey + 1) + 6 + + static member inline HashCJmp (cond: Expr) (t: Expr) (f: Expr) = + 19 * (19 * (19 * cond.HashKey + t.HashKey) + f.HashKey) + 7 + + static member inline HashInterJmp (e: Expr) (k: InterJmpKind) = + 19 * (19 * e.HashKey + int k) + 8 + + static member inline HashInterCJmp (cond: Expr) (t: Expr) (f: Expr) = + 19 * (19 * (19 * cond.HashKey + t.HashKey) + f.HashKey) + 9 + + static member inline HashSideEffect (e: SideEffect) = + (19 * hash e) + 10 + + override __.GetHashCode () = + match __ with + | ISMark len -> S.HashISMark len + | IEMark len -> S.HashIEMark len + | LMark s -> S.HashLMark s + | Put (dst, src) -> S.HashPut dst src + | Store (n, addr, e) -> S.HashStore n addr e + | Jmp (e) -> S.HashJmp e + | CJmp (cond, t, f) -> S.HashCJmp cond t f + | InterJmp (e, k) -> S.HashInterJmp e k + | InterCJmp (cond, t, f) -> S.HashInterCJmp cond t f + | SideEffect (e) -> S.HashSideEffect e +#endif + +#if ! HASHCONS +/// When hash-consing is not used, we simply create a wrapper for an AST node. +and [] Stmt = { + /// The actual AST node. + S: S +} +#else +/// Hash-consed Stmt. +and [] Stmt = { + /// The actual AST node. + S: S + /// Unique id. + Tag: uint32 + /// Hash cache. + HashKey: int +} +with + override __.Equals rhs = + match rhs with + | :? Stmt as rhs -> __.Tag = rhs.Tag + | _ -> false + + override __.GetHashCode () = __.HashKey +#endif + +module Stmt = + let appendToString stmt (sb: StringBuilder) = + match stmt.S with + | ISMark (len) -> + sb.Append ("(") |> ignore + sb.Append (len.ToString ()) |> ignore + sb.Append (") {") |> ignore + | IEMark (len) -> + sb.Append ("} // ") |> ignore + sb.Append (len.ToString ()) |> ignore + | LMark lbl -> + sb.Append (":") |> ignore + sb.Append (Symbol.getName lbl) |> ignore + | Put (exp1, exp2) -> + Expr.appendToString exp1 sb + sb.Append (" := ") |> ignore + Expr.appendToString exp2 sb + | Jmp exp -> + sb.Append ("jmp ") |> ignore + Expr.appendToString exp sb + | InterJmp (exp, _) -> + sb.Append ("ijmp ") |> ignore + Expr.appendToString exp sb + | Store (_endian, exp1, exp2) -> + sb.Append ("[") |> ignore + Expr.appendToString exp1 sb + sb.Append ("] := ") |> ignore + Expr.appendToString exp2 sb + | CJmp (cond, t, f) -> + sb.Append ("if ") |> ignore + Expr.appendToString cond sb + sb.Append (" then jmp ") |> ignore + Expr.appendToString t sb + sb.Append (" else jmp ") |> ignore + Expr.appendToString f sb + | InterCJmp (cond, t, f) -> + sb.Append ("if ") |> ignore + Expr.appendToString cond sb + sb.Append (" then ijmp ") |> ignore + Expr.appendToString t sb + sb.Append (" else ijmp ") |> ignore + Expr.appendToString f sb + | SideEffect eff -> + sb.Append ("!!" + SideEffect.toString eff) |> ignore + + let toString stmt = + let sb = new StringBuilder () + appendToString stmt sb + sb.ToString () diff --git a/src/BinIR/UnOpType.fs b/src/BinIR/UnOpType.fs index f4aa9492..df1f497d 100644 --- a/src/BinIR/UnOpType.fs +++ b/src/BinIR/UnOpType.fs @@ -53,4 +53,14 @@ module UnOpType = | UnOpType.FATAN -> "atan" | _ -> raise IllegalASTTypeException + let ofString = function + | "-" -> UnOpType.NEG + | "~" -> UnOpType.NOT + | "sqrt" -> UnOpType.FSQRT + | "cos" -> UnOpType.FCOS + | "sin" -> UnOpType.FSIN + | "tan" -> UnOpType.FTAN + | "atan" -> UnOpType.FATAN + | _ -> raise IllegalASTTypeException + // vim: set tw=80 sts=2 sw=2: diff --git a/src/BinIR/Utils.fs b/src/BinIR/Utils.fs index 41897293..7614ecf7 100644 --- a/src/BinIR/Utils.fs +++ b/src/BinIR/Utils.fs @@ -30,18 +30,3 @@ open B2R2.BinIR.LowUIR let isBranch = function | Jmp _ | CJmp _ | InterJmp _ | InterCJmp _ -> true | ISMark _ | IEMark _ | LMark _ | Put _ | Store _ | SideEffect _ -> false - -/// Does this IR statement halt the execution? -let isHalt = function - | ISMark _ | IEMark _ | LMark _ | Put _ | Store _ -> false - | Jmp _ | CJmp _ | InterJmp _ | InterCJmp _ -> false - | SideEffect effect -> effect = Halt - -/// Is this IR statement a branch statement or does it halt the execution? This -/// is equaivalent to (isBranch || isHalt), but defined separately just for -/// the performance reason. -let isBBEnd = function - | ISMark _ | IEMark _ | LMark _ | Put _ | Store _ -> false - | Jmp _ | CJmp _ | InterJmp _ | InterCJmp _ -> true - | SideEffect effect -> effect = Halt - diff --git a/src/ConcEval/B2R2.ConcEval.fsproj b/src/ConcEval/B2R2.ConcEval.fsproj deleted file mode 100644 index 315b80f5..00000000 --- a/src/ConcEval/B2R2.ConcEval.fsproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - netstandard2.1 - - - - - - - - - - - - - - - - diff --git a/src/ConcEval/EvalState.fs b/src/ConcEval/EvalState.fs deleted file mode 100644 index 580a8933..00000000 --- a/src/ConcEval/EvalState.fs +++ /dev/null @@ -1,220 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.ConcEval - -open B2R2 -open B2R2.BinIR - -type Context () = - /// The current index of the statement to evaluate within the scope of a - /// machine instruction. This index behaves like a PC for statements of an - /// instruction. - member val StmtIdx = 0 with get, set - - /// The current program counter. - member val PC: Addr = 0UL with get, set - - /// Store named register values. - member val Registers = Variables() with get - - /// Store temporary variable values. - member val Temporaries = Variables() with get - - /// Store labels and their corresponding statement indices. - member val Labels = Labels () with get - - /// Architecture mode. - member val Mode = ArchOperationMode.NoMode with get, set - -type EvalCallBacks () = - /// Per-instruction handler. - member val PerInstrHandler: EvalState -> EvalState = - fun st -> st with get, set - - /// Memory load event handler. - member val LoadEventHandler: Addr -> Addr -> BitVector -> unit = - fun _ _ _ -> () with get, set - - /// Memory store event handler. - member val StoreEventHandler: Addr -> Addr -> BitVector -> unit = - fun _ _ _ -> () with get, set - - /// Put event handler. The first parameter is PC, and the second is the value - /// that is put to the destination. - member val PutEventHandler: Addr -> EvalValue -> unit = - fun _ _ -> () with get, set - - /// Side-effect event handler. - member val SideEffectEventHandler: SideEffect -> EvalState -> EvalState = - fun _ st -> st with get, set - - /// Statement evaluation event handler. - member val StmtEvalEventHandler: LowUIR.Stmt -> unit = - fun _ -> () with get, set - - member __.OnInstr st = __.PerInstrHandler st - - member __.OnLoad pc addr v = __.LoadEventHandler pc addr v - - member __.OnStore pc addr v = __.StoreEventHandler pc addr v - - member __.OnPut pc v = __.PutEventHandler pc v - - member __.OnSideEffect eff st = __.SideEffectEventHandler eff st - - member __.OnStmtEval stmt = __.StmtEvalEventHandler stmt - -/// The main evaluation state that will be updated by evaluating every statement -/// encountered during the course of execution. -and EvalState (?reader, ?ignoreundef) = - /// Memory reader. - let reader = defaultArg reader (fun _ _ -> None) - - /// The current thread ID. We use thread IDs starting from zero. We assign new - /// thread IDs by incrementing it by one at a time. The first thread is 0, the - /// second is 1, and so on. - member val ThreadId = 0 with get, set - - /// Current PC. - member __.PC - with get() = __.Contexts.[__.ThreadId].PC - and set(addr) = __.Contexts.[__.ThreadId].PC <- addr - - /// Per-thread context. - member val Contexts: Context [] = [||] with get, set - - /// Memory. - member val Memory = Memory (Reader = reader) with get - - /// Callback functions. - member val Callbacks = EvalCallBacks () with get - - /// Indicate whether to terminate the current instruction or not. This flag is - /// set to true when we encounter an ISMark within a block. In other words, we - /// should proceed to the next instruction if this flag is set to true. - member val TerminateInstr = false with get, set - - /// Whether to ignore statements that cannot be evaluated due to undef values. - /// This is particularly useful to quickly check some constants. - member val IgnoreUndef = defaultArg ignoreundef false with get - - /// Prepare the initial context of the given thread id (tid). This function - /// will set the current thread to be tid. - static member PrepareContext (st: EvalState) tid pc regs = - let st = EvalState.ContextSwitch tid st - let st = EvalState.SetPC st pc - regs |> List.fold (fun st (r, v) -> EvalState.SetReg st r v) st - - /// Get the context of a specific thread. - static member inline GetContext (st: EvalState) tid = - st.Contexts.[tid] - - /// Get the current context of the current thread. - static member inline GetCurrentContext (st: EvalState) = - st.Contexts.[st.ThreadId] - - /// Thread context switch. If the given thread ID does not exist, we create a - /// new context for it. - static member ContextSwitch tid (st: EvalState) = - st.ThreadId <- tid - if Array.length st.Contexts <= tid then - st.Contexts <- Array.append st.Contexts [| Context () |] - else () - st - - /// Update the current statement index to be the next (current + 1) statement. - static member NextStmt (st: EvalState) = - st.Contexts.[st.ThreadId].StmtIdx <- st.Contexts.[st.ThreadId].StmtIdx + 1 - st - - /// Stop evaluating further statements of the current instruction, and move on - /// the next instruction. - static member AbortInstr (st: EvalState) = - st.TerminateInstr <- true - EvalState.NextStmt st - - /// Start evaluating the instruction. - static member StartInstr (st: EvalState) pc = - st.TerminateInstr <- false - EvalState.SetPC st pc - - /// Should we stop evaluating further statements of the current instruction, - /// and move on to the next instruction? - static member IsInstrTerminated (st: EvalState) = - st.TerminateInstr - - /// Get the value of the given temporary variable. - static member GetTmp (st: EvalState) n = - st.Contexts.[st.ThreadId].Temporaries.Get (n) - - /// Set the value for the given temporary variable. - static member SetTmp (st: EvalState) n v = - st.Contexts.[st.ThreadId].Temporaries.Set n v - st - - /// Get the value of the given register. - static member GetReg (st: EvalState) r = - st.Contexts.[st.ThreadId].Registers.Get r - - /// Set the value for the given register. - static member SetReg (st: EvalState) r v = - st.Contexts.[st.ThreadId].Registers.Set r v - st - - /// Get the program counter (PC). - static member GetPC (st: EvalState) = - st.PC - - /// Set the program counter (PC). - static member SetPC (st: EvalState) addr = - st.PC <- addr - st - - /// Go to the statement of the given label. - static member GoToLabel (st: EvalState) lbl = - st.Contexts.[st.ThreadId].StmtIdx <- - st.Contexts.[st.ThreadId].Labels.Index lbl - st - - /// Get ready for block-level evaluation (evalBlock). - static member PrepareBlockEval stmts (st: EvalState) = - st.Contexts.[st.ThreadId].Labels.Update stmts - st.Contexts.[st.ThreadId].StmtIdx <- 0 - st - - /// Get the current architecture operation mode. - static member GetMode (st: EvalState) = - st.Contexts.[st.ThreadId].Mode - - /// Set the architecture operation mode. - static member SetMode (st: EvalState) mode = - st.Contexts.[st.ThreadId].Mode <- mode - st - - /// Delete temporary states variables and get ready for evaluating the next - /// block of isntructions. - static member CleanUp (st: EvalState) = - st.Contexts.[st.ThreadId].Temporaries.Clear () - st diff --git a/src/ConcEval/Evaluator.fs b/src/ConcEval/Evaluator.fs deleted file mode 100644 index e3b33155..00000000 --- a/src/ConcEval/Evaluator.fs +++ /dev/null @@ -1,217 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -/// ConcEval is a concrete evaluation module for LowUIR. -module B2R2.ConcEval.Evaluator - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.LowUIR - -let private tr = BitVector.one 1 - -let private map1 fn p1 = function - | Undef -> raise UndefExpException - | Def bv -> Def (fn bv p1) - -let private map2 fn p1 p2 = function - | Undef -> raise UndefExpException - | Def bv -> Def (fn bv p1 p2) - -let private unwrap = function - | Undef -> raise UndefExpException - | Def bv -> bv - -let rec evalConcrete st e = - match e with - | Num n -> Def n - | Var (_, n, _, _) -> EvalState.GetReg st n - | PCVar (t, _) -> BitVector.ofUInt64 st.PC t |> Def - | TempVar (_, n) -> EvalState.GetTmp st n - | UnOp (t, e, _, _) -> evalUnOp st e t |> Def - | BinOp (t, _, e1, e2, _, _) -> evalBinOp st e1 e2 t |> Def - | RelOp (t, e1, e2, _, _) -> evalRelOp st e1 e2 t |> Def - | Load (endian, t, addr, _, _) -> evalLoad st endian t addr |> Def - | Ite (cond, e1, e2, _, _) -> evalIte st cond e1 e2 - | Cast (kind, t, e, _, _) -> evalCast st t e kind - | Extract (e, t, p, _, _) -> evalConcrete st e |> map2 BitVector.extract t p - | Undefined (_) -> Undef - | _ -> raise InvalidExprException - -and private evalLoad st endian t addr = - let pc = st.PC - let addr = evalConcrete st addr |> unwrap |> BitVector.toUInt64 - let v = st.Memory.Read pc addr endian t - st.Callbacks.OnLoad pc addr v - v - -and private evalIte st cond e1 e2 = - let cond = evalConcrete st cond |> unwrap - if cond = tr then evalConcrete st e1 else evalConcrete st e2 - -and private evalBinOpConc st e1 e2 fn = - let e1 = evalConcrete st e1 |> unwrap - let e2 = evalConcrete st e2 |> unwrap - fn e1 e2 - -and private evalUnOpConc st e fn = evalConcrete st e |> unwrap |> fn - -and private evalCast st t e = function -| CastKind.SignExt -> evalConcrete st e |> map1 BitVector.sext t -| CastKind.ZeroExt -> evalConcrete st e |> map1 BitVector.zext t -| CastKind.FloatExt -> evalConcrete st e |> map1 BitVector.fext t -| CastKind.IntToFloat -> evalConcrete st e |> map1 BitVector.itof t -| CastKind.FtoICeil -> evalConcrete st e |> map1 BitVector.ftoiceil t -| CastKind.FtoIFloor -> evalConcrete st e |> map1 BitVector.ftoifloor t -| CastKind.FtoIRound -> evalConcrete st e |> map1 BitVector.ftoiround t -| CastKind.FtoITrunc -> evalConcrete st e |> map1 BitVector.ftoitrunc t -| _ -> raise IllegalASTTypeException - -and private evalUnOp st e = function - | UnOpType.NEG -> evalUnOpConc st e BitVector.neg - | UnOpType.NOT -> evalUnOpConc st e BitVector.bnot - | UnOpType.FSQRT -> evalUnOpConc st e BitVector.fsqrt - | UnOpType.FCOS -> evalUnOpConc st e BitVector.fcos - | UnOpType.FSIN -> evalUnOpConc st e BitVector.fsin - | UnOpType.FTAN -> evalUnOpConc st e BitVector.ftan - | UnOpType.FATAN -> evalUnOpConc st e BitVector.fatan - | _ -> raise IllegalASTTypeException - -and private evalBinOp st e1 e2 = function - | BinOpType.ADD -> evalBinOpConc st e1 e2 BitVector.add - | BinOpType.SUB -> evalBinOpConc st e1 e2 BitVector.sub - | BinOpType.MUL -> evalBinOpConc st e1 e2 BitVector.mul - | BinOpType.DIV -> evalBinOpConc st e1 e2 BitVector.div - | BinOpType.SDIV -> evalBinOpConc st e1 e2 BitVector.sdiv - | BinOpType.MOD -> evalBinOpConc st e1 e2 BitVector.modulo - | BinOpType.SMOD -> evalBinOpConc st e1 e2 BitVector.smodulo - | BinOpType.SHL -> evalBinOpConc st e1 e2 BitVector.shl - | BinOpType.SAR -> evalBinOpConc st e1 e2 BitVector.sar - | BinOpType.SHR -> evalBinOpConc st e1 e2 BitVector.shr - | BinOpType.AND -> evalBinOpConc st e1 e2 BitVector.band - | BinOpType.OR -> evalBinOpConc st e1 e2 BitVector.bor - | BinOpType.XOR -> evalBinOpConc st e1 e2 BitVector.bxor - | BinOpType.CONCAT -> evalBinOpConc st e1 e2 BitVector.concat - | BinOpType.FADD -> evalBinOpConc st e1 e2 BitVector.fadd - | BinOpType.FSUB -> evalBinOpConc st e1 e2 BitVector.fsub - | BinOpType.FMUL -> evalBinOpConc st e1 e2 BitVector.fmul - | BinOpType.FDIV -> evalBinOpConc st e1 e2 BitVector.fdiv - | BinOpType.FPOW -> evalBinOpConc st e1 e2 BitVector.fpow - | BinOpType.FLOG -> evalBinOpConc st e1 e2 BitVector.flog - | _ -> raise IllegalASTTypeException - -and private evalRelOp st e1 e2 = function - | RelOpType.EQ -> evalBinOpConc st e1 e2 BitVector.eq - | RelOpType.NEQ -> evalBinOpConc st e1 e2 BitVector.neq - | RelOpType.GT -> evalBinOpConc st e1 e2 BitVector.gt - | RelOpType.GE -> evalBinOpConc st e1 e2 BitVector.ge - | RelOpType.SGT -> evalBinOpConc st e1 e2 BitVector.sgt - | RelOpType.SGE -> evalBinOpConc st e1 e2 BitVector.sge - | RelOpType.LT -> evalBinOpConc st e1 e2 BitVector.lt - | RelOpType.LE -> evalBinOpConc st e1 e2 BitVector.le - | RelOpType.SLT -> evalBinOpConc st e1 e2 BitVector.slt - | RelOpType.SLE -> evalBinOpConc st e1 e2 BitVector.sle - | RelOpType.FLT -> evalBinOpConc st e1 e2 BitVector.flt - | RelOpType.FLE -> evalBinOpConc st e1 e2 BitVector.fle - | RelOpType.FGT -> evalBinOpConc st e1 e2 BitVector.fgt - | RelOpType.FGE -> evalBinOpConc st e1 e2 BitVector.fge - | _ -> raise IllegalASTTypeException - -let private evalPut st lhs rhs = - try - let v = evalConcrete st rhs - st.Callbacks.OnPut st.PC v - match lhs with - | Var (_, n, _, _) -> EvalState.SetReg st n v - | PCVar (_) -> unwrap v |> BitVector.toUInt64 |> EvalState.SetPC st - | TempVar (_, n) -> EvalState.SetTmp st n v - | _ -> raise InvalidExprException - with UndefExpException -> - st (* Do not store undefined value *) - -let private evalStore st endian addr v = - let addr = evalConcrete st addr |> unwrap |> BitVector.toUInt64 - let v = evalConcrete st v |> unwrap - st.Callbacks.OnStore st.PC addr v - st.Memory.Write addr v endian - st - -let private evalJmp st target = - match target with - | Name n -> EvalState.GoToLabel st n - | _ -> raise InvalidExprException - -let private evalCJmp st cond t f = - let cond = evalConcrete st cond |> unwrap - if cond = tr then evalJmp st t else evalJmp st f - -let private evalIntCJmp st cond pc t f = - let cond = evalConcrete st cond |> unwrap - evalPut st pc (if cond = tr then t else f) - -let evalStmt st = function - | ISMark (pc, _) -> EvalState.StartInstr st pc |> EvalState.NextStmt - | IEMark (addr) -> EvalState.SetPC st addr |> EvalState.AbortInstr - | LMark _ -> EvalState.NextStmt st - | Put (lhs, rhs) -> evalPut st lhs rhs |> EvalState.NextStmt - | Store (e, addr, v) -> evalStore st e addr v |> EvalState.NextStmt - | Jmp target -> evalJmp st target - | CJmp (cond, t, f) -> evalCJmp st cond t f - | InterJmp (pc, target, _) -> evalPut st pc target |> EvalState.AbortInstr - | InterCJmp (c, pc, t, f) -> evalIntCJmp st c pc t f |> EvalState.AbortInstr - | SideEffect eff -> st.Callbacks.OnSideEffect eff st - -let rec internal gotoNextInstr stmts st = - let ctxt = EvalState.GetCurrentContext st - let idx = ctxt.StmtIdx - if EvalState.IsInstrTerminated st && Array.length stmts > idx && idx >= 0 then - match stmts.[idx] with - | ISMark (pc, _) -> EvalState.StartInstr st pc - | _ -> gotoNextInstr stmts (EvalState.NextStmt st) - else st - -let internal tryEvaluate stmt st = - try evalStmt st stmt with - | UndefExpException - | InvalidMemException -> - if st.IgnoreUndef then EvalState.NextStmt st - else raise UndefExpException - -let rec internal evalLoop stmts st = - let ctxt = EvalState.GetCurrentContext st - let idx = ctxt.StmtIdx - let st = if idx = 0 then st.Callbacks.OnInstr st else st - if Array.length stmts > idx && idx >= 0 then - let stmt = stmts.[idx] - st.Callbacks.OnStmtEval stmt - evalLoop stmts (tryEvaluate stmt st |> gotoNextInstr stmts) - else st - -/// Evaluate a block of statements. The block may represent a machine -/// instruction, or a basic block. -let evalBlock (st: EvalState) tid stmts = - if st.ThreadId <> tid then EvalState.ContextSwitch tid st else st - |> EvalState.PrepareBlockEval stmts - |> evalLoop stmts - |> EvalState.CleanUp diff --git a/src/ConcEval/Variables.fs b/src/ConcEval/Variables.fs deleted file mode 100644 index d3de2d1c..00000000 --- a/src/ConcEval/Variables.fs +++ /dev/null @@ -1,43 +0,0 @@ - -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.ConcEval - -open System.Collections.Generic - -type Variables<'Key when 'Key: equality> () = - let vars = Dictionary<'Key, EvalValue> () - - member __.Get k = - let found, v = vars.TryGetValue (k) - if found then v else Undef - - member __.Set k v = vars.[k] <- v - - member __.Clear () = vars.Clear () - - member __.Count () = vars.Count - - member __.ToSeq () = vars |> Seq.map (fun (KeyValue(k,v)) -> k, v) diff --git a/src/Core.Tests/AddrRange.Tests.fs b/src/Core.Tests/AddrRange.Tests.fs index 92a3b6e0..d03926a8 100644 --- a/src/Core.Tests/AddrRange.Tests.fs +++ b/src/Core.Tests/AddrRange.Tests.fs @@ -33,18 +33,18 @@ type AddrRangeTests () = [] [)>] member __.``Overlap Test 1`` () = - let r1 = AddrRange (100UL, 200UL) - let r2 = AddrRange (200UL, 300UL) + let r1 = AddrRange (100UL, 199UL) + let r2 = AddrRange (200UL, 299UL) let m = ARMap.empty let m = ARMap.add r1 1 m let m = ARMap.add r2 2 m - ARMap.addRange 99UL 101UL 3 m |> ignore + ARMap.addRange 99UL 100UL 3 m |> ignore [] [)>] member __.``Overlap Test 2`` () = - let r1 = AddrRange (100UL, 200UL) - let r2 = AddrRange (200UL, 300UL) + let r1 = AddrRange (100UL, 199UL) + let r2 = AddrRange (200UL, 299UL) let m = ARMap.empty let m = ARMap.add r1 1 m let m = ARMap.add r2 2 m @@ -55,14 +55,14 @@ type AddrRangeTests () = let size = 0x10UL let num = 0x100UL let sprayRange m i = - let r = AddrRange (size * i, size * (i + 1UL)) + let r = AddrRange (size * i, size * (i + 1UL) - 1UL) ARMap.add r None m - let r = AddrRange (0x150UL, 0x180UL) + let r = AddrRange (0x150UL, 0x17FUL) let l = [ 0UL .. num - 1UL ] |> List.fold sprayRange ARMap.empty |> ARMap.getOverlaps r - let n1 = (r.Max - r.Min) / size + let n1 = r.Count / size let n2 = uint64 <| List.length l Assert.AreEqual (n1, n2) @@ -75,8 +75,8 @@ type AddrRangeTests () = [] member __.``Count Test2 `` () = - let r1 = AddrRange (100UL, 200UL) - let r2 = AddrRange (50UL, 100UL) + let r1 = AddrRange (100UL, 199UL) + let r2 = AddrRange (50UL, 99UL) let m = ARMap.empty let m = ARMap.add r1 1 m let m = ARMap.add r2 2 m @@ -84,8 +84,8 @@ type AddrRangeTests () = [] member __.``Count Test3 `` () = - let r1 = AddrRange (100UL, 200UL) - let r2 = AddrRange (200UL, 300UL) + let r1 = AddrRange (100UL, 199UL) + let r2 = AddrRange (200UL, 299UL) let m = ARMap.empty let m = ARMap.add r1 1 m let m = ARMap.add r2 2 m @@ -93,11 +93,23 @@ type AddrRangeTests () = [] member __.``Count Test4 `` () = - let r1 = AddrRange (100UL, 200UL) - let r2 = AddrRange (200UL, 300UL) - let r3 = AddrRange (50UL, 100UL) + let r1 = AddrRange (100UL, 199UL) + let r2 = AddrRange (200UL, 299UL) + let r3 = AddrRange (50UL, 99UL) let m = ARMap.empty let m = ARMap.add r1 1 m let m = ARMap.add r2 2 m let m = ARMap.add r3 3 m Assert.AreEqual (ARMap.count m, 3) + + [] + member __.``Singleton Test1`` () = + let r1 = AddrRange (0UL) + let r2 = AddrRange (1UL) + let r3 = AddrRange (2UL) + let m = ARMap.empty + let m = ARMap.add r1 1 m + let m = ARMap.add r2 2 m + let m = ARMap.add r3 3 m + Assert.AreEqual (3, ARMap.count m) + Assert.AreEqual (2, ARMap.findByAddr 1UL m) diff --git a/src/Core.Tests/B2R2.Core.Tests.fsproj b/src/Core.Tests/B2R2.Core.Tests.fsproj index 83bc7d8a..1e8ecc74 100644 --- a/src/Core.Tests/B2R2.Core.Tests.fsproj +++ b/src/Core.Tests/B2R2.Core.Tests.fsproj @@ -1,25 +1,25 @@ - + - netcoreapp3.0 + net5.0 false - + + - - - - + + + diff --git a/src/Core.Tests/BitVector.Tests.fs b/src/Core.Tests/BitVector.Tests.fs index 331baa0f..30f28f35 100644 --- a/src/Core.Tests/BitVector.Tests.fs +++ b/src/Core.Tests/BitVector.Tests.fs @@ -26,7 +26,6 @@ namespace B2R2.Core.Tests open System open Microsoft.VisualStudio.TestTools.UnitTesting - open B2R2 [] @@ -35,7 +34,7 @@ type BitVectorTests () = [] member __.``Equality`` () = Assert.AreEqual (BitVector.ofInt32 5l 16, - BitVector.ofUBInt 5I 16) + BitVector.ofBInt 5I 16) Assert.AreEqual (BitVector.ofUInt32 5ul 16, BitVector.ofInt64 5L 16) Assert.AreEqual (BitVector.ofInt64 -5L 128, @@ -73,75 +72,75 @@ type BitVectorTests () = [] member __.``Basic Arithmetic 2`` () = - let e1 = BitVector.ofUBInt 10I 8 - let e2 = BitVector.ofUBInt 3I 8 + let e1 = BitVector.ofBInt 10I 8 + let e2 = BitVector.ofBInt 3I 8 let n1 = BitVector.ofUInt64 (uint8 -10 |> uint64) 8 let n2 = BitVector.ofUInt64 (uint8 -3 |> uint64) 8 - Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0xD:I8") + Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0xd:I8") Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0x7:I8") - Assert.AreEqual (BitVector.toString <| BitVector.mul e1 e2, "0x1E:I8") + Assert.AreEqual (BitVector.toString <| BitVector.mul e1 e2, "0x1e:I8") Assert.AreEqual (BitVector.toString <| BitVector.div e1 e2, "0x3:I8") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv e1 n2, "0xFD:I8") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 e2, "0xFD:I8") - let e1 = BitVector.ofUBInt 10000I 16 - let e2 = BitVector.ofUBInt 3000I 16 + Assert.AreEqual (BitVector.toString <| BitVector.sdiv e1 n2, "0xfd:I8") + Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 e2, "0xfd:I8") + let e1 = BitVector.ofBInt 10000I 16 + let e2 = BitVector.ofBInt 3000I 16 let n1 = BitVector.ofInt32 (-10000l) 16 let n2 = BitVector.ofInt32 (-3000l) 16 - Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0x32C8:I16") - Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0x1B58:I16") - Assert.AreEqual (BitVector.toString <| BitVector.mul e1 e2, "0xC380:I16") + Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0x32c8:I16") + Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0x1b58:I16") + Assert.AreEqual (BitVector.toString <| BitVector.mul e1 e2, "0xc380:I16") Assert.AreEqual (BitVector.toString <| BitVector.div e1 e2, "0x3:I16") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv e1 n2, "0xFFFD:I16") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 e2, "0xFFFD:I16") + Assert.AreEqual (BitVector.toString <| BitVector.sdiv e1 n2, "0xfffd:I16") + Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 e2, "0xfffd:I16") [] member __.``Basic Arithmetic 3`` () = - let e1 = BitVector.ofUBInt 100000I 32 - let e2 = BitVector.ofUBInt 30000I 32 + let e1 = BitVector.ofBInt 100000I 32 + let e2 = BitVector.ofBInt 30000I 32 let n1 = BitVector.ofInt32 (-100000l) 32 let n2 = BitVector.ofInt32 (-30000l) 32 - Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0x1FBD0:I32") + Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0x1fbd0:I32") Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0x11170:I32") Assert.AreEqual (BitVector.toString <| BitVector.mul e1 e2, - "0xB2D05E00:I32") + "0xb2d05e00:I32") Assert.AreEqual (BitVector.toString <| BitVector.div e1 e2, "0x3:I32") Assert.AreEqual (BitVector.toString <| BitVector.sdiv e1 n2, - "0xFFFFFFFD:I32") + "0xfffffffd:I32") Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 e2, - "0xFFFFFFFD:I32") - let e1 = BitVector.ofUBInt 1000000I 64 - let e2 = BitVector.ofUBInt 300000I 64 + "0xfffffffd:I32") + let e1 = BitVector.ofBInt 1000000I 64 + let e2 = BitVector.ofBInt 300000I 64 let n1 = BitVector.ofInt64 (-1000000L) 64 let n2 = BitVector.ofInt64 (-300000L) 64 - Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0x13D620:I64") - Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0xAAE60:I64") + Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0x13d620:I64") + Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0xaae60:I64") Assert.AreEqual (BitVector.toString <| BitVector.mul e1 e2, - "0x45D964B800:I64") + "0x45d964b800:I64") Assert.AreEqual (BitVector.toString <| BitVector.div e1 e2, "0x3:I64") Assert.AreEqual (BitVector.toString <| BitVector.sdiv e1 n2, - "0xFFFFFFFFFFFFFFFD:I64") + "0xfffffffffffffffd:I64") Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 e2, - "0xFFFFFFFFFFFFFFFD:I64") + "0xfffffffffffffffd:I64") [] member __.``Basic Arithmetic 4`` () = - let e1 = BitVector.ofUBInt 10000000I 128 - let e2 = BitVector.ofUBInt 3000000I 128 + let e1 = BitVector.ofBInt 10000000I 128 + let e2 = BitVector.ofBInt 3000000I 128 let n1 = BitVector.ofInt64 (-10000000L) 128 let n2 = BitVector.ofInt64 (-3000000L) 128 - Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0xC65D40:I128") - Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0x6ACFC0:I128") + Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0xc65d40:I128") + Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0x6acfc0:I128") Assert.AreEqual (BitVector.toString <| BitVector.mul e1 e2, - "0x1B48EB57E000:I128") + "0x1b48eb57e000:I128") Assert.AreEqual (BitVector.toString <| BitVector.div e1 e2, "0x3:I128") Assert.AreEqual (BitVector.toString <| BitVector.sdiv e1 n2, - "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD:I128") + "0xfffffffffffffffffffffffffffffffd:I128") Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 e2, - "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD:I128") + "0xfffffffffffffffffffffffffffffffd:I128") let e1 = BitVector.ofInt32 0xDFFFFDEA 32 let e2 = BitVector.ofInt32 1 32 Assert.AreEqual (BitVector.toString <| BitVector.sar e1 e2, - "0xEFFFFEF5:I32") + "0xeffffef5:I32") [] member __.``Basic Arithmetic 5`` () = @@ -153,12 +152,12 @@ type BitVectorTests () = let n1 = BitVector.ofInt64 (-4L) 64 let n2 = BitVector.ofInt64 (2L) 64 Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 n2, - "0xFFFFFFFFFFFFFFFE:I64") + "0xfffffffffffffffe:I64") Assert.AreEqual (BitVector.toString <| BitVector.sdiv n2 n1, "0x0:I64") let n1 = BitVector.ofInt64 (4L) 64 let n2 = BitVector.ofInt64 (-2L) 64 Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 n2, - "0xFFFFFFFFFFFFFFFE:I64") + "0xfffffffffffffffe:I64") Assert.AreEqual (BitVector.toString <| BitVector.sdiv n2 n1, "0x0:I64") [] @@ -170,18 +169,18 @@ type BitVectorTests () = let n4 = BitVector.ofInt64 (-1L) 32 Assert.AreEqual (BitVector.toString <| BitVector.shl n1 n2, "0x80000000:I32") Assert.AreEqual (BitVector.toString <| BitVector.shl n1 n3, "0x0:I32") - Assert.AreEqual (BitVector.toString <| BitVector.shl n4 n1, "0xFFFFFFFE:I32") + Assert.AreEqual (BitVector.toString <| BitVector.shl n4 n1, "0xfffffffe:I32") Assert.AreEqual (BitVector.toString <| BitVector.shl n4 n2, "0x80000000:I32") Assert.AreEqual (BitVector.toString <| BitVector.shr n1 n2, "0x0:I32") Assert.AreEqual (BitVector.toString <| BitVector.shr n4 n2, "0x1:I32") Assert.AreEqual (BitVector.toString <| BitVector.shr n4 n3, "0x0:I32") - Assert.AreEqual (BitVector.toString <| BitVector.shr n4 n1, "0x7FFFFFFF:I32") + Assert.AreEqual (BitVector.toString <| BitVector.shr n4 n1, "0x7fffffff:I32") Assert.AreEqual (BitVector.toString <| BitVector.sar n1 n2, "0x0:I32") - Assert.AreEqual (BitVector.toString <| BitVector.sar n4 n3, "0xFFFFFFFF:I32") - Assert.AreEqual (BitVector.toString <| BitVector.sar n4 n1, "0xFFFFFFFF:I32") - Assert.AreEqual (BitVector.toString <| BitVector.sar n4 n3, "0xFFFFFFFF:I32") + Assert.AreEqual (BitVector.toString <| BitVector.sar n4 n3, "0xffffffff:I32") + Assert.AreEqual (BitVector.toString <| BitVector.sar n4 n1, "0xffffffff:I32") + Assert.AreEqual (BitVector.toString <| BitVector.sar n4 n3, "0xffffffff:I32") [] member __.``Basic Arithmetic 7`` () = @@ -226,7 +225,7 @@ type BitVectorTests () = let n1 = BitVector.ofUInt32 5ul 32 let n2 = BitVector.ofInt32 -3l 32 Assert.AreEqual (BitVector.toString <| BitVector.modulo n1 n2, "0x5:I32") - let n1 = BitVector.ofUBInt 5I 256 + let n1 = BitVector.ofBInt 5I 256 let n2 = BitVector.ofInt64 -3L 256 Assert.AreEqual (BitVector.toString <| BitVector.modulo n1 n2, "0x5:I256") @@ -235,121 +234,128 @@ type BitVectorTests () = // Added for signed modulo bug test let n1 = BitVector.ofUInt32 5ul 32 let n2 = BitVector.ofInt32 3l 32 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 2l 32) - let n1 = BitVector.ofUBInt 5I 256 + Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 2 32) + let n1 = BitVector.ofBInt 5I 256 let n2 = BitVector.ofInt64 3L 256 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 2l 256) + Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 2 256) let n1 = BitVector.ofUInt32 5ul 32 let n2 = BitVector.ofInt32 -3l 32 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 -1l 32) - let n1 = BitVector.ofUBInt 5I 256 + Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 2 32) + let n1 = BitVector.ofBInt 5I 256 let n2 = BitVector.ofInt64 -3L 256 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 -1l 256) + Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 2 256) let n1 = BitVector.ofInt32 -5l 32 let n2 = BitVector.ofInt32 -3l 32 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 -2l 32) - let n1 = BitVector.ofUBInt -5I 256 + Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 -2 32) + let n1 = BitVector.ofBInt -5I 256 let n2 = BitVector.ofInt64 -3L 256 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 -2l 256) + Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 -2 256) let n1 = BitVector.ofInt32 -5l 32 let n2 = BitVector.ofInt32 3l 32 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 1l 32) - let n1 = BitVector.ofUBInt -5I 256 + Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 -2 32) + let n1 = BitVector.ofBInt -5I 256 let n2 = BitVector.ofInt64 3L 256 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 1l 256) + Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 -2 256) // zero value test let n1 = BitVector.ofUInt32 6ul 32 let n2 = BitVector.ofInt32 3l 32 Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 32) - let n1 = BitVector.ofUBInt 6I 256 + let n1 = BitVector.ofBInt 6I 256 let n2 = BitVector.ofInt64 3L 256 Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 256) let n1 = BitVector.ofUInt32 6ul 32 let n2 = BitVector.ofInt32 -3l 32 Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 32) - let n1 = BitVector.ofUBInt 6I 256 + let n1 = BitVector.ofBInt 6I 256 let n2 = BitVector.ofInt64 -3L 256 Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 256) let n1 = BitVector.ofInt32 -6l 32 let n2 = BitVector.ofInt32 -3l 32 Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 32) - let n1 = BitVector.ofUBInt -6I 256 + let n1 = BitVector.ofBInt -6I 256 let n2 = BitVector.ofInt64 -3L 256 Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 256) let n1 = BitVector.ofInt32 -6l 32 let n2 = BitVector.ofInt32 3l 32 Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 32) - let n1 = BitVector.ofUBInt -6I 256 + let n1 = BitVector.ofBInt -6I 256 let n2 = BitVector.ofInt64 3L 256 Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 256) [] member __.``Logical Operators`` () = - let n1 = BitVector.ofUBInt 100I 32 + let n1 = BitVector.ofBInt 100I 32 let n2 = BitVector.ofInt32 -500l 32 Assert.AreEqual (BitVector.toString <| BitVector.band n1 n2, "0x4:I32") - let n1 = BitVector.ofUBInt 100I 256 + let n1 = BitVector.ofBInt 100I 256 let n2 = BitVector.ofInt32 -500l 256 Assert.AreEqual (BitVector.toString <| BitVector.band n1 n2, "0x4:I256") - let n1 = BitVector.ofUBInt 100I 32 + let n1 = BitVector.ofBInt 100I 32 let n2 = BitVector.ofInt32 -500l 32 Assert.AreEqual (BitVector.toString <| BitVector.bor n1 n2, - "0xFFFFFE6C:I32") - let n1 = BitVector.ofUBInt 100I 256 + "0xfffffe6c:I32") + let n1 = BitVector.ofBInt 100I 256 let n2 = BitVector.ofInt32 -500l 256 Assert.AreEqual (BitVector.bor n1 n2, BitVector.ofInt64 -404L 256) - let n1 = BitVector.ofUBInt 100I 32 + let n1 = BitVector.ofBInt 100I 32 let n2 = BitVector.ofInt32 -500l 32 Assert.AreEqual (BitVector.toString <| BitVector.bxor n1 n2, - "0xFFFFFE68:I32") - let n1 = BitVector.ofUBInt 100I 256 + "0xfffffe68:I32") + let n1 = BitVector.ofBInt 100I 256 let n2 = BitVector.ofInt32 -500l 256 Assert.AreEqual (BitVector.bxor n1 n2, BitVector.ofInt64 -408L 256) [] member __.``Comparison Operators`` () = - let n1 = BitVector.ofUBInt 100I 32 - let n2 = BitVector.ofUBInt 100I 32 + let n1 = BitVector.ofBInt 100I 32 + let n2 = BitVector.ofBInt 100I 32 Assert.AreEqual (BitVector.slt n1 n2, BitVector.zero 1) Assert.AreEqual (BitVector.sle n1 n2, BitVector.one 1) - let n1 = BitVector.ofUBInt 100I 256 - let n2 = BitVector.ofUBInt 100I 256 + let n1 = BitVector.ofBInt 100I 256 + let n2 = BitVector.ofBInt 100I 256 Assert.AreEqual (BitVector.slt n1 n2, BitVector.zero 1) Assert.AreEqual (BitVector.sle n1 n2, BitVector.one 1) - let n1 = BitVector.ofUBInt 100I 32 + let n1 = BitVector.ofBInt 100I 32 let n2 = BitVector.ofInt32 -500l 32 Assert.AreEqual (BitVector.lt n1 n2, BitVector.one 1) Assert.AreEqual (BitVector.le n1 n2, BitVector.one 1) Assert.AreEqual (BitVector.slt n1 n2, BitVector.zero 1) Assert.AreEqual (BitVector.sle n1 n2, BitVector.zero 1) - let n1 = BitVector.ofUBInt 100I 256 + let n1 = BitVector.ofBInt 100I 256 let n2 = BitVector.ofInt32 -500l 256 Assert.AreEqual (BitVector.slt n1 n2, BitVector.zero 1) Assert.AreEqual (BitVector.sle n1 n2, BitVector.zero 1) + let n1 = BitVector.ofInt32 -200 256 + let n2 = BitVector.ofInt32 -500 256 + Assert.AreEqual (BitVector.slt n1 n2, BitVector.zero 1) + Assert.AreEqual (BitVector.sle n1 n2, BitVector.zero 1) + let n1 = BitVector.ofInt32 0x5b 8 + let n2 = BitVector.ofInt32 0x98 8 + Assert.AreEqual (BitVector.sgt n1 n2, BitVector.one 1) [] member __.``Unary Operators`` () = - let n1 = BitVector.ofUBInt 100I 32 - let n2 = BitVector.ofUBInt 0I 16 + let n1 = BitVector.ofBInt 100I 32 + let n2 = BitVector.ofBInt 0I 16 let n3 = BitVector.ofInt32 0xffffffff 32 Assert.AreEqual (BitVector.bnot n1, BitVector.ofInt32 0xffffff9bl 32) Assert.AreEqual (BitVector.bnot n2, BitVector.ofInt32 0xffffl 16) Assert.AreEqual (BitVector.bnot n3, BitVector.ofInt32 0 32) - Assert.AreEqual (BitVector.toString <| BitVector.neg n1, "0xFFFFFF9C:I32") + Assert.AreEqual (BitVector.toString <| BitVector.neg n1, "0xffffff9c:I32") Assert.AreEqual (BitVector.neg n2, BitVector.ofInt32 0l 16) - let n1 = BitVector.ofUBInt 0I 128 + let n1 = BitVector.ofBInt 0I 128 Assert.AreEqual (BitVector.neg n1, BitVector.ofInt32 0l 128) [] member __.``Concatenation Operator`` () = - let e1 = BitVector.ofUBInt 1000I 32 - let e2 = BitVector.ofUBInt 300I 32 + let e1 = BitVector.ofBInt 1000I 32 + let e2 = BitVector.ofBInt 300I 32 Assert.AreEqual (BitVector.toString <| BitVector.concat e1 e2, - "0x3E80000012C:I64") - let e1 = BitVector.ofUBInt 1000I 32 + "0x3e80000012c:I64") + let e1 = BitVector.ofBInt 1000I 32 let e2 = BitVector.ofInt64 -300L 32 Assert.AreEqual (BitVector.toString <| BitVector.concat e1 e2, - "0x3E8FFFFFED4:I64") + "0x3e8fffffed4:I64") [] member __.``Size Extension``() = diff --git a/src/Core.Tests/ByteArray.Tests.fs b/src/Core.Tests/ByteArray.Tests.fs index 8eb42c72..6206d5e1 100644 --- a/src/Core.Tests/ByteArray.Tests.fs +++ b/src/Core.Tests/ByteArray.Tests.fs @@ -35,10 +35,11 @@ type ByteArrayTests () = member __.``ByteArray Test`` () = let hexString = "68656c6c6f" let newArray = ByteArray.ofHexString hexString - CollectionAssert.AreEqual ([| 0x68uy; 0x65uy; 0x6cuy; 0x6cuy; 0x6fuy |], newArray) + let expectation = [| 0x68uy; 0x65uy; 0x6cuy; 0x6cuy; 0x6fuy |] + CollectionAssert.AreEqual (expectation, newArray) let hexString = "68656C6C6F" let newArray = ByteArray.ofHexString hexString - CollectionAssert.AreEqual ([| 0x68uy; 0x65uy; 0x6cuy; 0x6cuy; 0x6fuy |], newArray) + CollectionAssert.AreEqual (expectation, newArray) [] member __.``CString Extraction Test`` () = @@ -58,6 +59,12 @@ type ByteArrayTests () = member __.``Pattern Matching Test`` () = let buf = "hellotexthellotexthellotexthellopencilfsharptesttext"B let pattern = "text"B - let offset = uint64 0 - let indexList = ByteArray.findIdxs offset pattern buf + let indexList = ByteArray.findIdxs 0UL pattern buf Assert.AreEqual([48UL; 23UL; 14UL; 5UL], indexList) + + [] + member __.``Pattern Matching Test 2`` () = + let buf = [| 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy |] + let pattern = [| 0uy; 1uy |] + let indexList = ByteArray.findIdxs 0UL pattern buf + Assert.AreEqual([ 0UL ], indexList) diff --git a/src/Core.Tests/IntervalTree.Tests.fs b/src/Core.Tests/IntervalTree.Tests.fs index be2f4ee4..4d5b69b4 100644 --- a/src/Core.Tests/IntervalTree.Tests.fs +++ b/src/Core.Tests/IntervalTree.Tests.fs @@ -33,22 +33,22 @@ type IntervalTreeTests () = [] member __.``IntervalSet Test tryFindByAddr`` () = - let range1 = AddrRange (0x100UL, 0x200UL) + let range1 = AddrRange (0x100UL, 0x1FFUL) let set = IntervalSet.add range1 IntervalSet.empty Assert.AreEqual (Some range1, IntervalSet.tryFindByAddr 0x100UL set) Assert.AreEqual (Some range1, IntervalSet.tryFindByAddr 0x199UL set) Assert.AreEqual (None, IntervalSet.tryFindByAddr 0x200UL set) Assert.AreEqual (None, IntervalSet.tryFindByAddr 0x99UL set) - let range2 = AddrRange (0x200UL, 0x300UL) + let range2 = AddrRange (0x200UL, 0x2FFUL) let set = IntervalSet.add range2 set Assert.AreEqual (Some range1, IntervalSet.tryFindByAddr 0x199UL set) Assert.AreEqual (Some range2, IntervalSet.tryFindByAddr 0x200UL set) [] member __.``IntervalSet Test contains`` () = - let range1 = AddrRange (0x100UL, 0x200UL) - let range2 = AddrRange (0x200UL, 0x300UL) - let range3 = AddrRange (0x300UL, 0x400UL) + let range1 = AddrRange (0x100UL, 0x1FFUL) + let range2 = AddrRange (0x200UL, 0x2FFUL) + let range3 = AddrRange (0x300UL, 0x3FFUL) let set = IntervalSet.add range1 IntervalSet.empty let set = IntervalSet.add range2 set let set = IntervalSet.add range3 set @@ -74,7 +74,7 @@ type IntervalTreeTests () = let set = IntervalSet.add range2 set let set = IntervalSet.add range3 set let set = IntervalSet.add range4 set - let range5 = AddrRange (0x120UL, 0x121UL) + let range5 = AddrRange (0x120UL, 0x120UL) let overlap1 = [| range4; range1; range2 |] let result1 = IntervalSet.findAll range5 set |> List.toArray CollectionAssert.AreEqual (overlap1, result1) @@ -88,29 +88,115 @@ type IntervalTreeTests () = let range2 = AddrRange (0x300UL, 0x400UL) let set = IntervalSet.add range1 IntervalSet.empty let set = IntervalSet.add range2 set - let range = AddrRange (0x250UL, 0x300UL) + let range = AddrRange (0x250UL, 0x2FFUL) Assert.AreEqual (0, IntervalSet.findAll range set |> List.length) + [] + member __.``IntervalSet Test Non-Overlapping Intervals`` () = + let range1 = AddrRange (0UL, 1UL) + let range2 = AddrRange (2UL, 3UL) + let range3 = AddrRange (4UL, 5UL) + let set = IntervalSet.add range1 IntervalSet.empty + let set = IntervalSet.add range2 set |> IntervalSet.add range3 + Assert.IsTrue (IntervalSet.tryFindByAddr 0UL set |> Option.isSome) + Assert.IsTrue (IntervalSet.tryFindByAddr 1UL set |> Option.isSome) + Assert.IsTrue (IntervalSet.tryFindByAddr 2UL set |> Option.isSome) + Assert.IsTrue (IntervalSet.tryFindByAddr 3UL set |> Option.isSome) + Assert.IsTrue (IntervalSet.tryFindByAddr 4UL set |> Option.isSome) + Assert.IsTrue (IntervalSet.tryFindByAddr 5UL set |> Option.isSome) + Assert.IsTrue (IntervalSet.tryFindByAddr 6UL set |> Option.isNone) + Assert.IsTrue (IntervalSet.containsAddr 0UL set) + Assert.IsTrue (IntervalSet.containsAddr 1UL set) + Assert.IsTrue (IntervalSet.containsAddr 2UL set) + Assert.IsTrue (IntervalSet.containsAddr 3UL set) + Assert.IsTrue (IntervalSet.containsAddr 4UL set) + Assert.IsTrue (IntervalSet.containsAddr 5UL set) + Assert.IsFalse (IntervalSet.containsAddr 6UL set) + Assert.IsTrue (IntervalSet.contains (AddrRange (0UL, 1UL)) set) + Assert.IsTrue (IntervalSet.contains (AddrRange (2UL, 3UL)) set) + Assert.IsTrue (IntervalSet.contains (AddrRange (4UL, 5UL)) set) + Assert.IsFalse (IntervalSet.contains (AddrRange (3UL, 4UL)) set) + Assert.IsFalse (IntervalSet.contains (AddrRange (5UL, 6UL)) set) + Assert.IsFalse (IntervalSet.contains (AddrRange (1UL, 6UL)) set) + + [] + member __.``IntervalSet Test Non-Overlapping Intervals 2`` () = + let range1 = AddrRange (0UL, 1UL) + let range2 = AddrRange (2UL, 3UL) + let range3 = AddrRange (4UL, 5UL) + let set = IntervalSet.add range1 IntervalSet.empty + let set = IntervalSet.add range2 set |> IntervalSet.add range3 + let expected = [| range3; range2 |] + let actual = IntervalSet.findAll (AddrRange (3UL, 4UL)) set |> List.toArray + CollectionAssert.AreEqual (expected, actual) + let expected = [| range2 |] + let actual = IntervalSet.findAll (AddrRange (3UL, 3UL)) set |> List.toArray + CollectionAssert.AreEqual (expected, actual) + let expected = [| range2; range1 |] + let actual = IntervalSet.findAll (AddrRange (0UL, 2UL)) set |> List.toArray + CollectionAssert.AreEqual (expected, actual) + let expected = [| range3; range2; range1 |] + let actual = IntervalSet.findAll (AddrRange (1UL, 9UL)) set |> List.toArray + CollectionAssert.AreEqual (expected, actual) + let actual = IntervalSet.findAll (AddrRange (6UL, 7UL)) set + Assert.IsTrue (List.isEmpty actual) + + [] + member __.``IntervalSet Test Removal`` () = + let range1 = AddrRange (1UL, 2UL) + let range2 = AddrRange (2UL, 3UL) + let range3 = AddrRange (3UL, 4UL) + let set = IntervalSet.add range1 IntervalSet.empty + let set = IntervalSet.add range2 set |> IntervalSet.add range3 + let expected = [| range3; range2; range1 |] + let actual = IntervalSet.findAll (AddrRange (2UL, 3UL)) set |> List.toArray + CollectionAssert.AreEqual (expected, actual) + let removed = IntervalSet.remove range2 set + Assert.IsFalse (IntervalSet.containsAddr 0UL removed) + Assert.IsTrue (IntervalSet.containsAddr 1UL removed) + Assert.IsTrue (IntervalSet.containsAddr 2UL removed) + Assert.IsTrue (IntervalSet.containsAddr 3UL removed) + Assert.IsTrue (IntervalSet.containsAddr 4UL removed) + Assert.IsTrue (IntervalSet.contains (AddrRange (1UL, 2UL)) removed) + Assert.IsTrue (IntervalSet.contains (AddrRange (3UL, 4UL)) removed) + Assert.AreEqual (2, IntervalSet.fold (fun cnt _ -> cnt + 1) 0 removed) + + [] + member __.``IntervalSet Test Removal 2`` () = + let range1 = AddrRange (1UL, 2UL) + let range2 = AddrRange (2UL, 3UL) + let range3 = AddrRange (3UL, 4UL) + let set = IntervalSet.add range1 IntervalSet.empty + let set = IntervalSet.add range2 set |> IntervalSet.add range3 + let removed = IntervalSet.remove (AddrRange (1UL, 2UL)) set + Assert.IsFalse (IntervalSet.containsAddr 1UL removed) + Assert.IsTrue (IntervalSet.containsAddr 2UL removed) + Assert.IsTrue (IntervalSet.containsAddr 3UL removed) + Assert.IsTrue (IntervalSet.containsAddr 4UL removed) + Assert.IsTrue (IntervalSet.contains (AddrRange (2UL, 3UL)) removed) + Assert.IsTrue (IntervalSet.contains (AddrRange (3UL, 4UL)) removed) + Assert.AreEqual (2, IntervalSet.fold (fun cnt _ -> cnt + 1) 0 removed) + [] member __.``IntervalMap Test tryFindByMin`` () = - let range1 = AddrRange (0x100UL, 0x200UL) + let range1 = AddrRange (0x100UL, 0x1FFUL) let map = IntervalMap.add range1 1 IntervalMap.empty Assert.AreEqual (Some 1, IntervalMap.tryFindByMin 0x100UL map) Assert.AreEqual (None, IntervalMap.tryFindByMin 0x199UL map) Assert.AreEqual (None, IntervalMap.tryFindByMin 0x200UL map) - let range2 = AddrRange (0x200UL, 0x300UL) + let range2 = AddrRange (0x200UL, 0x2FFUL) let map = IntervalMap.add range2 2 map Assert.AreEqual (Some 1, IntervalMap.tryFindByMin 0x100UL map) Assert.AreEqual (Some 2, IntervalMap.tryFindByMin 0x200UL map) [] member __.``IntervalMap Test Removal`` () = - let range1 = AddrRange (0x100UL, 0x200UL) - let range2 = AddrRange (0x200UL, 0x300UL) - let range3 = AddrRange (0x300UL, 0x400UL) - let range4 = AddrRange (0x150UL, 0x180UL) - let range5 = AddrRange (0x150UL, 0x220UL) - let range6 = AddrRange (0x400UL, 0x500UL) + let range1 = AddrRange (0x100UL, 0x1FFUL) + let range2 = AddrRange (0x200UL, 0x2FFUL) + let range3 = AddrRange (0x300UL, 0x3FFUL) + let range4 = AddrRange (0x150UL, 0x17FUL) + let range5 = AddrRange (0x150UL, 0x21FUL) + let range6 = AddrRange (0x400UL, 0x4FFUL) let map = IntervalMap.add range2 2 IntervalMap.empty let map = IntervalMap.add range1 1 map let map = IntervalMap.add range3 3 map @@ -128,6 +214,6 @@ type IntervalTreeTests () = [] [)>] member __.``IntervalMap Test Removal Exception`` () = - let range1 = AddrRange (0x100UL, 0x200UL) + let range1 = AddrRange (0x100UL, 0x1FFUL) let map = IntervalMap.add range1 1 IntervalMap.empty IntervalMap.remove (AddrRange (0x100UL, 0x199UL)) map |> ignore diff --git a/src/Core.Tests/ConcurrentLRU.Tests.fs b/src/Core.Tests/LRUCache.Tests.fs similarity index 54% rename from src/Core.Tests/ConcurrentLRU.Tests.fs rename to src/Core.Tests/LRUCache.Tests.fs index 923ace57..165ffa38 100644 --- a/src/Core.Tests/ConcurrentLRU.Tests.fs +++ b/src/Core.Tests/LRUCache.Tests.fs @@ -30,54 +30,58 @@ open B2R2 open System.Threading -[] -type ConcurrentLRUTests () = - member __.GenTestFunc<'K, 'V> (proc: 'K -> 'V) = - let x = ref 0 - (fun k -> Interlocked.Increment x |> ignore; proc k), x +type TestOp () = + let cnt = ref 0 + member __.Count with get() = !cnt + interface ICacheableOperation with + member __.Perform v = + Interlocked.Increment cnt |> ignore + v +[] +type LRUCacheTests () = [] member __.``GetOrAddTest`` () = - let proc, cnt = __.GenTestFunc (fun x -> x) - let lru = new ConcurrentLRU(100) - for i = 0 to 10 do Assert.AreEqual (1, lru.GetOrAdd 1 proc) - Assert.AreEqual (1, !cnt) + let op = TestOp () + let lru = LRUCache(100) + for i = 0 to 10 do Assert.AreEqual (1, lru.GetOrAdd 1 op 1) + Assert.AreEqual (1, op.Count) [] member __.``CountTest`` () = - let proc, cnt = __.GenTestFunc (fun x -> x) - let lru = new ConcurrentLRU(100) - for i = 0 to 99 do Assert.AreEqual (i, lru.GetOrAdd i proc) - Assert.AreEqual (100, !cnt) + let op = TestOp () + let lru = LRUCache(100) + for i = 0 to 99 do Assert.AreEqual (i, lru.GetOrAdd i op i) + Assert.AreEqual (100, op.Count) Assert.AreEqual (100, lru.Count) lru.Clear () Assert.AreEqual (0, lru.Count) - for i = 0 to 99 do Assert.AreEqual (i, lru.GetOrAdd i proc) - Assert.AreEqual (200, !cnt) + for i = 0 to 99 do Assert.AreEqual (i, lru.GetOrAdd i op i) + Assert.AreEqual (200, op.Count) Assert.AreEqual (100, lru.Count) [] member __.``OverflowTest`` () = - let proc, cnt = __.GenTestFunc (fun x -> x) - let lru = new ConcurrentLRU(100) - for i = 0 to 199 do Assert.AreEqual (i, lru.GetOrAdd i proc) - Assert.AreEqual (200, !cnt) + let op = TestOp () + let lru = LRUCache(100) + for i = 0 to 199 do Assert.AreEqual (i, lru.GetOrAdd i op i) + Assert.AreEqual (200, op.Count) Assert.AreEqual (100, lru.Count) - let proc2, cnt2 = __.GenTestFunc (fun x -> x) - for i = 100 to 199 do Assert.AreEqual (i, lru.GetOrAdd i proc2) - Assert.AreEqual (0, !cnt2) + let op = TestOp () + for i = 100 to 199 do Assert.AreEqual (i, lru.GetOrAdd i op i) + Assert.AreEqual (0, op.Count) [] member __.``LRUTest`` () = - let proc, cnt = __.GenTestFunc (fun x -> x) - let lru = new ConcurrentLRU(100) - for i = 0 to 99 do Assert.AreEqual (i, lru.GetOrAdd i proc) - Assert.AreEqual (100, !cnt) + let op = TestOp () + let lru = LRUCache(100) + for i = 0 to 99 do Assert.AreEqual (i, lru.GetOrAdd i op i) + Assert.AreEqual (100, op.Count) Assert.AreEqual (100, lru.Count) - Assert.AreEqual (0, lru.GetOrAdd 0 proc) - Assert.AreEqual (100, !cnt) + Assert.AreEqual (0, lru.GetOrAdd 0 op 0) + Assert.AreEqual (100, op.Count) Assert.AreEqual (100, lru.Count) - Assert.AreEqual (100, lru.GetOrAdd 100 proc) - let proc2, cnt2 = __.GenTestFunc (fun x -> x) - Assert.AreEqual (0, lru.GetOrAdd 0 proc2) - Assert.AreEqual (0, !cnt2) + Assert.AreEqual (100, lru.GetOrAdd 100 op 100) + let op = TestOp () + Assert.AreEqual (0, lru.GetOrAdd 0 op 0) + Assert.AreEqual (0, op.Count) diff --git a/src/Core.Tests/SortedList.Tests.fs b/src/Core.Tests/SortedList.Tests.fs new file mode 100644 index 00000000..e71a4fad --- /dev/null +++ b/src/Core.Tests/SortedList.Tests.fs @@ -0,0 +1,67 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +namespace B2R2.Core.Tests + +open System.Collections.Generic +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 + +[] +type SortedListTests () = + + let lst = SortedList () + do lst.[100] <- 1 + lst.[200] <- 2 + lst.[300] <- 3 + lst.[400] <- 4 + + [] + member __.``GLB`` () = + let actual = SortedList.findGreatestLowerBoundKey 250 lst |> Option.get + Assert.AreEqual (200, actual) + let actual = SortedList.findGreatestLowerBoundKey 101 lst |> Option.get + Assert.AreEqual (100, actual) + let actual = SortedList.findGreatestLowerBoundKey 450 lst |> Option.get + Assert.AreEqual (400, actual) + + [] + member __.``LUB`` () = + let actual = SortedList.findLeastUpperBoundKey 250 lst |> Option.get + Assert.AreEqual (300, actual) + let actual = SortedList.findLeastUpperBoundKey 350 lst |> Option.get + Assert.AreEqual (400, actual) + let actual = SortedList.findLeastUpperBoundKey 99 lst |> Option.get + Assert.AreEqual (100, actual) + + [] + member __.``Boundary Conditions`` () = + Assert.IsTrue + <| (SortedList.findGreatestLowerBoundKey 0 lst |> Option.isNone) + Assert.IsTrue + <| (SortedList.findGreatestLowerBoundKey 100 lst |> Option.isNone) + Assert.IsTrue + <| (SortedList.findLeastUpperBoundKey 400 lst |> Option.isNone) + Assert.IsTrue + <| (SortedList.findLeastUpperBoundKey 500 lst |> Option.isNone) diff --git a/src/FrontEnd/Core/Stack.fs b/src/Core/Addr.fs similarity index 75% rename from src/FrontEnd/Core/Stack.fs rename to src/Core/Addr.fs index 0fc04348..5ba5ba64 100644 --- a/src/FrontEnd/Core/Stack.fs +++ b/src/Core/Addr.fs @@ -22,20 +22,17 @@ SOFTWARE. *) -namespace B2R2.FrontEnd +namespace B2R2 -/// Stack for stack-based languages, such as EVM. -type ExprStack () = - let mutable stack: B2R2.BinIR.LowUIR.Expr list = [] +/// Addresses are represented with a 64-bit integer in B2R2. +type Addr = uint64 - member __.Push e = - stack <- e :: stack +module Addr = + let [] private functionPrefix = "func_" - member __.Pop () = - let ret = stack.Head - stack <- stack.Tail - ret + let toString wordSize (addr: Addr) = + if wordSize = WordSize.Bit32 then (uint32 addr).ToString ("x8") + else addr.ToString ("x16") - member __.Peek n = List.item (n - 1) stack - - member __.Clear () = stack <- [] + let toFuncName (addr: Addr) = + functionPrefix + addr.ToString ("x") diff --git a/src/Core/AddrRange.fs b/src/Core/AddrRange.fs index 78a5ea27..624d192e 100644 --- a/src/Core/AddrRange.fs +++ b/src/Core/AddrRange.fs @@ -32,24 +32,19 @@ exception RangeOverlapException /// value is larger than Max value. exception InvalidAddrRangeException -/// Address type in B2R2 is 64-bit unsigned integer. -type Addr = uint64 - -module Addr = - let toString wordSize (addr: Addr) = - if wordSize = WordSize.Bit32 then addr.ToString ("X8") - else addr.ToString ("X16") - type AddrRange = val Min: Addr val Max: Addr new (min, max) = - if min >= max then raise InvalidAddrRangeException else () + if min > max then raise InvalidAddrRangeException else () { Min = min; Max = max } + new (addr) = + { Min = addr; Max = addr } + override __.ToString () = - __.Min.ToString ("X") + " -- " + __.Max.ToString ("X") + String.u64ToHexNoPrefix __.Min + " -- " + String.u64ToHexNoPrefix __.Max override __.Equals (rhs: obj) = match rhs with @@ -59,9 +54,15 @@ type AddrRange = override __.GetHashCode () = hash ( __.Min, __.Max ) + member __.Count with get() = __.Max - __.Min + 1UL + member __.ToTuple () = __.Min, __.Max + /// Check if the address range is including the given address. + member inline __.IsIncluding (addr: Addr) = + __.Min <= addr && addr <= __.Max + static member inline GetMin (range: AddrRange) = range.Min static member inline GetMax (range: AddrRange) = range.Max diff --git a/src/Core/AddrRange.fsi b/src/Core/AddrRange.fsi index b37ee065..0f7a2892 100644 --- a/src/Core/AddrRange.fsi +++ b/src/Core/AddrRange.fsi @@ -31,17 +31,10 @@ exception RangeOverlapException /// interval. exception InvalidAddrRangeException -/// Addresses are represented with a 64-bit integer in B2R2. -type Addr = uint64 - -module Addr = - /// Convert the given address to a hex-string. - val toString: WordSize -> Addr -> string - /// AddrRange is a tuple (min, max) that represents a range of address values -/// that are greater or equal to the min value (inclusive) and are less than the -/// max value (exclusive). To access the min and the max value of a range, use -/// either getMin or getMax function. +/// that are greater or equal to the min value (inclusive) and are less than or +/// equal to the max value (inclusive). To access the min and the max value of a +/// range, use either getMin or getMax function. type AddrRange = class /// @@ -54,12 +47,25 @@ type AddrRange = /// new : min: Addr * max: Addr -> AddrRange + /// + /// Initialize an instance of AddrRange of size 1 has a single addr, i.e., + /// (addr - addr). + /// + /// The start address. + /// + /// An instance of AddrRange. + /// + new : addr: Addr -> AddrRange + /// Minimum value (lower bound) of the interval. val Min: Addr /// Maximum value (upper bound) of the interval. val Max: Addr + /// The number of addresses in this range. + member Count: uint64 + /// /// Get the corresponding tuple (Addr, Addr) from the AddrRange. /// @@ -68,6 +74,14 @@ type AddrRange = /// member ToTuple: unit -> Addr * Addr + /// + /// Check if the address range is including the given address. + /// + /// + /// True if the address is included in the range. False otherwise. + /// + member inline IsIncluding: Addr -> bool + /// /// Get the min value (inclusive) of the AddrRange. /// diff --git a/src/Core/AddrRangeMap.fs b/src/Core/AddrRangeMap.fs index 98fb331d..d47f57be 100644 --- a/src/Core/AddrRangeMap.fs +++ b/src/Core/AddrRangeMap.fs @@ -28,7 +28,7 @@ exception InvalidWhiteningException exception KeyNotFoundException -type Color = +type internal RBColor = /// Red | R /// Black @@ -39,8 +39,8 @@ type Color = | NB type ARMap<'V> = - | Leaf of Color - | Node of Color * AddrRange * 'V * ARMap<'V> * ARMap<'V> + | Leaf of RBColor + | Node of RBColor * AddrRange * 'V * ARMap<'V> * ARMap<'V> [] module ARMap = @@ -87,9 +87,9 @@ module ARMap = | Node (c, k', v', l, r) -> if k' = k then (if isReplace then Node (c, k', v, l, r) else raise RangeOverlapException) - elif k.Min < k'.Min && k.Max <= k'.Min then + elif k.Min < k'.Min && k.Max < k'.Min then balance (c, k', v', ins l, r) - elif k.Min >= k'.Max && k.Max > k'.Max then + elif k.Min > k'.Max && k.Max > k'.Max then balance (c, k', v', l, ins r) else raise RangeOverlapException ins tree |> toBlack @@ -104,22 +104,22 @@ module ARMap = let replace k v tree = fnAdd k v tree true let rec private findLoop isExact k = function - | Leaf _ -> None + | Leaf _ -> Error ErrorCase.ItemNotFound | Node (_, k', v', l, r) -> - if k = k' then Some (k', v') - elif k.Min < k'.Min && k.Max <= k'.Min then findLoop isExact k l - elif k.Min >= k'.Max && k.Max > k'.Max then findLoop isExact k r + if k = k' then Ok (k', v') + elif k.Min < k'.Min && k.Max < k'.Min then findLoop isExact k l + elif k.Min > k'.Max && k.Max > k'.Max then findLoop isExact k r elif (not isExact) - && k.Min >= k'.Min && k.Max <= k'.Max then Some (k', v') - else None + && k.Min >= k'.Min && k.Max <= k'.Max then Ok (k', v') + else Error ErrorCase.ItemNotFound let rec private del isExact k = function | Leaf _ -> raise KeyNotFoundException | Node (c, k', v', l, r) -> if k = k' then delAndBalance isExact (c, l, r) - elif k.Min < k'.Min && k.Max <= k'.Min then + elif k.Min < k'.Min && k.Max < k'.Min then bubble (c, k', v', del isExact k l, r) - elif k.Min >= k'.Max && k.Max > k'.Max then + elif k.Min > k'.Max && k.Max > k'.Max then bubble (c, k', v', l, del isExact k r) elif (not isExact) && k.Min >= k'.Min && k.Max <= k'.Max then delAndBalance isExact (c, l, r) @@ -145,12 +145,12 @@ module ARMap = | node -> Node node [] - let remove range tree = - del true range tree |> toBlack + let remove k tree = + del true k tree |> toBlack [] - let removeAddr k tree = - del false (AddrRange (k, k + 1UL)) tree + let removeAddr addr tree = + del false (AddrRange addr) tree [] let empty = Leaf B @@ -162,30 +162,37 @@ module ARMap = | _ -> false [] - let containsAddr k tree = - findLoop false (AddrRange (k, k + 1UL)) tree |> Option.isSome + let containsAddr addr tree = + findLoop false (AddrRange addr) tree |> Result.isOk [] let containsRange range tree = - findLoop true range tree |> Option.isSome + findLoop true range tree |> Result.isOk [] - let find range tree = findLoop true range tree |> Option.get |> snd + let find range tree = findLoop true range tree |> Result.get |> snd [] let tryFindKey addr tree = - findLoop false (AddrRange (addr, addr + 1UL)) tree |> Option.map fst + match findLoop false (AddrRange addr) tree with + | Ok (k, _) -> Some k + | _ -> None [] let tryFind range tree = - findLoop true range tree |> Option.map snd + match findLoop true range tree with + | Ok (_, v) -> Some v + | _ -> None [] - let tryFindByAddr k tree = - findLoop false (AddrRange (k, k + 1UL)) tree |> Option.map snd + let tryFindByAddr addr tree = + match findLoop false (AddrRange addr) tree with + | Ok (_, v) -> Some v + | _ -> None [] - let findByAddr k tree = tryFindByAddr k tree |> Option.get + let findByAddr addr tree = + findLoop false (AddrRange addr) tree |> Result.get |> snd let rec private sizeAux acc tree = match tree with @@ -196,16 +203,19 @@ module ARMap = let count tree = sizeAux 0 tree [] - let rec iter fn = function + let rec iter fn tree = + match tree with | Leaf _ -> () | Node (_, k, v, l, r) -> iter fn l; fn k v; iter fn r [] - let rec fold fn acc = function + let rec fold fn acc tree = + match tree with | Leaf _ -> acc - | Node (_, k, v, l, r) -> let acc = fold fn acc l - let acc = fn acc k v - fold fn acc r + | Node (_, k, v, l, r) -> + let acc = fold fn acc l + let acc = fn acc k v + fold fn acc r [] let getOverlaps (k: AddrRange) tree = @@ -214,7 +224,7 @@ module ARMap = | Node (_, k', v', l, r) -> let acc = if k.Min < k'.Min then loop acc l else acc let acc = - if k.Max <= k'.Min || k.Min >= k'.Max then acc + if k.Max < k'.Min || k.Min > k'.Max then acc else (k', v') :: acc let acc = if k.Max > k'.Max then loop acc r else acc acc diff --git a/src/Core/AddrRangeMap.fsi b/src/Core/AddrRangeMap.fsi index 2a8e8a56..593a3716 100644 --- a/src/Core/AddrRangeMap.fsi +++ b/src/Core/AddrRangeMap.fsi @@ -47,7 +47,7 @@ module ARMap = /// Returns true if the tree is empty, false otherwise. /// [] - val isEmpty: ARMap<'V> -> bool + val isEmpty: tree: ARMap<'V> -> bool /// /// Add a mapping from an interval to the value in the interval tree. @@ -62,7 +62,7 @@ module ARMap = /// Thrown when there is an existing (overlapping) interval in the tree. /// [] - val add: AddrRange -> 'V -> ARMap<'V> -> ARMap<'V> + val add: k: AddrRange -> v: 'V -> tree: ARMap<'V> -> ARMap<'V> /// /// This function is the same as add except that this one takes in two @@ -80,7 +80,7 @@ module ARMap = /// Thrown when there is an existing (overlapping) interval in the tree. /// [] - val addRange: Addr -> Addr -> 'V -> ARMap<'V> -> ARMap<'V> + val addRange: min: Addr -> max: Addr -> v: 'V -> tree: ARMap<'V> -> ARMap<'V> /// /// This function is the same as add except that it will overwrite the @@ -94,7 +94,7 @@ module ARMap = /// A new interval tree. /// [] - val replace: AddrRange -> 'V -> ARMap<'V> -> ARMap<'V> + val replace: k: AddrRange -> v: 'V -> tree: ARMap<'V> -> ARMap<'V> /// /// Remove a mapping that matches exactly with the given range. To remove a @@ -106,7 +106,7 @@ module ARMap = /// A new interval tree. /// [] - val remove: AddrRange -> ARMap<'V> -> ARMap<'V> + val remove: k: AddrRange -> tree: ARMap<'V> -> ARMap<'V> /// /// Remove a mapping that matches with the given address. Unlike remove, @@ -118,19 +118,19 @@ module ARMap = /// A new interval tree. /// [] - val removeAddr: Addr -> ARMap<'V> -> ARMap<'V> + val removeAddr: addr: Addr -> tree: ARMap<'V> -> ARMap<'V> /// /// Check whether a given Addr exists in any of the ranges in the map. /// - /// Address. + /// Address. /// The interval tree. /// /// True if the interval tree contains an interval that includes the given /// address, false otherwise. /// [] - val containsAddr: Addr -> ARMap<'V> -> bool + val containsAddr: addr: Addr -> tree: ARMap<'V> -> bool /// /// Check whether the exact range exists in the interval map. @@ -141,7 +141,7 @@ module ARMap = /// True if the interval tree contains the interval, false otherwise. /// [] - val containsRange: AddrRange -> ARMap<'V> -> bool + val containsRange: range: AddrRange -> tree: ARMap<'V> -> bool /// /// Find the mapping that exactly matches with the given range. @@ -152,7 +152,7 @@ module ARMap = /// The value associated with the given interval. /// [] - val find: AddrRange -> ARMap<'V> -> 'V + val find: range: AddrRange -> tree: ARMap<'V> -> 'V /// /// Find the mapping that matches with the given range. Unlike find, this @@ -164,7 +164,7 @@ module ARMap = /// The value associated with the given address. /// [] - val findByAddr: Addr -> ARMap<'V> -> 'V + val findByAddr: addr: Addr -> tree: ARMap<'V> -> 'V /// /// Find an interval stored in the interval tree map, which includes the @@ -176,7 +176,7 @@ module ARMap = /// The found interval wrapped with option. /// [] - val tryFindKey: Addr -> ARMap<'V> -> AddrRange option + val tryFindKey: addr: Addr -> tree: ARMap<'V> -> AddrRange option /// /// Same as find, except that this returns an option-wrapped type. @@ -187,7 +187,7 @@ module ARMap = /// The value associated with the given interval. /// [] - val tryFind: AddrRange -> ARMap<'V> -> 'V option + val tryFind: range: AddrRange -> tree: ARMap<'V> -> 'V option /// /// Same as findByAddr, except that this returns an option-wrapped type. @@ -198,7 +198,7 @@ module ARMap = /// The value associated with the given address. /// [] - val tryFindByAddr: Addr -> ARMap<'V> -> 'V option + val tryFindByAddr: addr: Addr -> tree: ARMap<'V> -> 'V option /// /// Return the number of bindings in the interval map. @@ -208,7 +208,7 @@ module ARMap = /// The number of bindings. /// [] - val count: ARMap<'V> -> int + val count: tree: ARMap<'V> -> int /// /// Iterate over the tree. @@ -216,7 +216,7 @@ module ARMap = /// Iterator. /// The interval tree. [] - val iter: (AddrRange -> 'V -> unit) -> ARMap<'V> -> unit + val iter: fn: (AddrRange -> 'V -> unit) -> tree: ARMap<'V> -> unit /// /// Fold over the tree. @@ -228,15 +228,16 @@ module ARMap = /// Accumulated value. /// [] - val fold: ('b -> AddrRange -> 'V -> 'b) -> 'b -> ARMap<'V> -> 'b + val fold: + fn: ('b -> AddrRange -> 'V -> 'b) -> acc: 'b -> tree: ARMap<'V> -> 'b /// /// Return a sequence of overlapping mappings of the given interval. /// - /// The interval. + /// The key interval. /// The interval tree. /// /// A sequence of mappings. /// [] - val getOverlaps: AddrRange -> ARMap<'V> -> (AddrRange * 'V) list + val getOverlaps: k: AddrRange -> tree: ARMap<'V> -> (AddrRange * 'V) list diff --git a/src/Core/B2R2.Core.fsproj b/src/Core/B2R2.Core.fsproj index 46c8ccbf..8e5da501 100644 --- a/src/Core/B2R2.Core.fsproj +++ b/src/Core/B2R2.Core.fsproj @@ -1,20 +1,24 @@ - + - netstandard2.1 + net5.0 + LICENSE.md + b2r2-240x240.png + $(OtherFlags)--warnon:3390 + README.md + B2R2 core library. - - - - + + + + + + - - @@ -22,26 +26,28 @@ + - + + + - - - - + + + diff --git a/src/Core/BaseRegisterSet.fs b/src/Core/BaseRegisterSet.fs deleted file mode 100644 index 3f144349..00000000 --- a/src/Core/BaseRegisterSet.fs +++ /dev/null @@ -1,182 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2 - -open System.Runtime.InteropServices - -/// Raised when two RegisterSets with two distinct tags operate. -exception TagMismatchException - -/// A tag used in RegisterSet for identifying distinct set of registers for -/// different ISAs. -type RegisterSetTag = - | Empty = 0 - | Intel = 1 - | ARM32 = 2 - | ARM64 = 3 - | MIPS = 4 - | EVM = 5 - | TMS320C6000 = 6 - -/// RegisterSet is an efficient set data structure for managing a set of -/// registers. -[] -type RegisterSet () = - /// Tag identifies ISA. - abstract member Tag : RegisterSetTag - - /// Create a new RegisterSet. This method should be overridden by ISA-specific - /// RegisterSet implementation. - abstract member New : uint64 [] -> Set -> RegisterSet - - /// Obtain an integer from a given RegisterID. - abstract member Project : RegisterID -> int - - /// Return an empty RegisterSet. - abstract member Empty : RegisterSet - - /// Size of the internal array. - abstract member ArrSize : int - - /// An empty array representing an empty set of registers. This array should - /// be initialized based on the ArrSize. - abstract member EmptyArr : uint64 [] - - /// An internal array storing the register set. - abstract member BitArray : uint64 [] - - /// A backup storage for unknown variables, which does not have an unknown - /// RegisterID. For example, when writing a symbolic executor, we may - /// encounter unknown variables, i.e., fresh symbolic variables. We store them - /// in this set. - abstract member S : Set - - /// Add a register to the set. - abstract member Add : RegisterID -> RegisterSet - - /// Remove a register from the set. - abstract member Remove : RegisterID -> RegisterSet - - /// Union of two register sets. - abstract member Union : RegisterSet -> RegisterSet - - /// Intersection of two register sets. - abstract member Intersect : RegisterSet -> RegisterSet - - /// Check if a register exists in the set. - abstract member Exists : RegisterID -> bool - - /// Check if the set is empty. - abstract member IsEmpty : unit -> bool - -[] -type NonEmptyRegisterSet (bitArray: uint64 [], s: Set) = - inherit RegisterSet () - - member __.CheckTag (o: RegisterSet) = - if __.Tag = o.Tag then () else raise TagMismatchException - - (* Get Buckets and Index *) - static member inline GetBI (x, [] index: int byref) = - index <- x &&& 0x3F; x / 64 - - override __.BitArray = bitArray - override __.S = s - override __.Remove id = - match __.Project id with - | -1 -> __.New __.EmptyArr (Set.remove id s) - | id -> - let bucket, index = NonEmptyRegisterSet.GetBI id - let newArr = Array.copy bitArray - newArr.[bucket] <- newArr.[bucket] &&& ~~~(1UL <<< index) - __.New newArr Set.empty - - override __.Add id = - match __.Project id with - | -1 -> __.New __.EmptyArr (Set.add id s) - | id -> - let bucket, index = NonEmptyRegisterSet.GetBI id - let newArr = Array.copy bitArray - newArr.[bucket] <- newArr.[bucket] ||| (1UL <<< index) - __.New newArr s - - override __.Union (other: RegisterSet) = - if other.Tag = RegisterSetTag.Empty then __ :> RegisterSet - else - __.CheckTag other - let newArr = Array.copy bitArray - let otherArr = other.BitArray - for i = 0 to __.ArrSize - 1 do newArr.[i] <- newArr.[i] ||| otherArr.[i] - __.New newArr <| Set.union __.S other.S - - override __.Intersect (other: RegisterSet) = - if other.Tag = RegisterSetTag.Empty then __.Empty - else - __.CheckTag other - let newArr = Array.copy bitArray - let otherArr = other.BitArray - for i = 0 to __.ArrSize - 1 do newArr.[i] <- newArr.[i] &&& otherArr.[i] - __.New newArr <| Set.union __.S other.S - - override __.Exists id = - match __.Project id with - | -1 -> Set.contains id __.S - | id -> - let bucket, index = NonEmptyRegisterSet.GetBI id - bitArray.[bucket] &&& (1UL <<< index) <> 0UL - - override __.IsEmpty () = - (Array.exists (fun x -> x <> 0UL) bitArray |> not) && Set.isEmpty __.S - -type EmptyRegisterSet () = - inherit RegisterSet () - static member Instance = EmptyRegisterSet () :> RegisterSet - override __.Tag = RegisterSetTag.Empty - override __.ArrSize = 0 - override __.New _ _ = invalidOp "Cannot call EmptyRegisterSet.New" - override __.Project _ = invalidOp "Cannot call EmptyRegisterSet.Project" - override __.Empty = EmptyRegisterSet.Instance - override __.EmptyArr = [||] - override __.BitArray = [||] - override __.S = Set.empty - override __.Add _ = invalidOp "Cannot call EmptyRegisterSet.Add" - override __.Remove _ = __ :> RegisterSet - override __.Union o = o - override __.Intersect o = o.Empty - override __.Exists _ = false - override __.IsEmpty () = true - -/// A helper module for building a RegisterSet. -module RegisterSetBuilder = - let inline singletonBuilder (s: RegisterSet) = - let impl id = - match s.Project id with - | -1 -> s.New s.EmptyArr (Set.singleton id) - | id -> - let bucket, index = NonEmptyRegisterSet.GetBI id - let newArr = Array.init s.ArrSize (fun _ -> 0UL) - newArr.[bucket] <- newArr.[bucket] ||| (1UL <<< index) - s.New newArr Set.empty - impl diff --git a/src/Core/BinReader.fs b/src/Core/BinReader.fs index 847fed18..018a5ff7 100644 --- a/src/Core/BinReader.fs +++ b/src/Core/BinReader.fs @@ -81,8 +81,8 @@ type BinReader (bytes: byte []) = member inline private __.extendSign b offset currentValue bitmask maxLen = if b &&& 0x40uy <> 0uy then - let shiftOffset = if offset < (maxLen - 1) then offset + 1 else offset - bitmask <<< (7 * (shiftOffset)) ||| currentValue + let shiftOffset = if offset < (maxLen - 1) then offset + 1 else offset + bitmask <<< (7 * (shiftOffset)) ||| currentValue else currentValue @@ -217,7 +217,7 @@ type BinReader (bytes: byte []) = member __.Length () = Array.length bytes /// Is the given offset points to a position out of the range of the file? - member __.IsOutOfRange (o) = Array.length bytes <= o + member __.IsOutOfRange (o) = o < 0 || Array.length bytes <= o /// Instantiate BinReader from a given byte array and endianness. static member Init @@ -225,7 +225,7 @@ type BinReader (bytes: byte []) = match endian with | Endian.Little -> BinReaderLE (bytes) :> BinReader | Endian.Big -> BinReaderBE (bytes) :> BinReader - | _ -> invalidArg "BinReader.init" "Invalid endian is given." + | _ -> invalidArg (nameof endian) "Invalid endian is given." /// Return a new BinReader of the given endianness. This function will return /// the same reader if the given endianness is the same as the endianness of @@ -322,4 +322,15 @@ and internal BinReaderBE (bytes: byte []) = override __.Endianness = Endian.Big +/// Empty BinReader, representing a null type. +type EmptyBinReader () = + inherit BinReader ([||]) + override __.PeekInt16 (o) = Utils.impossible () + override __.PeekUInt16 (o) = Utils.impossible () + override __.PeekInt32 (o) = Utils.impossible () + override __.PeekUInt32 (o) = Utils.impossible () + override __.PeekInt64 (o) = Utils.impossible () + override __.PeekUInt64 (o) = Utils.impossible () + override __.Endianness = Utils.impossible () + // vim: set tw=80 sts=2 sw=2: diff --git a/src/Core/BitVector.fs b/src/Core/BitVector.fs index 064d543c..762132af 100644 --- a/src/Core/BitVector.fs +++ b/src/Core/BitVector.fs @@ -26,15 +26,58 @@ namespace B2R2 open System +[] +module BitVectorConstants = + /// BigInteger zero. + let bigZero = 0I + + /// BigInteger one. + let bigOne = 1I + /// A helper module for BitVector. [] module internal BitVectorHelper = + exception ArithTypeMismatchException let nSizeErr t = failwithf "Invalid BitVector value for its type: %s" (t.ToString ()) - let bigNull = 0I + let inline adaptSmall (len: RegType) (n: uint64) = + (UInt64.MaxValue >>> (64 - int len)) &&& n + + let inline adaptBig (len: RegType) (n: bigint) = + ((bigOne <<< int len) - bigOne) &&& n + + let inline isSmallPositive (len: RegType) (n: uint64) = + (n >>> (int len - 1)) &&& 1UL = 0UL + + let inline isBigPositive (len: RegType) (n: bigint) = + (n >>> (int len - 1)) &&& bigOne = bigZero + + let inline neg (len: RegType) (n: bigint) = (bigOne <<< int len) - n + + let inline toFloat32 (n: uint64) = + n |> int32 |> BitConverter.Int32BitsToSingle + + let inline toFloat64 (n: uint64) = + n |> int64 |> BitConverter.Int64BitsToDouble + + let inline toBigFloat (n: bigint) = + let sign = n >>> 79 <<< 63 |> uint64 + let exponent = n >>> 64 &&& 32767I + let adjustedExp = exponent - 15360I |> uint64 <<< 52 + let significand = n &&& (bigint 0x7FFFFFFFFFFFFFFFUL) |> uint64 >>> 11 + let f64 = sign ||| adjustedExp ||| significand + f64 |> int64 |> BitConverter.Int64BitsToDouble + + let inline encodeBigFloat (n: uint64) = + let signOnly = n &&& (1UL <<< 63) >>> 48 + let exp = n &&& 0x7FF0000000000000UL >>> 52 + let expAndSign = exp + 0x3C00UL ||| signOnly |> bigint + let significand = n &&& 0x000FFFFFFFFFFFFFUL + let significand = significand ||| 0x0010000000000000UL <<< 11 |> bigint + expAndSign <<< 64 ||| significand /// BitVector is the fundamental data type for binary code, which is essentially /// a bit vector. We want the size of a bit vector to be less than or equal to @@ -44,860 +87,1772 @@ module internal BitVectorHelper = /// /// N.B. Num becomes zero when the Length becomes greater than 64. We /// intentionally do not sync Num and BigNum. -[] -type BitVector = - private - { - Num : uint64 - Length : RegType - BigNum : bigint - } - override __.Equals obj = - match obj with - | :? BitVector as obj -> - __.Length = obj.Length && __.Num = obj.Num && __.BigNum = obj.BigNum - | _ -> false +[] +type BitVector internal (len) = + /// BitVector length. + member __.Length with get(): RegType = len - override __.GetHashCode () = - hash (__.Num, __.Length, __.BigNum) + /// Return the uint64 representation of the bitvector value. + abstract SmallValue: unit -> uint64 - override __.ToString () = - __.ValToString () + ":" + RegType.toString __.Length + /// Return the BigInteger representation of the bitvector value. + abstract BigValue: unit -> bigint + + /// Return true if the value is zero. + abstract IsZero: unit -> bool + + /// Return true if the value is one. + abstract IsOne: unit -> bool + + /// BitVector addition with uint64. + abstract Add: uint64 -> BitVector + + /// BitVector addition. + abstract Add: BitVector -> BitVector + + /// BitVector subtraction with uint64. + abstract Sub: uint64 -> BitVector + + /// BitVector subtraction. + abstract Sub: BitVector -> BitVector + + /// BitVector multiplication with uint64. + abstract Mul: uint64 -> BitVector + + /// BitVector multiplication. + abstract Mul: BitVector -> BitVector + + /// BitVector signed division. + abstract SDiv: BitVector -> BitVector + + /// BitVector unsigned division with uint64. + abstract Div: uint64 -> BitVector + + /// BitVector unsigned division. + abstract Div: BitVector -> BitVector + + /// BitVector signed modulo. + abstract SMod: BitVector -> BitVector + + /// BitVector unsigned modulo with uint64. + abstract Mod: uint64 -> BitVector + + /// BitVector unsigned modulo. + abstract Mod: BitVector -> BitVector + + /// BitVector bitwise AND with uint64. + abstract And: uint64 -> BitVector + + /// BitVector bitwise AND. + abstract And: BitVector -> BitVector + + /// BitVector bitwise OR with uint64. + abstract Or: uint64 -> BitVector + + /// BitVector bitwise OR. + abstract Or: BitVector -> BitVector + + /// BitVector bitwise XOR with uint64. + abstract Xor: uint64 -> BitVector + + /// BitVector bitwise XOR. + abstract Xor: BitVector -> BitVector + + /// BitVector logical shift-left. + abstract Shl: BitVector -> BitVector + + /// BitVector logical shift-right. + abstract Shr: BitVector -> BitVector + + /// BitVector arithmetic shift-right. + abstract Sar: BitVector -> BitVector + + /// BitVector bitwise NOT. + abstract Not: unit -> BitVector + + /// BitVector unary negation. + abstract Neg: unit -> BitVector + + /// Type-cast a BitVector to another type. If the target type is bigger than + /// the current type, then this works the same as ZExt. + abstract Cast: RegType -> BitVector + + /// Extract a sub-BitVector of size (RegType) starting from the index (int). + abstract Extract: RegType -> int -> BitVector + + /// BitVector concatenation. + abstract Concat: BitVector -> BitVector + + /// BitVector sign-extension. + abstract SExt: RegType -> BitVector + + /// BitVector zero-extension. + abstract ZExt: RegType -> BitVector + + /// BitVector equal. + abstract Eq: BitVector -> BitVector + + /// BitVector not equal. + abstract Neq: BitVector -> BitVector + + /// BitVector unsigned greater than. + abstract Gt: BitVector -> BitVector + + /// BitVector unsigned greater than or equal. + abstract Ge: BitVector -> BitVector + + /// BitVector signed greater than. + abstract SGt: BitVector -> BitVector + + /// BitVector signed greater than or equal. + abstract SGe: BitVector -> BitVector + + /// BitVector unsigned less than. + abstract Lt: BitVector -> BitVector + + /// BitVector unsigned less than or equal. + abstract Le: BitVector -> BitVector + + /// BitVector signed less than. + abstract SLt: BitVector -> BitVector + + /// BitVector signed less than or equal. + abstract SLe: BitVector -> BitVector + + /// BitVector absolute value. + abstract Abs: unit -> BitVector + + /// Floating point addition. + abstract FAdd: BitVector -> BitVector - member __.ValToString () = - if __.Length <= 64 then "0x" + __.Num.ToString ("X") - elif __.Num = 0UL && __.BigNum = 0I then "0x0" - else "0x" + __.BigNum.ToString("X").TrimStart('0') + /// Floating point subtraction. + abstract FSub: BitVector -> BitVector - static member inline BOp (v: BitVector) (b: uint64) op bigop = - let a = v.Num - match v.Length with - | 8 -> { v with Num = op a b |> uint8 |> uint64 } - | 16 -> { v with Num = op a b |> uint16 |> uint64 } - | 32 -> { v with Num = op a b |> uint32 |> uint64 } - | 64 -> { v with Num = op a b } - | len when len > 64 -> - let n1 = v.BigNum - let n2 = bigint b - let a = bigint.op_BitwiseAnd (bigop (n1, n2), RegType.getMask v.Length) - { v with BigNum = a } - | _ -> { v with Num = op a b &&& uint64 (RegType.getMask v.Length) } + /// Floating point multiplication. + abstract FMul: BitVector -> BitVector - static member (+) (v: BitVector, b: uint64) = - BitVector.BOp v b (+) (bigint.Add) + /// Floating point division. + abstract FDiv: BitVector -> BitVector - static member (-) (v: BitVector, b: uint64) = - BitVector.BOp v b (-) (bigint.Subtract) + /// Floating point logarithm. + abstract FLog: BitVector -> BitVector - static member (*) (v: BitVector, b: uint64) = - BitVector.BOp v b (*) (bigint.Multiply) + /// Floating point power. + abstract FPow: BitVector -> BitVector - static member (&&&) (v: BitVector, b: uint64) = - BitVector.BOp v b (&&&) (bigint.op_BitwiseAnd) + /// Floating point casting. + abstract FCast: RegType -> BitVector - static member (|||) (v: BitVector, b: uint64) = - BitVector.BOp v b (|||) (bigint.op_BitwiseOr) + /// Integer to float conversion. + abstract Itof: RegType -> BitVector - static member (^^^) (v: BitVector, b: uint64) = - BitVector.BOp v b (^^^) (bigint.op_ExclusiveOr) + /// Floating point to integer conversion with truncation. + abstract FtoiTrunc: RegType -> BitVector - static member (/) (v: BitVector, b: uint64) = - BitVector.BOp v b (/) (bigint.Divide) + /// Floating point to integer conversion with rounding. + abstract FtoiRound: RegType -> BitVector - static member (%) (v: BitVector, b: uint64) = - BitVector.BOp v b (%) (bigint.op_Modulus) + /// Floating point to integer conversion with flooring. + abstract FtoiFloor: RegType -> BitVector - static member (+) (v1: BitVector, v2: BitVector) = - BitVector.add v1 v2 + /// Floating point to integer conversion with ceiling. + abstract FtoiCeil: RegType -> BitVector - static member (-) (v1: BitVector, v2: BitVector) = - BitVector.sub v1 v2 + /// Floating point square root. + abstract FSqrt: unit -> BitVector - static member (*) (v1: BitVector, v2: BitVector) = - BitVector.mul v1 v2 + /// Floating point tangent. + abstract FTan: unit -> BitVector - static member (&&&) (v1: BitVector, v2: BitVector) = - BitVector.band v1 v2 + /// Floating point sine. + abstract FSin: unit -> BitVector - static member (|||) (v1: BitVector, v2: BitVector) = - BitVector.bor v1 v2 + /// Floating point cosine. + abstract FCos: unit -> BitVector - static member (^^^) (v1: BitVector, v2: BitVector) = - BitVector.bxor v1 v2 + /// Floating point arc tangent. + abstract FATan: unit -> BitVector - static member (~~~) (v: BitVector) = - BitVector.bnot v + /// Floating point greater than. + abstract FGt: BitVector -> BitVector - static member (/) (v1: BitVector, v2: BitVector) = - BitVector.sdiv v1 v2 + /// Floating point greater than or equal. + abstract FGe: BitVector -> BitVector - static member (|/|) (v1: BitVector, v2: BitVector) = - BitVector.div v1 v2 + /// Floating point less than. + abstract FLt: BitVector -> BitVector - static member (%) (v1: BitVector, v2: BitVector) = - BitVector.smodulo v1 v2 + /// Floating point less than or equal. + abstract FLe: BitVector -> BitVector - static member (|%|) (v1: BitVector, v2: BitVector) = - BitVector.modulo v1 v2 + /// Return the string representation of the BitVector value. Type is not + /// appended to the output string. + abstract ValToString: unit -> string - static member (~-) (v: BitVector) = - BitVector.neg v + /// BitVector approximate equal. For high-precision floating point numbers, + /// this function performs approximate equality check. + abstract ApproxEq: BitVector -> BitVector + /// Is this bitvector representing a positive number? + abstract IsPositive: unit -> bool + + /// Is this bitvector representing a negative number? + abstract IsNegative: unit -> bool + + /// Return zero (0) of the given bit length. + [] + static member zero t = + if t <= 64 then BitVectorSmall (0UL, t) :> BitVector + else BitVectorBig (bigZero, t) :> BitVector + + /// Return one (1) of the given bit length. + [] + static member one t = + if t <= 64 then BitVectorSmall (1UL, t) :> BitVector + else BitVectorBig (bigOne, t) :> BitVector + + /// True value. + static member T = BitVectorSmall (1UL, 1) :> BitVector + + /// False value. + static member F = BitVectorSmall (0UL, 1) :> BitVector + + /// Return a smaller BitVector. + [] + static member min (bv1: BitVector) bv2 = + if bv1.Lt bv2 = BitVector.T then bv1 else bv2 + + /// Return a larger BitVector. + [] + static member max (bv1: BitVector) bv2 = + if bv1.Gt bv2 = BitVector.T then bv1 else bv2 + + /// Return a smaller BitVector (with signed comparison). + [] + static member smin (bv1: BitVector) bv2 = + if bv1.SLt bv2 = BitVector.T then bv1 else bv2 + + /// Return a larger BitVector (with signed comparison). + [] + static member smax (bv1: BitVector) bv2 = + if bv1.SGt bv2 = BitVector.T then bv1 else bv2 + + /// Get a BitVector from an unsigned integer. [] - static member ofUInt64 (i: uint64) typ = - match typ with + static member inline ofUInt64 (i: uint64) typ = #if DEBUG - | typ when typ <= 0 -> nSizeErr typ + if typ <= 0 then raise ArithTypeMismatchException else () #endif - | 1 when i = 1UL -> { Num = 1UL; Length = typ; BigNum = bigNull } - | 1 when i = 0UL -> { Num = 0UL; Length = typ; BigNum = bigNull } - | 2 -> { Num = i &&& 0x3UL; Length = typ; BigNum = bigNull } - | 4 -> { Num = i &&& 0xFUL; Length = typ; BigNum = bigNull } - | 8 -> { Num = uint8 i |> uint64; Length = typ; BigNum = bigNull } - | 16 -> { Num = uint16 i |> uint64; Length = typ; BigNum = bigNull } - | 32 -> { Num = uint32 i |> uint64; Length = typ; BigNum = bigNull } - | 64 -> { Num = i; Length = typ; BigNum = bigNull } - | t when t < 64 -> - { Num = i &&& (RegType.getUInt64Mask t); Length = typ; BigNum = bigNull } - | _ -> { Num = 0UL; Length = typ; BigNum = bigint i} + if typ <= 64 then + let mask = UInt64.MaxValue >>> (64 - int typ) + BitVectorSmall (i &&& mask, typ) :> BitVector + else BitVectorBig (bigint i, typ) :> BitVector + /// Get a BitVector from a signed integer. [] - static member ofInt64 (i: int64) typ = + static member inline ofInt64 (i: int64) typ = #if DEBUG - if typ <= 0 then nSizeErr typ else () + if typ <= 0 then raise ArithTypeMismatchException else () #endif - if typ <= 64 then BitVector.ofUInt64 (uint64 i) typ + if typ <= 64 then + let mask = UInt64.MaxValue >>> (64 - int typ) + BitVectorSmall (uint64 i &&& mask, typ) :> BitVector else if i < 0L then - let n = bigint.Pow (2I, int typ) - ((~-) i |> uint64 |> bigint) - { Num = 0UL; Length = typ; BigNum = n } - else - { Num = 0UL; Length = typ; BigNum = bigint i } + BitVectorBig ((bigOne <<< int typ) - (- i |> bigint), typ) :> BitVector + else BitVectorBig (bigint i, typ) :> BitVector + /// Get a BitVector from an unsigned integer. [] - static member ofUInt32 (i: uint32) typ = -#if DEBUG - if typ <= 0 then nSizeErr typ else () -#endif + static member inline ofUInt32 (i: uint32) typ = BitVector.ofUInt64 (uint64 i) typ + /// Get a BitVector from a signed integer. [] - static member ofInt32 (i: int32) typ = -#if DEBUG - if typ <= 0 then nSizeErr typ else () -#endif + static member inline ofInt32 (i: int32) typ = BitVector.ofInt64 (int64 i) typ - [] - static member ofUBInt (i: bigint) typ = + /// Get a BitVector from a bigint. We assume that the given RegType (typ) is + /// big enough to hold the given bigint. Otherwise, the resulting BitVector + /// may contain an unexpected value. + [] + static member ofBInt (i: bigint) typ = #if DEBUG if typ <= 0 then nSizeErr typ else () #endif if typ <= 64 then BitVector.ofUInt64 (uint64 i) typ - else { Num = 0UL; Length = typ; BigNum = i } + else + if i.Sign < 0 then + BitVectorBig ((bigOne <<< int typ) + i, typ) :> BitVector + else BitVectorBig (i, typ) :> BitVector + /// Get a BitVector from a byte array (in little endian). [] static member ofArr (arr: byte []) = - match Array.length arr with - | 1 -> - { Num = uint64 arr.[0]; Length = 8; BigNum = bigNull } + match arr.Length with + | 1 -> BitVectorSmall (uint64 arr.[0], 8) :> BitVector | 2 -> let n = BitConverter.ToUInt16 (arr, 0) |> uint64 - { Num = n; Length = 16; BigNum = bigNull } + BitVectorSmall (n, 16) :> BitVector | 3 -> - let arr = Array.append arr [| 0uy |] - let n = BitConverter.ToUInt32 (arr, 0) |> uint64 - { Num = n; Length = 24; BigNum = bigNull } + let n = BitConverter.ToUInt32 (Array.append arr [| 0uy |], 0) |> uint64 + BitVectorSmall (n, 24) :> BitVector | 4 -> let n = BitConverter.ToUInt32 (arr, 0) |> uint64 - { Num = n; Length = 32; BigNum = bigNull } + BitVectorSmall (n, 32) :> BitVector | 5 -> let arr = Array.append arr [| 0uy; 0uy; 0uy |] let n = BitConverter.ToUInt64 (arr, 0) - { Num = n; Length = 40; BigNum = bigNull } + BitVectorSmall (n, 40) :> BitVector | 6 -> let arr = Array.append arr [| 0uy; 0uy |] let n = BitConverter.ToUInt64 (arr, 0) - { Num = n; Length = 48; BigNum = bigNull } + BitVectorSmall (n, 48) :> BitVector | 7 -> let arr = Array.append arr [| 0uy |] let n = BitConverter.ToUInt64 (arr, 0) - { Num = n; Length = 56; BigNum = bigNull } + BitVectorSmall (n, 56) :> BitVector | 8 -> let n = BitConverter.ToUInt64 (arr, 0) - { Num = n; Length = 64; BigNum = bigNull } - | sz when sz > 8 -> - let arr = Array.append arr [| 0uy |] - { Num = 0UL; Length = sz * 8; BigNum = bigint arr } - | sz -> nSizeErr (sz * 8) - - [] - static member ofBv bv typ = -#if DEBUG - if typ <= 0 then nSizeErr typ else () -#endif - { bv with Length = typ } - + BitVectorSmall (n, 64) :> BitVector + | sz -> + if sz > 8 then + let arr = Array.append arr [| 0uy |] + BitVectorBig (bigint arr, sz * 8) :> BitVector + else nSizeErr (sz * 8) + + /// Get a uint64 value from a BitVector. [] - static member toUInt64 bv = - if bv.Length <= 64 then bv.Num - elif bv.BigNum > bigint 0xFFFFFFFFFFFFFFFFUL then nSizeErr bv.Length - else bv.BigNum |> uint64 + static member toUInt64 (bv: BitVector) = + bv.SmallValue () + /// Get an int64 value from a BitVector. [] - static member toInt64 bv = BitVector.toUInt64 bv |> int64 + static member toInt64 (bv: BitVector) = + bv.SmallValue () |> int64 + /// Get a uint32 value from a BitVector. [] - static member toUInt32 bv = BitVector.toUInt64 bv |> uint32 + static member toUInt32 (bv: BitVector) = + bv.SmallValue () |> uint32 + /// Get an int32 value from a BitVector. [] - static member toInt32 bv = BitVector.toInt64 bv |> int32 + static member toInt32 (bv: BitVector) = + bv.SmallValue () |> int32 + /// Get a numeric value (bigint) from a BitVector. [] - static member getValue bv = - if bv.Length <= 64 then bigint bv.Num else bv.BigNum + static member getValue (bv: BitVector) = + bv.BigValue () + /// Get the type (length of the BitVector). [] static member getType (bv: BitVector) = bv.Length - [] - static member zero (t: RegType) = { Num = 0UL; Length = t; BigNum = bigNull } + /// Get the string representation of a BitVector without appended type info. + [] + static member valToString (n: BitVector) = n.ValToString () - [] - static member one (t: RegType) = { Num = 1UL; Length = t; BigNum = bigNull } + /// Get the string representation of a BitVector. + [] + static member toString (n: BitVector) = n.ToString () - /// True. - static member T = BitVector.one 1 + /// Bitvector of unsigned 8-bit maxvalue. + static member maxUInt8 = BitVector.ofUInt64 0xFFUL 8 - /// False. - static member F = BitVector.zero 1 + /// Bitvector of unsigned 16-bit maxvalue. + static member maxUInt16 = BitVector.ofUInt64 0xFFFFUL 16 - static member inline shiftRightAndCheckOne n len = - bigint.op_BitwiseAnd (bigint.op_RightShift (n, len), 1I) = 0I + /// Bitvector of unsigned 32-bit maxvalue. + static member maxUInt32 = BitVector.ofUInt64 0xFFFFFFFFUL 32 - [] - static member isPositive bv = - let len = int bv.Length - if len <= 64 then ((bv.Num >>> (len - 1)) &&& 1UL) = 0UL - else BitVector.shiftRightAndCheckOne bv.BigNum (len - 1) + /// Bitvector of unsigned 64-bit maxvalue. + static member maxUInt64 = BitVector.ofUInt64 0xFFFFFFFFFFFFFFFFUL 64 - [] - static member isNegative bv = BitVector.isPositive bv |> not + /// Check if the given BitVector is zero. + [] + static member isZero (bv: BitVector) = + bv.IsZero () + + /// Check if the given BitVector is one. + [] + static member isOne (bv: BitVector) = + bv.IsOne () - static member inline castSmall n rt = - match rt with + /// Check if the given BitVector is "false". + [] + static member isFalse (bv: BitVector) = + bv = BitVector.F + + /// Check if the given BitVector is "true". + [] + static member isTrue (bv: BitVector) = + bv = BitVector.T + + /// Check if the given BitVector represents the specified number. + [] + static member isNum (bv: BitVector) (n: uint64) = + if bv.Length <= 64 then bv.SmallValue () = n + else bigint n = bv.BigValue () + + /// BitVector representing a unsigned maximum integer for the given RegType. + [] + static member unsignedMax rt = #if DEBUG - | typ when typ <= 0 -> nSizeErr typ + if rt <= 0 then nSizeErr rt else () #endif - | 1 -> n &&& 1UL - | 2 -> n &&& 0x3UL - | 4 -> n &&& 0xFUL - | 8 -> n &&& 0xFFUL - | 16 -> n &&& 0xFFFFUL - | 32 -> n &&& 0xFFFFFFFFUL - | 64 -> n - | t when t < 64 -> n &&& (RegType.getUInt64Mask rt) - | sz -> nSizeErr sz - - static member inline castBig n newLen = - (RegType.getMask newLen) &&& n - - static member inline private IntBinOp op64 opBigFn bv1 bv2 = - let n1, n2 = bv1.Num, bv2.Num - if bv1.Length <> bv2.Length then raise ArithTypeMismatchException - elif bv1.Length <= 64 then - { bv1 with Num = BitVector.castSmall (op64 n1 n2) bv1.Length } - else - let n = opBigFn (bv1.BigNum, bv2.BigNum) - { bv1 with BigNum = BitVector.castBig n bv1.Length } - - static member inline private FloatBinOp op64 bv1 bv2 = - match bv1.Length, bv2.Length with - | 32, 32 -> - let f1 = BitVector.getFloatValue bv1 - let f2 = BitVector.getFloatValue bv2 - let result = op64 f1 f2 |> float32 |> BitConverter.GetBytes - { bv1 with Num = BitConverter.ToInt32 (result, 0) |> uint64 } - | 64, 64 -> - let f1 = bv1.Num |> int64 |> BitConverter.Int64BitsToDouble - let f2 = bv2.Num |> int64 |> BitConverter.Int64BitsToDouble - let result = op64 f1 f2 |> BitConverter.DoubleToInt64Bits - { bv1 with Num = uint64 result } - | 80, 80 -> - let f1 = BitVector.getFloatValue bv1 - let f2 = BitVector.getFloatValue bv2 - let result = op64 f1 f2 |> BitConverter.DoubleToInt64Bits |> uint64 - BitVector.castAsFloat result 80 - | _ -> raise ArithTypeMismatchException - - static member inline FloatUnOp op64 bv = - match bv.Length with - | 32 -> - let fv = BitVector.getFloatValue bv - let result = op64 fv |> float32 |> BitConverter.GetBytes - { bv with Num = BitConverter.ToInt32 (result, 0) |> uint64 } - | 64 -> - let fv = BitVector.getFloatValue bv - let result = op64 fv |> BitConverter.DoubleToInt64Bits - { bv with Num = uint64 result } - | 80 -> - let fv = BitVector.getFloatValue bv - let result = op64 fv |> BitConverter.DoubleToInt64Bits |> uint64 - BitVector.castAsFloat result 80 - | _ -> raise ArithTypeMismatchException + if rt <= 64 then + BitVectorSmall (UInt64.MaxValue >>> (64 - int rt), rt) :> BitVector + else BitVectorBig ((bigOne <<< int rt) - bigOne, rt) :> BitVector - static member private castAsFloat num typ = - match typ with - | 32 -> - let f64 = num |> int64 |> BitConverter.Int64BitsToDouble - let f32 = f64 |> float32 |> BitConverter.GetBytes - let f32 = BitConverter.ToInt32 (f32, 0) |> uint64 - BitVector.ofUInt64 f32 typ - | 64 -> BitVector.ofUInt64 num typ - | 80 -> - match num with - | 0UL -> BitVector.zero typ - | _ -> - let signOnly = num &&& (1UL <<< 63) >>> 48 - let exp = num &&& 0x7FF0000000000000UL >>> 52 - let expAndSign = exp + 0x3C00UL ||| signOnly |> bigint - let significand = num &&& 0x000FFFFFFFFFFFFFUL - let significand = significand ||| 0x0010000000000000UL <<< 11 |> bigint - { Num = 0UL; BigNum = expAndSign <<< 64 ||| significand; Length = typ } - | _ -> raise ArithTypeMismatchException - - static member private castAsInt f64 typ = - match typ with - | 8 -> - let v = f64 |> int8 |> uint8 |> uint64 - BitVector.ofUInt64 v 8 - | 16 -> - let v = f64 |> int16 |> uint16 |> uint64 - BitVector.ofUInt64 v 16 - | 32 -> - let v = f64 |> int32 - BitVector.ofInt32 v 32 - | 64 -> - let v = f64 |> int64 - BitVector.ofInt64 v 64 - | _ -> raise ArithTypeMismatchException + /// BitVector representing a unsigned minimum integer for the given RegType. + [] + static member unsignedMin rt = +#if DEBUG + if rt <= 0 then nSizeErr rt else () +#endif + if rt <= 64 then BitVectorSmall (0UL, rt) :> BitVector + else BitVectorBig (bigZero, rt) :> BitVector - static member private getFloatValue bv = - match bv.Length with - | 32 -> - let f1 = int32 bv.Num |> BitConverter.GetBytes - BitConverter.ToSingle (f1, 0) |> float - | 64 ->bv.Num |> int64 |> BitConverter.Int64BitsToDouble - | 80 -> - let sign = bv.BigNum >>> 79 <<< 63 |> uint64 - let exponent = bv.BigNum >>> 64 &&& 32767I - let adjustedExp = exponent - 15360I |> uint64 <<< 52 - let significand = - bv.BigNum &&& (bigint 0x7FFFFFFFFFFFFFFFUL) |> uint64 >>> 11 - let f64 = sign ||| adjustedExp ||| significand - f64 |> int64 |> BitConverter.Int64BitsToDouble - | _ -> raise ArithTypeMismatchException + /// BitVector representing a signed maximum integer for the given RegType. + [] + static member signedMax rt = +#if DEBUG + if rt <= 0 then nSizeErr rt else () +#endif + if rt <= 64 then + BitVectorSmall (UInt64.MaxValue >>> (65 - int rt), rt) :> BitVector + else BitVectorBig ((bigOne <<< (int rt - 1)) - bigOne, rt) :> BitVector + /// BitVector representing a signed minimum integer for the given RegType. + [] + static member signedMin rt = +#if DEBUG + if rt <= 0 then nSizeErr rt else () +#endif + if rt <= 64 then BitVectorSmall (1UL <<< (int rt - 1), rt) :> BitVector + else BitVectorBig (bigOne <<< (int rt - 1), rt) :> BitVector + + /// Does the bitvector represent an unsigned max value? + [] + static member isUnsignedMax (bv: BitVector) = + BitVector.unsignedMax bv.Length = bv + + /// Does the bitvector represent a signed max value? + [] + static member isSignedMax (bv: BitVector) = + BitVector.signedMax bv.Length = bv + + /// Does the bitvector represent a signed min value? + [] + static member isSignedMin (bv: BitVector) = + BitVector.signedMin bv.Length = bv + + /// Is the bitvector positive? + [] + static member isPositive (bv: BitVector) = bv.IsPositive () + + /// Is the bitvector negative? + [] + static member isNegative (bv: BitVector) = bv.IsNegative () + + /// BitVector addition. [] - static member add v1 v2 = BitVector.IntBinOp (+) (bigint.Add) v1 v2 + static member inline add (v1: BitVector) (v2: BitVector) = v1.Add v2 + /// BitVector subtraction. [] - static member sub v1 v2 = BitVector.IntBinOp (-) (bigint.Subtract) v1 v2 + static member inline sub (v1: BitVector) (v2: BitVector) = v1.Sub v2 + /// BitVector multiplication. [] - static member mul v1 v2 = BitVector.IntBinOp (*) (bigint.Multiply) v1 v2 + static member inline mul (v1: BitVector) (v2: BitVector) = v1.Mul v2 + + /// BitVector signed division. + [] + static member inline sdiv (v1: BitVector) (v2: BitVector) = v1.SDiv v2 + + /// BitVector unsigned division. + [] + static member inline div (v1: BitVector) (v2: BitVector) = v1.Div v2 + + /// BitVector signed modulo. + [] + static member inline smodulo (v1: BitVector) (v2: BitVector) = v1.SMod v2 + + /// BitVector unsigned modulo. + [] + static member inline modulo (v1: BitVector) (v2: BitVector) = v1.Mod v2 + + /// BitVector bitwise AND. + [] + static member inline band (v1: BitVector) (v2: BitVector) = v1.And v2 + + /// BitVector bitwise OR. + [] + static member inline bor (v1: BitVector) (v2: BitVector) = v1.Or v2 + + /// BitVector bitwise XOR. + [] + static member inline bxor (v1: BitVector) (v2: BitVector) = v1.Xor v2 + + /// BitVector logical shift-left. + [] + static member inline shl (v1: BitVector) (v2: BitVector) = v1.Shl v2 + + /// BitVector logical shift-right. + [] + static member inline shr (v1: BitVector) (v2: BitVector) = v1.Shr v2 + + /// BitVector arithmetic shift-right. + [] + static member inline sar (v1: BitVector) (v2: BitVector) = v1.Sar v2 + + /// BitVector bitwise NOT. + [] + static member inline bnot (v1: BitVector) = v1.Not () + + /// BitVector negation. + [] + static member inline neg (v1: BitVector) = v1.Neg () + + /// BitVector type cast. + [] + static member inline cast (v1: BitVector) targetLen = v1.Cast targetLen + /// BitVector extraction. + [] + static member inline extract (v1: BitVector) rt pos = v1.Extract rt pos + + /// BitVector concatenation. + [] + static member inline concat (v1: BitVector) (v2: BitVector) = v1.Concat v2 + + /// BitVector sign-extension. + [] + static member inline sext (v1: BitVector) targetLen = v1.SExt targetLen + + /// BitVector zero-extension. + [] + static member inline zext (v1: BitVector) targetLen = v1.ZExt targetLen + + /// BitVector equal. + [] + static member inline eq (v1: BitVector) (v2: BitVector) = v1.Eq v2 + + /// BitVector not equal. + [] + static member inline neq (v1: BitVector) (v2: BitVector) = v1.Neq v2 + + /// BitVector greater than. + [] + static member inline gt (v1: BitVector) (v2: BitVector) = v1.Gt v2 + + /// BitVector greater than or equal. + [] + static member inline ge (v1: BitVector) (v2: BitVector) = v1.Ge v2 + + /// BitVector signed greater than. + [] + static member inline sgt (v1: BitVector) (v2: BitVector) = v1.SGt v2 + + /// BitVector signed greater than or equal. + [] + static member inline sge (v1: BitVector) (v2: BitVector) = v1.SGe v2 + + /// BitVector less than. + [] + static member inline lt (v1: BitVector) (v2: BitVector) = v1.Lt v2 + + /// BitVector less than or equal. + [] + static member inline le (v1: BitVector) (v2: BitVector) = v1.Le v2 + + /// BitVector signed less than. + [] + static member inline slt (v1: BitVector) (v2: BitVector) = v1.SLt v2 + + /// BitVector signed less than or equal. + [] + static member inline sle (v1: BitVector) (v2: BitVector) = v1.SLe v2 + + /// BitVector absolute value. + [] + static member inline abs (v1: BitVector) = v1.Abs () + + /// BitVector floating point addition. [] - static member fadd v1 v2 = BitVector.FloatBinOp (+) v1 v2 + static member inline fadd (v1: BitVector) (v2: BitVector) = v1.FAdd v2 + /// BitVector floating point subtraction. [] - static member fsub v1 v2 = BitVector.FloatBinOp (-) v1 v2 + static member inline fsub (v1: BitVector) (v2: BitVector) = v1.FSub v2 + /// BitVector floating point multiplication. [] - static member fmul v1 v2 = BitVector.FloatBinOp (*) v1 v2 + static member inline fmul (v1: BitVector) (v2: BitVector) = v1.FMul v2 - [] - static member neg bv = - match bv.Length with - | 1 -> bv - | 8 -> { bv with Num = (- (int8 bv.Num)) |> uint8 |> uint64 } - | 16 -> { bv with Num = (- (int16 bv.Num)) |> uint16 |> uint64 } - | 32 -> { bv with Num = (- (int32 bv.Num)) |> uint32 |> uint64 } - | 64 -> { bv with Num = (- (int64 bv.Num)) |> uint64 } - | t when t < 64 -> - { bv with Num = ((~~~ bv.Num) + 1UL) &&& (RegType.getUInt64Mask t)} - | _ -> - let n = bigint.Pow (2I, int bv.Length) - bv.BigNum - { bv with BigNum = BitVector.castBig n bv.Length } - - [] - static member band v1 v2 = BitVector.IntBinOp (&&&) (bigint.op_BitwiseAnd) v1 v2 - - [] - static member bor v1 v2 = BitVector.IntBinOp (|||) (bigint.op_BitwiseOr) v1 v2 - - [] - static member bxor v1 v2 = BitVector.IntBinOp (^^^) (bigint.op_ExclusiveOr) v1 v2 - - [] - static member bnot bv = - if bv.Length = 1 then - { bv with Num = if bv.Num = 0UL then 1UL else 0UL } - elif bv.Length <= 64 then - { bv with Num = BitVector.castSmall (~~~ bv.Num) bv.Length } - else - { bv with BigNum = bigint.Pow (2I, int bv.Length) - bv.BigNum - 1I } + /// BitVector floating point division. + [] + static member inline fdiv (v1: BitVector) (v2: BitVector) = v1.FDiv v2 + /// BitVector floating point logarithm. + [] + static member inline flog (v1: BitVector) (v2: BitVector) = v1.FLog v2 + + /// BitVector floating point power. + [] + static member inline fpow (v1: BitVector) (v2: BitVector) = v1.FPow v2 + + /// BitVector floating point casting. + [] + static member inline fcast (v1: BitVector) rt = v1.FCast rt + + /// BitVector integer to float conversion. + [] + static member inline itof (v1: BitVector) rt = v1.Itof rt + + /// BitVector float to integer conversion with truncation. + [] + static member inline ftoitrunc (v1: BitVector) rt = v1.FtoiTrunc rt + + /// BitVector float to integer conversion with round. + [] + static member inline ftoiround (v1: BitVector) rt = v1.FtoiRound rt + + /// BitVector float to integer conversion with flooring. + [] + static member inline ftoifloor (v1: BitVector) rt = v1.FtoiFloor rt + + /// BitVector float to integer conversion with ceiling. + [] + static member inline ftoiceil (v1: BitVector) rt = v1.FtoiCeil rt + + /// BitVector square root. [] - static member fsqrt v = BitVector.FloatUnOp sqrt v + static member inline fsqrt (v1: BitVector) = v1.FSqrt () + /// BitVector tangent. [] - static member ftan v = BitVector.FloatUnOp tan v - - [] - static member fatan v = BitVector.FloatUnOp atan v + static member inline ftan (v1: BitVector) = v1.FTan () + /// BitVector sine. [] - static member fsin v = BitVector.FloatUnOp sin v + static member inline fsin (v1: BitVector) = v1.FSin () + /// BitVector cosine. [] - static member fcos v = BitVector.FloatUnOp cos v + static member inline fcos (v1: BitVector) = v1.FCos () - [] - static member eq v1 v2 = - if v1.Length = v2.Length && v1.Num = v2.Num && v1.BigNum = v2.BigNum then - BitVector.T - else BitVector.F + /// BitVector arc tangent. + [] + static member inline fatan (v1: BitVector) = v1.FATan () - [] - static member aeq v1 v2 = - match v1.Length, v2.Length with - | 80, 80 -> - let shifter = BitVector.ofInt32 12 80 - let v1 = BitVector.shr v1 shifter - let v2 = BitVector.shr v2 shifter - BitVector.eq v1 v2 - | t1, _ -> - let shifter = BitVector.ofInt32 1 t1 - let v1 = BitVector.shr v1 shifter - let v2 = BitVector.shr v2 shifter - BitVector.eq v1 v2 - - [] - static member neq v1 v2 = - if v1.Length = v2.Length && v1.Num = v2.Num && v1.BigNum = v2.BigNum then - BitVector.F - else BitVector.T + /// BitVector floating point greater than. + [] + static member inline fgt (v1: BitVector) (v2: BitVector) = v1.FGt v2 - static member inline unsignedComp v1 v2 op bigop = - if v1.Length <> v2.Length then raise ArithTypeMismatchException - elif v1.Length <= 64 then - if op v1.Num v2.Num then BitVector.T else BitVector.F - else - if bigop v1.BigNum v2.BigNum then BitVector.T else BitVector.F + /// BitVector floating point greater than or equal. + [] + static member inline fge (v1: BitVector) (v2: BitVector) = v1.FGe v2 - [] - static member gt v1 v2 = BitVector.unsignedComp v1 v2 (>) (>) + /// BitVector floating point less than. + [] + static member inline flt (v1: BitVector) (v2: BitVector) = v1.FLt v2 - [] - static member ge v1 v2 = BitVector.unsignedComp v1 v2 (>=) (>=) + /// BitVector floating point less than or equal. + [] + static member inline fle (v1: BitVector) (v2: BitVector) = v1.FLe v2 - [] - static member lt v1 v2 = BitVector.unsignedComp v1 v2 (<) (<) + /// BitVector addition. + static member inline (+) (v1: BitVector, v2: uint64) = v1.Add v2 - [] - static member le v1 v2 = BitVector.unsignedComp v1 v2 (<=) (<=) + /// BitVector subtraction. + static member inline (-) (v1: BitVector, v2: uint64) = v1.Sub v2 - static member inline signedComp v1 v2 op8 op16 op32 op64 opBigFn = - if v1.Length <> v2.Length then raise ArithTypeMismatchException - match v1.Length with - | 8 -> - if op8 (int8 v1.Num) (int8 v2.Num) then BitVector.T else BitVector.F - | 16 -> - if op16 (int16 v1.Num) (int16 v2.Num) then BitVector.T else BitVector.F - | 32 -> - if op32 (int32 v1.Num) (int32 v2.Num) then BitVector.T else BitVector.F - | 64 -> - if op64 (int64 v1.Num) (int64 v2.Num) then BitVector.T else BitVector.F - | t when t < 64 -> - if BitVector.isPositive v1 && BitVector.isNegative v2 then BitVector.F - elif BitVector.isNegative v1 && BitVector.isPositive v2 then BitVector.T - elif BitVector.isNegative v1 && BitVector.isNegative v2 then - if op64 (int64 v1.Num) (int64 v2.Num) then BitVector.F - else BitVector.T - else - if op64 (int64 v1.Num) (int64 v2.Num) then BitVector.T - else BitVector.F - | _ -> - if BitVector.isPositive v1 && BitVector.isNegative v2 then BitVector.F - elif BitVector.isNegative v1 && BitVector.isPositive v2 then BitVector.T - elif BitVector.isNegative v1 && BitVector.isNegative v2 then - if opBigFn (v1.BigNum, v2.BigNum) then BitVector.F - else BitVector.T - else - if opBigFn (v1.BigNum, v2.BigNum) then BitVector.T - else BitVector.F + /// BitVector multiplication. + static member inline (*) (v1: BitVector, v2: uint64) = v1.Mul v2 - [] - static member slt v1 v2 = - BitVector.signedComp v1 v2 (<) (<) (<) (<) bigint.op_LessThan + /// BitVector division. + static member inline (/) (v1: BitVector, v2: uint64) = v1.Div v2 - [] - static member sle v1 v2 = - BitVector.signedComp v1 v2 (<=) (<=) (<=) (<=) (bigint.op_LessThanOrEqual) + /// BitVector modulo. + static member inline (%) (v1: BitVector, v2: uint64) = v1.Mod v2 - [] - static member sgt v1 v2 = BitVector.slt v2 v1 + /// BitVector bitwise AND. + static member inline (&&&) (v1: BitVector, v2: uint64) = v1.And v2 - [] - static member sge v1 v2 = BitVector.sle v2 v1 + /// BitVector bitwise OR. + static member inline (|||) (v1: BitVector, v2: uint64) = v1.Or v2 - static member inline private floatComp v1 v2 op = - let fv1 = BitVector.getFloatValue v1 - let fv2 = BitVector.getFloatValue v2 - if op fv1 fv2 then BitVector.T else BitVector.F + /// BitVector bitwise XOR. + static member inline (^^^) (v1: BitVector, v2: uint64) = v1.Xor v2 - [] - static member fge v1 v2 = BitVector.floatComp v1 v2 (>=) + /// BitVector addition. + static member inline (+) (v1: BitVector, v2: BitVector) = v1.Add v2 - [] - static member fle v1 v2 = BitVector.floatComp v1 v2 (<=) + /// BitVector subtraction. + static member inline (-) (v1: BitVector, v2: BitVector) = v1.Sub v2 - [] - static member fgt v1 v2 = BitVector.floatComp v1 v2 (>) + /// BitVector multiplication. + static member inline (*) (v1: BitVector, v2: BitVector) = v1.Mul v2 - [] - static member flt v1 v2 = BitVector.floatComp v1 v2 (<) + /// BitVector unsigned division. + static member inline (/) (v1: BitVector, v2: BitVector) = v1.Div v2 - [] - static member cast (bv: BitVector) newLen = - if bv.Length = newLen then bv - elif bv.Length <= 64 && newLen <= 64 then - { bv with Num = BitVector.castSmall bv.Num newLen; Length = newLen } - elif bv.Length <= 64 && newLen > 64 then - { Num = 0UL; Length = newLen - BigNum = BitVector.castBig (bigint bv.Num) newLen } - elif bv.Length > 64 && newLen <= 64 then - { Num = BitVector.castSmall (BitVector.castBig bv.BigNum newLen |> uint64) - newLen; - Length = newLen; BigNum = bigNull } - else - { bv with BigNum = BitVector.castBig bv.BigNum newLen; Length = newLen } + /// BitVector signed division. + static member inline (?/) (v1: BitVector, v2: BitVector) = v1.SDiv v2 - [] - static member extract (bv: BitVector) newLen pos = - if bv.Length = newLen then bv - elif bv.Length <= 64 then - { bv with Num = BitVector.castSmall (bv.Num >>> pos) newLen - Length = newLen } - elif bv.Length > 64 && newLen <= 64 then - { Num = BitVector.castSmall (BitVector.castBig (bv.BigNum >>> pos) newLen - |> uint64) newLen; - Length = newLen; BigNum = bigNull } - else - { bv with - BigNum = BitVector.castBig (bv.BigNum >>> pos) newLen - Length = newLen } + /// BitVector unsigned modulo. + static member inline (%) (v1: BitVector, v2: BitVector) = v1.Mod v2 - [] - static member div v1 v2 = BitVector.IntBinOp (/) (bigint.Divide) v1 v2 + /// BitVector signed modulo. + static member inline (?%) (v1: BitVector, v2: BitVector) = v1.SMod v2 - [] - static member fdiv v1 v2 = BitVector.FloatBinOp (/) v1 v2 + /// BitVector bitwise AND. + static member inline (&&&) (v1: BitVector, v2: BitVector) = v1.And v2 - [] - static member fpow v1 v2 = - let pow64 f1 f2 = Math.Pow (f1, f2) - BitVector.FloatBinOp pow64 v1 v2 + /// BitVector bitwise OR. + static member inline (|||) (v1: BitVector, v2: BitVector) = v1.Or v2 - [] - static member flog v1 v2 = - let log64 f1 f2 = Math.Log (f2, f1) - BitVector.FloatBinOp log64 v1 v2 + /// BitVector bitwise XOR. + static member inline (^^^) (v1: BitVector, v2: BitVector) = v1.Xor v2 - [] - static member sdiv v1 v2 = - let sign1, sign2 = BitVector.isPositive v1, BitVector.isPositive v2 - let bv1 = if sign1 then v1 else BitVector.neg v1 - let bv2 = if sign2 then v2 else BitVector.neg v2 - let bv = BitVector.div bv1 bv2 - if sign1 = sign2 then bv - else BitVector.neg bv - - [] - static member modulo v1 v2 = BitVector.IntBinOp (%) (bigint.op_Modulus) v1 v2 - - [] - static member smodulo v1 v2 = - let sign1, sign2 = BitVector.isPositive v1, BitVector.isPositive v2 - let bv1 = if sign1 then v1 else BitVector.neg v1 - let bv2 = if sign2 then v2 else BitVector.neg v2 - let bv = BitVector.modulo bv1 bv2 - if BitVector.isZero bv then bv + /// BitVector bitwise not. + static member inline (~~~) (v1: BitVector) = v1.Not () + + /// BitVector negation. + static member inline (~-) (v1: BitVector) = v1.Neg () + +/// This is a BitVector with its length less than or equal to 64. This is +/// preferred because all the operations will be much faster than BitVectorBig. +and BitVectorSmall (n, len) = + inherit BitVector(len) + +#if DEBUG + do if len > 64 then raise ArithTypeMismatchException else () +#endif + + new (n: int64, len) = BitVectorSmall (uint64 n, len) + new (n: int32, len) = BitVectorSmall (uint64 n, len) + new (n: int16, len) = BitVectorSmall (uint64 n, len) + new (n: int8, len) = BitVectorSmall (uint64 n, len) + new (n: uint32, len) = BitVectorSmall (uint64 n, len) + new (n: uint16, len) = BitVectorSmall (uint64 n, len) + new (n: uint8, len) = BitVectorSmall (uint64 n, len) + + member __.Value with get(): uint64 = n + + override __.ValToString () = String.u64ToHex n + + override __.Equals obj = + match obj with + | :? BitVectorSmall as obj -> len = obj.Length && n = obj.Value + | _ -> false + + override __.ApproxEq (rhs: BitVector) = +#if DEBUG + if len <> rhs.Length then raise ArithTypeMismatchException else () +#endif + let shifter = BitVector.ofInt32 1 len + let v1 = __.Shr shifter + let v2 = rhs.Shr shifter + v1.Eq v2 + + override __.IsPositive () = isSmallPositive len n + + override __.IsNegative () = not <| isSmallPositive len n + + override __.GetHashCode () = + HashCode.Combine (n, len) + + override __.ToString () = + __.ValToString () + ":" + RegType.toString len + + override __.SmallValue () = n + + override __.BigValue () = bigint n + + override __.IsZero () = n = 0UL + + override __.IsOne () = n = 1UL + + override __.Add (rhs: uint64) = + BitVectorSmall (n + rhs |> adaptSmall len, len) :> BitVector + + override __.Add (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorSmall (n + rhs.SmallValue () |> adaptSmall len, len) :> BitVector + + override __.Sub (rhs: uint64) = + BitVectorSmall (n - rhs |> adaptSmall len, len) :> BitVector + + override __.Sub (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorSmall (n - rhs.SmallValue () |> adaptSmall len, len) :> BitVector + + override __.Mul (rhs: uint64) = + BitVectorSmall (n * rhs |> adaptSmall len, len) :> BitVector + + override __.Mul (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorSmall (n * rhs.SmallValue () |> adaptSmall len, len) :> BitVector + + override __.SDiv (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let v1 = n + let v2 = rhs.SmallValue () + let isPos1 = isSmallPositive len v1 + let isPos2 = isSmallPositive len v2 + let v1 = int64 (if isPos1 then v1 else ((~~~ v1) + 1UL) |> adaptSmall len) + let v2 = int64 (if isPos2 then v2 else ((~~~ v2) + 1UL) |> adaptSmall len) + let result = if isPos1 = isPos2 then v1 / v2 else - (v1 / v2) + BitVectorSmall (result |> uint64 |> adaptSmall len, len) :> BitVector + + override __.Div (rhs: uint64) = + BitVectorSmall (n / rhs |> adaptSmall len, len) :> BitVector + + override __.Div (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorSmall (n / rhs.SmallValue () |> adaptSmall len, len) :> BitVector + + override __.SMod (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let v1 = n + let v2 = rhs.SmallValue () + let isPos1 = isSmallPositive len v1 + let isPos2 = isSmallPositive len v2 + let v1 = int64 (if isPos1 then v1 else ((~~~ v1) + 1UL) |> adaptSmall len) + let v2 = int64 (if isPos2 then v2 else ((~~~ v2) + 1UL) |> adaptSmall len) + let result = if isPos1 then v1 % v2 else - (v1 % v2) + BitVectorSmall (result |> uint64 |> adaptSmall len, len) :> BitVector + + override __.Mod (rhs: uint64) = + BitVectorSmall (n % rhs |> adaptSmall len, len) :> BitVector + + override __.Mod (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorSmall (n % rhs.SmallValue () |> adaptSmall len, len) :> BitVector + + override __.And (rhs: uint64) = + BitVectorSmall (n &&& rhs |> adaptSmall len, len) :> BitVector + + override __.And (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorSmall (n &&& rhs.SmallValue () |> adaptSmall len, len) + :> BitVector + + override __.Or (rhs: uint64) = + BitVectorSmall (n ||| rhs |> adaptSmall len, len) :> BitVector + + override __.Or (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorSmall (n ||| rhs.SmallValue () |> adaptSmall len, len) + :> BitVector + + override __.Xor (rhs: uint64) = + BitVectorSmall (n ^^^ rhs |> adaptSmall len, len) :> BitVector + + override __.Xor (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorSmall (n ^^^ rhs.SmallValue () |> adaptSmall len, len) + :> BitVector + + override __.Shl (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let v1 = n + let v2 = rhs.SmallValue () + if v2 >= 64UL then BitVectorSmall (0UL, len) :> BitVector + else BitVectorSmall (adaptSmall len (v1 <<< int v2), len) :> BitVector + + override __.Shr (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let v1 = n + let v2 = rhs.SmallValue () |> uint16 |> int + (* In .NET, 1UL >>> 63 = 0, but 1UL >>> 64 = 1 *) + BitVectorSmall (v1 >>> (min v2 63), len) :> BitVector + + override __.Sar (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let v1 = n + let v2 = rhs.SmallValue () |> uint16 |> int + (* In .NET, 1UL >>> 63 = 0, but 1UL >>> 64 = 1 *) + let res = v1 >>> (min v2 63) + if len = 1 then + if v2 = 0 then __ :> BitVector else BitVector.zero len + elif isSmallPositive len v1 then BitVectorSmall (res, len) :> BitVector else - match sign1, sign2 with - | true, true -> bv - | true, false -> BitVector.add bv v2 - | false, true -> BitVector.sub v2 bv - | false, false -> BitVector.neg bv + let pad = + (UInt64.MaxValue >>> (64 - int len)) + - (if int len <= v2 then 0UL + else UInt64.MaxValue >>> (64 - (int len - v2))) + BitVectorSmall (res ||| pad, len) :> BitVector - [] - static member shl v1 v2 = - let len = v1.Length - if len <> v2.Length then raise ArithTypeMismatchException - elif len = 1 then - { v1 with Num = if v2.Num = 0UL then v1.Num else 0UL } - elif len <= 64 then - { v1 with Num = if v2.Num >= 64UL then 0UL - else BitVector.castSmall (v1.Num <<< int v2.Num) len } + override __.Not () = + BitVectorSmall ((~~~ n) |> adaptSmall len, len) :> BitVector + + override __.Neg () = + BitVectorSmall (((~~~ n) + 1UL) |> adaptSmall len, len) :> BitVector + + override __.Cast targetLen = + if targetLen <= 64 then + BitVectorSmall (adaptSmall targetLen n, targetLen) :> BitVector else - let n = bigint.op_LeftShift (v1.BigNum, int v2.BigNum) - { v1 with BigNum = BitVector.castBig n len } + BitVectorBig (adaptBig targetLen (__.BigValue ()), targetLen) :> BitVector - [] - static member shr v1 v2 = - if v1.Length <> v2.Length then raise ArithTypeMismatchException - elif v1.Length = 1 then - { v1 with Num = if v2.Num = 0UL then v1.Num else 0UL } - elif v1.Length <= 64 then - (* In .NET, 1UL >>> 63 = 0, but 1UL >>> 64 = 1 *) - { v1 with Num = v1.Num >>> min (int v2.Num) 0x3f } + override __.Extract targetLen pos = + if len < targetLen then raise ArithTypeMismatchException + elif len = targetLen then __ :> BitVector else - { v1 with BigNum = bigint.op_RightShift (v1.BigNum, int v2.BigNum) } + BitVectorSmall (adaptSmall targetLen (n >>> pos), targetLen) :> BitVector - [] - static member sar v1 v2 = - let n1, n2 = v1.Num, v2.Num - let l1, l2 = v1.Length, v2.Length - if l1 <> l2 then raise ArithTypeMismatchException - match l1 with - | 1 -> { v1 with Num = if n2 = 0UL then n1 else 0UL } - | 8 -> - { v1 with Num = (int8 n1 >>> min (int n2) 0x7) |> uint8 |> uint64 } - | 16 -> - { v1 with Num = (int16 n1 >>> min (int n2) 0xf) |> uint16 |> uint64 } - | 32 -> - { v1 with Num = (int32 n1 >>> min (int n2) 0x1f) |> uint32 |> uint64 } - | 64 -> - { v1 with Num = (int64 n1 >>> min (int n2) 0x3f) |> uint64 } - | t when t < 64 -> - let res = BitVector.shr v1 v2 - if BitVector.isPositive v1 then res + override __.Concat (rhs: BitVector) = + let rLen = rhs.Length + let targetLen = len + rLen + if targetLen <= 64 then + BitVectorSmall ((n <<< int rLen) + rhs.SmallValue (), targetLen) + :> BitVector + else + let v1 = __.BigValue () + let v2 = rhs.BigValue () + BitVectorBig ((v1 <<< int rLen) + v2, targetLen) :> BitVector + + override __.SExt targetLen = + if targetLen < len then raise ArithTypeMismatchException + elif targetLen = len then __ :> BitVector + elif targetLen <= 64 then + if isSmallPositive len n then BitVectorSmall (n, targetLen) :> BitVector else - let pad = RegType.getUInt64Mask v1.Length - let pad = - pad - (RegType.getUInt64Mask (v1.Length - (1 * int v2.Num))) - { res with Num = (res.Num ||| pad) } - | _ -> - let res = BitVector.shr v1 v2 - if BitVector.isPositive v1 then res + let mask = + (UInt64.MaxValue >>> (64 - int targetLen)) + - (UInt64.MaxValue >>> (64 - int len)) + BitVectorSmall (n + mask, targetLen) :> BitVector + else + let n' = adaptBig targetLen (__.BigValue ()) + if isSmallPositive len n then BitVectorBig (n', targetLen) :> BitVector else - let pad = BigInteger.getMask (int v1.Length) - let pad = pad - (BigInteger.getMask (int v1.Length - int v2.BigNum)) - { res with BigNum = (bigint.op_BitwiseOr (res.BigNum, pad)) } + let mask = (bigOne <<< int targetLen) - (bigOne <<< int len) + BitVectorBig (n' + mask, targetLen) :> BitVector + + override __.ZExt targetLen = + if targetLen < len then raise ArithTypeMismatchException + elif targetLen = len then __ :> BitVector + elif targetLen <= 64 then + BitVectorSmall (adaptSmall targetLen n, targetLen) :> BitVector + else + BitVectorBig (adaptBig targetLen (__.BigValue ()), targetLen) :> BitVector - [] - static member concat v1 v2 = - let len1 = v1.Length - let len2 = v2.Length - let targetLen = len1 + len2 - if targetLen <= 64 then - let n = (v1.Num <<< int len2) + v2.Num - { Num = n; Length = targetLen; BigNum = bigNull } + override __.Eq rhs = + if len = rhs.Length && n = rhs.SmallValue () then BitVector.T + else BitVector.F + + override __.Neq rhs = + if len = rhs.Length && n = rhs.SmallValue () then BitVector.F + else BitVector.T + + override __.Gt rhs = + if len <> rhs.Length then raise ArithTypeMismatchException + elif n > rhs.SmallValue () then BitVector.T + else BitVector.F + + override __.Ge rhs = + if len <> rhs.Length then raise ArithTypeMismatchException + elif n >= rhs.SmallValue () then BitVector.T + else BitVector.F + + override __.SGt rhs = + if len <> rhs.Length then raise ArithTypeMismatchException + else + let v1 = n + let v2 = rhs.SmallValue () + let isPos1 = isSmallPositive len v1 + let isPos2 = isSmallPositive len v2 + match isPos1, isPos2 with + | true, false -> BitVector.T + | false, true -> BitVector.F + | _ -> if v1 > v2 then BitVector.T else BitVector.F + + override __.SGe rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else - let v1 = BitVector.getValue v1 - let v2 = BitVector.getValue v2 - let n = bigint.op_LeftShift (v1, int len2) + v2 - { Num = 0UL; Length = targetLen; BigNum = n } - - [] - static member fext bv typ = - match bv.Length, typ with - | 32, 32 | 64, 64 | 80, 80 -> bv - | 32, _ -> - let f32 = bv.Num |> int32 |> BitConverter.GetBytes - let f32 = BitConverter.ToSingle (f32, 0) |> float - let f64 = BitConverter.DoubleToInt64Bits f32 |> uint64 - BitVector.castAsFloat f64 typ - | 64, _ -> BitVector.castAsFloat bv.Num typ - | 80, _ -> - let sign = bv.BigNum >>> 79 <<< 63 |> uint64 - let exponent = bv.BigNum >>> 64 &&& 32767I - let adjustedExp = exponent - 15360I |> uint64 <<< 52 - let significand = - bv.BigNum &&& (bigint 0x7FFFFFFFFFFFFFFFUL) |> uint64 >>> 11 - let significand = - if BitVector.extract bv 1 10 = BitVector.T then significand + 1UL - else significand - BitVector.castAsFloat (sign ||| adjustedExp ||| significand) typ + let v1 = n + let v2 = rhs.SmallValue () + let isPos1 = isSmallPositive len v1 + let isPos2 = isSmallPositive len v2 + match isPos1, isPos2 with + | true, false -> BitVector.T + | false, true -> BitVector.F + | _ -> if v1 >= v2 then BitVector.T else BitVector.F + + override __.Lt rhs = + if len <> rhs.Length then raise ArithTypeMismatchException + elif n < rhs.SmallValue () then BitVector.T + else BitVector.F + + override __.Le rhs = + if len <> rhs.Length then raise ArithTypeMismatchException + elif n <= rhs.SmallValue () then BitVector.T + else BitVector.F + + override __.SLt rhs = + if len <> rhs.Length then raise ArithTypeMismatchException + else + let v1 = n + let v2 = rhs.SmallValue () + let isPos1 = isSmallPositive len v1 + let isPos2 = isSmallPositive len v2 + match isPos1, isPos2 with + | true, false -> BitVector.F + | false, true -> BitVector.T + | _ -> if v1 < v2 then BitVector.T else BitVector.F + + override __.SLe rhs = + if len <> rhs.Length then raise ArithTypeMismatchException + else + let v1 = n + let v2 = rhs.SmallValue () + let isPos1 = isSmallPositive len v1 + let isPos2 = isSmallPositive len v2 + match isPos1, isPos2 with + | true, false -> BitVector.F + | false, true -> BitVector.T + | _ -> if v1 <= v2 then BitVector.T else BitVector.F + + override __.Abs () = + if isSmallPositive len n then __ :> BitVector + else __.Neg () + + override __.FAdd rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 32 -> + let v1 = __.SmallValue () |> toFloat32 + let v2 = rhs.SmallValue () |> toFloat32 + let bs = v1 + v2 |> BitConverter.GetBytes + BitVectorSmall (BitConverter.ToInt32 (bs, 0) |> uint64, len) :> BitVector + | 64 -> + let v1 = __.SmallValue () |> toFloat64 + let v2 = rhs.SmallValue () |> toFloat64 + let r = v1 + v2 |> BitConverter.DoubleToInt64Bits |> uint64 + BitVectorSmall (r, len) :> BitVector | _ -> raise ArithTypeMismatchException - [] - static member ftoiceil bv typ = - let fValue = BitVector.getFloatValue bv |> ceil - BitVector.castAsInt fValue typ + override __.FSub rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 32 -> + let v1 = __.SmallValue () |> toFloat32 + let v2 = rhs.SmallValue () |> toFloat32 + let bs = v1 - v2 |> BitConverter.GetBytes + BitVectorSmall (BitConverter.ToInt32 (bs, 0) |> uint64, len) :> BitVector + | 64 -> + let v1 = __.SmallValue () |> toFloat64 + let v2 = rhs.SmallValue () |> toFloat64 + let r = v1 - v2 |> BitConverter.DoubleToInt64Bits |> uint64 + BitVectorSmall (r, len) :> BitVector + | _ -> raise ArithTypeMismatchException - [] - static member ftoifloor bv typ = - let fValue = BitVector.getFloatValue bv |> floor - BitVector.castAsInt fValue typ + override __.FMul rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 32 -> + let v1 = __.SmallValue () |> toFloat32 + let v2 = rhs.SmallValue () |> toFloat32 + let bs = v1 * v2 |> BitConverter.GetBytes + BitVectorSmall (BitConverter.ToInt32 (bs, 0) |> uint64, len) :> BitVector + | 64 -> + let v1 = __.SmallValue () |> toFloat64 + let v2 = rhs.SmallValue () |> toFloat64 + let r = v1 * v2 |> BitConverter.DoubleToInt64Bits |> uint64 + BitVectorSmall (r, len) :> BitVector + | _ -> raise ArithTypeMismatchException - [] - static member ftoiround bv typ = - let fValue = BitVector.getFloatValue bv |> round - BitVector.castAsInt fValue typ + override __.FDiv rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 32 -> + let v1 = __.SmallValue () |> toFloat32 + let v2 = rhs.SmallValue () |> toFloat32 + let bs = v1 / v2 |> BitConverter.GetBytes + BitVectorSmall (BitConverter.ToInt32 (bs, 0) |> uint64, len) :> BitVector + | 64 -> + let v1 = __.SmallValue () |> toFloat64 + let v2 = rhs.SmallValue () |> toFloat64 + let r = v1 / v2 |> BitConverter.DoubleToInt64Bits |> uint64 + BitVectorSmall (r, len) :> BitVector + | _ -> raise ArithTypeMismatchException - [] - static member ftoitrunc bv typ = - let fValue = - BitVector.getFloatValue bv |> truncate - BitVector.castAsInt fValue typ - - [] - static member itof bv typ = - let signedFloat = - match bv.Length with - | 8 -> bv.Num |> int8 |> float - | 16 -> bv.Num |> int16 |> float - | 32 -> bv.Num |> int32 |> float - | 64 -> bv.Num |> int64 |> float + override __.FLog rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 32 -> + let v1 = __.SmallValue () |> toFloat32 + let v2 = rhs.SmallValue () |> toFloat32 + let bs = MathF.Log (v2, v1) |> BitConverter.GetBytes + BitVectorSmall (BitConverter.ToInt32 (bs, 0) |> uint64, len) :> BitVector + | 64 -> + let v1 = __.SmallValue () |> toFloat64 + let v2 = rhs.SmallValue () |> toFloat64 + let r = Math.Log (v2, v1) |> BitConverter.DoubleToInt64Bits |> uint64 + BitVectorSmall (r, len) :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FPow rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 32 -> + let v1 = __.SmallValue () |> toFloat32 + let v2 = rhs.SmallValue () |> toFloat32 + let bs = MathF.Pow (v1, v2) |> BitConverter.GetBytes + BitVectorSmall (BitConverter.ToInt32 (bs, 0) |> uint64, len) :> BitVector + | 64 -> + let v1 = __.SmallValue () |> toFloat64 + let v2 = rhs.SmallValue () |> toFloat64 + let r = Math.Pow (v1, v2) |> BitConverter.DoubleToInt64Bits |> uint64 + BitVectorSmall (r, len) :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FCast targetLen = + match len, targetLen with + | 32, 32 -> __ :> BitVector + | 32, 64 -> + let f32 = __.SmallValue () |> toFloat32 |> float + let u64 = BitConverter.DoubleToInt64Bits f32 |> uint64 + BitVectorSmall (u64, targetLen) :> BitVector + | 32, 80 -> + let f32 = __.SmallValue () |> toFloat32 |> float + let u64 = BitConverter.DoubleToInt64Bits f32 |> uint64 + BitVectorBig (encodeBigFloat u64, targetLen) :> BitVector + | 64, 32 -> + let f64 = __.SmallValue () |> toFloat64 + let u64 = BitConverter.SingleToInt32Bits (float32 f64) |> uint64 + BitVectorSmall (u64, targetLen) :> BitVector + | 64, 64 -> __ :> BitVector + | 64, 80 -> + BitVectorBig (__.SmallValue () |> encodeBigFloat, targetLen) :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.Itof targetLen = + let mask = UInt64.MaxValue - (UInt64.MaxValue >>> (64 - int len)) + let signedFloat = (n + mask) |> int64 |> float + let u64 = BitConverter.DoubleToInt64Bits signedFloat |> uint64 + match targetLen with + | 32 | 64 -> BitVectorSmall (u64, targetLen) :> BitVector + | 80 -> BitVectorBig (bigint u64, targetLen) :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FtoiTrunc targetLen = + let f = + match len with + | 32 -> __.SmallValue () |> toFloat32 |> float |> truncate + | 64 -> __.SmallValue () |> toFloat64 |> truncate + | _ -> raise ArithTypeMismatchException + if targetLen <= 64 then + BitVectorSmall (adaptSmall targetLen (uint64 f), targetLen) :> BitVector + else BitVectorBig (adaptBig targetLen (bigint f), targetLen) :> BitVector + + override __.FtoiRound targetLen = + let f = + match len with + | 32 -> __.SmallValue () |> toFloat32 |> float |> round + | 64 -> __.SmallValue () |> toFloat64 |> round + | _ -> raise ArithTypeMismatchException + if targetLen <= 64 then + BitVectorSmall (adaptSmall targetLen (uint64 f), targetLen) :> BitVector + else BitVectorBig (adaptBig targetLen (bigint f), targetLen) :> BitVector + + override __.FtoiFloor targetLen = + let f = + match len with + | 32 -> __.SmallValue () |> toFloat32 |> float |> floor + | 64 -> __.SmallValue () |> toFloat64 |> floor + | _ -> raise ArithTypeMismatchException + if targetLen <= 64 then + BitVectorSmall (adaptSmall targetLen (uint64 f), targetLen) :> BitVector + else BitVectorBig (adaptBig targetLen (bigint f), targetLen) :> BitVector + + override __.FtoiCeil targetLen = + let f = + match len with + | 32 -> __.SmallValue () |> toFloat32 |> float |> ceil + | 64 -> __.SmallValue () |> toFloat64 |> ceil | _ -> raise ArithTypeMismatchException - let rep = signedFloat |> BitConverter.DoubleToInt64Bits |> uint64 - BitVector.castAsFloat rep typ + if targetLen <= 64 then + BitVectorSmall (adaptSmall targetLen (uint64 f), targetLen) :> BitVector + else BitVectorBig (adaptBig targetLen (bigint f), targetLen) :> BitVector - [] - static member sext bv typ = - let bv' = BitVector.cast bv typ - if BitVector.isPositive bv then bv' - else - let mask = - BitVector.ofUBInt (RegType.getMask typ - RegType.getMask bv.Length) typ - BitVector.add mask bv' + override __.FSqrt () = + match len with + | 32 -> + let r = __.SmallValue () |> toFloat32 |> sqrt + BitVectorSmall (BitConverter.SingleToInt32Bits r |> uint64, len) + :> BitVector + | 64 -> + let r = __.SmallValue () |> toFloat64 |> sqrt + BitVectorSmall (BitConverter.DoubleToInt64Bits r |> uint64, len) + :> BitVector + | _ -> raise ArithTypeMismatchException - [] - static member zext bv t = BitVector.cast bv t + override __.FTan () = + match len with + | 32 -> + let r = __.SmallValue () |> toFloat32 |> tan + BitVectorSmall (BitConverter.SingleToInt32Bits r |> uint64, len) + :> BitVector + | 64 -> + let r = __.SmallValue () |> toFloat64 |> tan + BitVectorSmall (BitConverter.DoubleToInt64Bits r |> uint64, len) + :> BitVector + | _ -> raise ArithTypeMismatchException - [] - static member abs bv = - if BitVector.isPositive bv then bv else BitVector.neg bv + override __.FATan () = + match len with + | 32 -> + let r = __.SmallValue () |> toFloat32 |> atan + BitVectorSmall (BitConverter.SingleToInt32Bits r |> uint64, len) + :> BitVector + | 64 -> + let r = __.SmallValue () |> toFloat64 |> atan + BitVectorSmall (BitConverter.DoubleToInt64Bits r |> uint64, len) + :> BitVector + | _ -> raise ArithTypeMismatchException - [] - static member min bv1 bv2 = - if BitVector.lt bv1 bv2 = BitVector.T then bv1 - else bv2 + override __.FSin () = + match len with + | 32 -> + let r = __.SmallValue () |> toFloat32 |> sin + BitVectorSmall (BitConverter.SingleToInt32Bits r |> uint64, len) + :> BitVector + | 64 -> + let r = __.SmallValue () |> toFloat64 |> sin + BitVectorSmall (BitConverter.DoubleToInt64Bits r |> uint64, len) + :> BitVector + | _ -> raise ArithTypeMismatchException - [] - static member max bv1 bv2 = - if BitVector.gt bv1 bv2 = BitVector.T then bv1 - else bv2 + override __.FCos () = + match len with + | 32 -> + let r = __.SmallValue () |> toFloat32 |> cos + BitVectorSmall (BitConverter.SingleToInt32Bits r |> uint64, len) + :> BitVector + | 64 -> + let r = __.SmallValue () |> toFloat64 |> cos + BitVectorSmall (BitConverter.DoubleToInt64Bits r |> uint64, len) + :> BitVector + | _ -> raise ArithTypeMismatchException - [] - static member smin bv1 bv2 = - if BitVector.slt bv1 bv2 = BitVector.T then bv1 - else bv2 + override __.FGt rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 32 -> + let v1 = __.SmallValue () |> toFloat32 + let v2 = rhs.SmallValue () |> toFloat32 + if v1 > v2 then BitVector.T else BitVector.F + | 64 -> + let v1 = __.SmallValue () |> toFloat64 + let v2 = rhs.SmallValue () |> toFloat64 + if v1 > v2 then BitVector.T else BitVector.F + | _ -> raise ArithTypeMismatchException - [] - static member smax bv1 bv2 = - if BitVector.sgt bv1 bv2 = BitVector.T then bv1 - else bv2 + override __.FGe rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 32 -> + let v1 = __.SmallValue () |> toFloat32 + let v2 = rhs.SmallValue () |> toFloat32 + if v1 >= v2 then BitVector.T else BitVector.F + | 64 -> + let v1 = __.SmallValue () |> toFloat64 + let v2 = rhs.SmallValue () |> toFloat64 + if v1 >= v2 then BitVector.T else BitVector.F + | _ -> raise ArithTypeMismatchException - static member maxNum8 = BitVector.ofUInt64 0xFFUL 8 - static member maxNum16 = BitVector.ofUInt64 0xFFFFUL 16 - static member maxNum32 = BitVector.ofUInt64 0xFFFFFFFFUL 32 - static member maxNum64 = BitVector.ofUInt64 0xFFFFFFFFFFFFFFFFUL 64 + override __.FLt rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 32 -> + let v1 = __.SmallValue () |> toFloat32 + let v2 = rhs.SmallValue () |> toFloat32 + if v1 < v2 then BitVector.T else BitVector.F + | 64 -> + let v1 = __.SmallValue () |> toFloat64 + let v2 = rhs.SmallValue () |> toFloat64 + if v1 < v2 then BitVector.T else BitVector.F + | _ -> raise ArithTypeMismatchException - static member midNum8 = BitVector.ofUInt64 0x80UL 8 - static member midNum16 = BitVector.ofUInt64 0x8000UL 16 - static member midNum32 = BitVector.ofUInt64 0x80000000UL 32 - static member midNum64 = BitVector.ofUInt64 0x8000000000000000UL 64 + override __.FLe rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 32 -> + let v1 = __.SmallValue () |> toFloat32 + let v2 = rhs.SmallValue () |> toFloat32 + if v1 <= v2 then BitVector.T else BitVector.F + | 64 -> + let v1 = __.SmallValue () |> toFloat64 + let v2 = rhs.SmallValue () |> toFloat64 + if v1 <= v2 then BitVector.T else BitVector.F + | _ -> raise ArithTypeMismatchException - [] - static member unsignedMax rt = - match rt with -#if DEBUG - | typ when typ <= 0 -> nSizeErr typ -#endif - | 8 -> BitVector.maxNum8 - | 16 -> BitVector.maxNum16 - | 32 -> BitVector.maxNum32 - | 64 -> BitVector.maxNum64 - | t when t < 64 -> BitVector.ofUInt64 (RegType.getUInt64Mask rt) rt - | _ -> { Num = 0UL; Length = rt; BigNum = RegType.getMask rt } +/// This is a BitVector with its length less than or equal to 64. This is +/// preferred because all the operations will be much faster than BitVectorBig. +and BitVectorBig (n, len) = + inherit BitVector(len) - [] - static member unsignedMin rt = #if DEBUG - if rt <= 0 then nSizeErr rt else () + do if len <= 64 then raise ArithTypeMismatchException else () #endif - BitVector.zero rt - [] - static member signedMax rt = - match rt with + member __.Value with get(): bigint = n + + override __.ValToString () = + if n = bigZero then "0x0" + else "0x" + n.ToString("x").TrimStart('0') + + override __.Equals obj = + match obj with + | :? BitVectorBig as obj -> len = obj.Length && n = obj.Value + | _ -> false + + override __.ApproxEq (rhs: BitVector) = #if DEBUG - | typ when typ <= 0 -> nSizeErr typ + if len <> rhs.Length then raise ArithTypeMismatchException else () #endif - | 8 -> BitVector.midNum8 - 1UL - | 16 -> BitVector.midNum16 - 1UL - | 32 -> BitVector.midNum32 - 1UL - | 64 -> BitVector.midNum64 - 1UL - | t when t < 64 -> - BitVector.ofUInt64 (RegType.getUInt64Mask (rt - 1)) rt - | _ -> - { Num = 0UL ; Length = rt; BigNum = RegType.getMask (rt - 1)} + if len = 80 then + let shifter = BitVector.ofInt32 12 80 + let v1 = __.Shr shifter + let v2 = rhs.Shr shifter + v1.Eq v2 + else raise ArithTypeMismatchException - [] - static member signedMin rt = - match rt with + override __.IsPositive () = isBigPositive len n + + override __.IsNegative () = not <| isBigPositive len n + + override __.GetHashCode () = + HashCode.Combine (n, len) + + override __.ToString () = + __.ValToString () + ":" + RegType.toString len + + override __.SmallValue () = #if DEBUG - | typ when typ <= 0 -> nSizeErr typ + if n > bigint 0xFFFFFFFFFFFFFFFFUL then nSizeErr len else () #endif - | 8 -> BitVector.midNum8 - | 16 -> BitVector.midNum16 - | 32 -> BitVector.midNum32 - | 64 -> BitVector.midNum64 - | t when t < 64 -> BitVector.ofUInt64 (1UL <<< int (rt - 1)) rt - | _ -> { Num = 0UL; Length = rt; BigNum = 1I <<< int (rt - 1) } + uint64 n + + override __.BigValue () = n + + override __.IsZero () = n = 0I + + override __.IsOne () = n = 1I + + override __.Add (rhs: uint64) = + BitVectorBig (n + bigint rhs, len) :> BitVector + + override __.Add (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorBig (n + rhs.BigValue () |> adaptBig len, len) :> BitVector + + override __.Sub (rhs: uint64) = + BitVectorBig (n - bigint rhs, len) :> BitVector + + override __.Sub (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorBig (n - rhs.BigValue () |> adaptBig len, len) :> BitVector + + override __.Mul (rhs: uint64) = + BitVectorBig (n * bigint rhs, len) :> BitVector + + override __.Mul (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorBig (n * rhs.BigValue () |> adaptBig len, len) :> BitVector + + override __.SDiv (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let v1 = n + let v2 = rhs.BigValue () + let isPos1 = isBigPositive len v1 + let isPos2 = isBigPositive rhs.Length v2 + let v1 = if isPos1 then v1 else neg len v1 + let v2 = if isPos2 then v2 else neg len v2 + let result = if isPos1 = isPos2 then v1 / v2 else neg len (v1 / v2) + BitVectorBig (result |> adaptBig len, len) :> BitVector + + override __.Div (rhs: uint64) = + BitVectorBig (n / bigint rhs, len) :> BitVector + + override __.Div (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorBig (n / rhs.BigValue () |> adaptBig len, len) :> BitVector + + override __.SMod (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let v1 = n + let v2 = rhs.BigValue () + let isPos1 = isBigPositive len v1 + let isPos2 = isBigPositive rhs.Length v2 + let v1 = if isPos1 then v1 else neg len v1 + let v2 = if isPos2 then v2 else neg len v2 + let result = if isPos1 then v1 % v2 else neg len (v1 % v2) + BitVectorBig (result |> adaptBig len, len) :> BitVector + + override __.Mod (rhs: uint64) = + BitVectorBig (n % bigint rhs, len) :> BitVector + + override __.Mod (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorBig (n % rhs.BigValue () |> adaptBig len, len) :> BitVector + + override __.And (rhs: uint64) = + BitVectorBig (n &&& bigint rhs, len) :> BitVector + + override __.And (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorBig (n &&& rhs.BigValue () |> adaptBig len, len) :> BitVector + + override __.Or (rhs: uint64) = + BitVectorBig (n ||| bigint rhs, len) :> BitVector + + override __.Or (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorBig (n ||| rhs.BigValue () |> adaptBig len, len) :> BitVector + + override __.Xor (rhs: uint64) = + BitVectorBig (n ^^^ bigint rhs, len) :> BitVector + + override __.Xor (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + BitVectorBig (n ^^^ rhs.BigValue () |> adaptBig len, len) :> BitVector + + override __.Shl (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let v1 = n + let v2 = rhs.SmallValue () |> uint16 |> int + BitVectorBig (adaptBig len (v1 <<< v2), len) :> BitVector + + override __.Shr (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let v1 = n + let v2 = rhs.SmallValue () |> uint16 |> int + BitVectorBig (v1 >>> v2, len) :> BitVector + + override __.Sar (rhs: BitVector) = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let v1 = n + let v2 = rhs.SmallValue () |> uint16 |> int + let res = v1 >>> v2 + if isBigPositive len v1 then BitVectorBig (res, len) :> BitVector + else + let pad = ((bigOne <<< int len) - bigOne) - ((bigOne <<< (int len - v2))) + BitVectorBig (res ||| pad, len) :> BitVector - [] - static member isUnsignedMax bv = - BitVector.unsignedMax bv.Length = bv + override __.Not () = + BitVectorBig ((bigOne <<< (int len)) - bigOne - n, len) :> BitVector - [] - static member isSignedMax bv = - BitVector.signedMax bv.Length = bv + override __.Neg () = + BitVectorBig (adaptBig len ((bigOne <<< (int len)) - n), len) :> BitVector - [] - static member isSignedMin bv = - BitVector.signedMin bv.Length = bv + override __.Cast targetLen = + if targetLen <= 64 then + BitVectorSmall (adaptSmall targetLen (uint64 n), targetLen) :> BitVector + else BitVectorBig (adaptBig targetLen n, targetLen) :> BitVector + + override __.Extract targetLen pos = + if len < targetLen then raise ArithTypeMismatchException + elif len = targetLen then __ :> BitVector + elif targetLen <= 64 then + let n' = n >>> pos |> adaptBig targetLen |> uint64 + BitVectorSmall (n', targetLen) :> BitVector + else BitVectorBig (adaptBig targetLen (n >>> pos), targetLen) :> BitVector + + override __.Concat (rhs: BitVector) = + let rLen = rhs.Length + let targetLen = len + rLen + let v1 = n + let v2 = rhs.BigValue () + BitVectorBig ((v1 <<< int rLen) + v2, targetLen) :> BitVector + + override __.SExt targetLen = + if targetLen < len then raise ArithTypeMismatchException + elif targetLen = len then __ :> BitVector + else + let n' = adaptBig targetLen n + if isBigPositive len n then + BitVectorBig (n', targetLen) :> BitVector + else + let mask = (bigOne <<< int targetLen) - (bigOne <<< int len) + BitVectorBig (n' + mask, targetLen) :> BitVector - [] - static member isZero bv = - if bv.Length <= 64 then bv.Num = 0UL - else bv.BigNum = 0I + override __.ZExt targetLen = + if targetLen < len then raise ArithTypeMismatchException + elif targetLen = len then __ :> BitVector + else BitVectorBig (adaptBig targetLen n, targetLen) :> BitVector - [] - static member isOne bv = - if bv.Length <= 64 then bv.Num = 1UL - else bv.BigNum = 1I + override __.Eq rhs = + if len = rhs.Length && n = rhs.BigValue () then BitVector.T + else BitVector.F - [] - static member isFalse bv = - bv = BitVector.F + override __.Neq rhs = + if len = rhs.Length && n = rhs.BigValue () then BitVector.F + else BitVector.T - [] - static member isTrue bv = - bv = BitVector.T + override __.Gt rhs = + if len <> rhs.Length then raise ArithTypeMismatchException + elif n > rhs.BigValue () then BitVector.T + else BitVector.F - [] - static member isNum bv n = - if bv.Length <= 64 then bv.Num = n - else bv.BigNum = bigint n + override __.Ge rhs = + if len <> rhs.Length then raise ArithTypeMismatchException + elif n >= rhs.BigValue () then BitVector.T + else BitVector.F - [] - static member valToString (n: BitVector) = n.ValToString () + override __.SGt rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let isPos1 = isBigPositive len n + let isPos2 = isBigPositive len (rhs.BigValue ()) + if isPos1 && not isPos2 then BitVector.T + elif not isPos1 && isPos2 then BitVector.F + else + if n > rhs.BigValue () then BitVector.T else BitVector.F + + override __.SGe rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let isPos1 = isBigPositive len n + let isPos2 = isBigPositive len (rhs.BigValue ()) + if isPos1 && not isPos2 then BitVector.T + elif not isPos1 && isPos2 then BitVector.F + else + if n >= rhs.BigValue () then BitVector.T else BitVector.F - [] - static member toString (n: BitVector) = n.ToString () + override __.Lt rhs = + if len <> rhs.Length then raise ArithTypeMismatchException + elif n < rhs.BigValue () then BitVector.T + else BitVector.F + + override __.Le rhs = + if len <> rhs.Length then raise ArithTypeMismatchException + elif n <= rhs.BigValue () then BitVector.T + else BitVector.F + + override __.SLt rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let isPos1 = isBigPositive len n + let isPos2 = isBigPositive len (rhs.BigValue ()) + if isPos1 && not isPos2 then BitVector.F + elif not isPos1 && isPos2 then BitVector.T + else + if n < rhs.BigValue () then BitVector.T else BitVector.F + + override __.SLe rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + let isPos1 = isBigPositive len n + let isPos2 = isBigPositive len (rhs.BigValue ()) + if isPos1 && not isPos2 then BitVector.F + elif not isPos1 && isPos2 then BitVector.T + else + if n <= rhs.BigValue () then BitVector.T else BitVector.F -// vim: set tw=80 sts=2 sw=2: + override __.Abs () = + if isBigPositive len n then __ :> BitVector + else __.Neg () + + override __.FAdd rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 80 -> + let v1 = __.BigValue () |> toBigFloat + let v2 = rhs.BigValue () |> toBigFloat + let n = v1 + v2 |> BitConverter.DoubleToInt64Bits |> uint64 + if n = 0UL then BitVector.zero len + else BitVectorBig (encodeBigFloat n, len) :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FSub rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 80 -> + let v1 = __.BigValue () |> toBigFloat + let v2 = rhs.BigValue () |> toBigFloat + let n = v1 - v2 |> BitConverter.DoubleToInt64Bits |> uint64 + if n = 0UL then BitVector.zero len + else BitVectorBig (encodeBigFloat n, len) :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FMul rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 80 -> + let v1 = __.BigValue () |> toBigFloat + let v2 = rhs.BigValue () |> toBigFloat + let n = v1 * v2 |> BitConverter.DoubleToInt64Bits |> uint64 + if n = 0UL then BitVector.zero len + else BitVectorBig (encodeBigFloat n, len) :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FDiv rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 80 -> + let v1 = __.BigValue () |> toBigFloat + let v2 = rhs.BigValue () |> toBigFloat + let n = v1 / v2 |> BitConverter.DoubleToInt64Bits |> uint64 + if n = 0UL then BitVector.zero len + else BitVectorBig (encodeBigFloat n, len) :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FLog rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 80 -> + let v1 = __.BigValue () |> toBigFloat + let v2 = rhs.BigValue () |> toBigFloat + let n = Math.Log (v2, v1) |> BitConverter.DoubleToInt64Bits |> uint64 + if n = 0UL then BitVector.zero len + else BitVectorBig (encodeBigFloat n, len) :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FPow rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 80 -> + let v1 = __.BigValue () |> toBigFloat + let v2 = rhs.BigValue () |> toBigFloat + let n = Math.Pow (v1, v2) |> BitConverter.DoubleToInt64Bits |> uint64 + if n = 0UL then BitVector.zero len + else BitVectorBig (encodeBigFloat n, len) :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FCast targetLen = + match len, targetLen with + | 80, 32 -> + let f32 = __.BigValue () |> toBigFloat |> float32 + BitVectorSmall (BitConverter.SingleToInt32Bits f32 |> uint64, targetLen) + :> BitVector + | 80, 64 -> + let f64 = __.BigValue () |> toBigFloat + BitVectorSmall (BitConverter.DoubleToInt64Bits f64 |> uint64, targetLen) + :> BitVector + | 80, 80 -> __ :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.Itof targetLen = + let v = if isBigPositive len n then n else - n + let signedFloat = float v + let u64 = BitConverter.DoubleToInt64Bits signedFloat |> uint64 + match targetLen with + | 32 | 64 -> BitVectorSmall (u64, targetLen) :> BitVector + | 80 -> BitVectorBig (bigint u64, targetLen) :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FtoiTrunc targetLen = + let f = + match len with + | 80 -> __.BigValue () |> toBigFloat |> truncate + | _ -> raise ArithTypeMismatchException + if targetLen <= 64 then + BitVectorSmall (adaptSmall targetLen (uint64 f), targetLen) :> BitVector + else BitVectorBig (adaptBig targetLen (bigint f), targetLen) :> BitVector + + override __.FtoiRound targetLen = + let f = + match len with + | 80 -> __.BigValue () |> toBigFloat |> round + | _ -> raise ArithTypeMismatchException + if targetLen <= 64 then + BitVectorSmall (adaptSmall targetLen (uint64 f), targetLen) :> BitVector + else BitVectorBig (adaptBig targetLen (bigint f), targetLen) :> BitVector + + override __.FtoiFloor targetLen = + let f = + match len with + | 80 -> __.BigValue () |> toBigFloat |> floor + | _ -> raise ArithTypeMismatchException + if targetLen <= 64 then + BitVectorSmall (adaptSmall targetLen (uint64 f), targetLen) :> BitVector + else BitVectorBig (adaptBig targetLen (bigint f), targetLen) :> BitVector + + override __.FtoiCeil targetLen = + let f = + match len with + | 80 -> __.BigValue () |> toBigFloat |> ceil + | _ -> raise ArithTypeMismatchException + if targetLen <= 64 then + BitVectorSmall (adaptSmall targetLen (uint64 f), targetLen) :> BitVector + else BitVectorBig (adaptBig targetLen (bigint f), targetLen) :> BitVector + + override __.FSqrt () = + match len with + | 80 -> + let r = __.BigValue () |> toBigFloat |> sqrt + BitVectorBig (BitConverter.DoubleToInt64Bits r |> uint64 |> bigint, len) + :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FTan () = + match len with + | 80 -> + let r = __.BigValue () |> toBigFloat |> tan + BitVectorBig (BitConverter.DoubleToInt64Bits r |> uint64 |> bigint, len) + :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FATan () = + match len with + | 80 -> + let r = __.BigValue () |> toBigFloat |> atan + BitVectorBig (BitConverter.DoubleToInt64Bits r |> uint64 |> bigint, len) + :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FSin () = + match len with + | 80 -> + let r = __.BigValue () |> toBigFloat |> sin + BitVectorBig (BitConverter.DoubleToInt64Bits r |> uint64 |> bigint, len) + :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FCos () = + match len with + | 80 -> + let r = __.BigValue () |> toBigFloat |> cos + BitVectorBig (BitConverter.DoubleToInt64Bits r |> uint64 |> bigint, len) + :> BitVector + | _ -> raise ArithTypeMismatchException + + override __.FGt rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 80 -> + let v1 = __.BigValue () |> toBigFloat + let v2 = rhs.BigValue () |> toBigFloat + if v1 > v2 then BitVector.T else BitVector.F + | _ -> raise ArithTypeMismatchException + + override __.FGe rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 80 -> + let v1 = __.BigValue () |> toBigFloat + let v2 = rhs.BigValue () |> toBigFloat + if v1 >= v2 then BitVector.T else BitVector.F + | _ -> raise ArithTypeMismatchException + + override __.FLt rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 80 -> + let v1 = __.BigValue () |> toBigFloat + let v2 = rhs.BigValue () |> toBigFloat + if v1 < v2 then BitVector.T else BitVector.F + | _ -> raise ArithTypeMismatchException + + override __.FLe rhs = + if len <> rhs.Length then raise ArithTypeMismatchException else () + match len with + | 80 -> + let v1 = __.BigValue () |> toBigFloat + let v2 = rhs.BigValue () |> toBigFloat + if v1 <= v2 then BitVector.T else BitVector.F + | _ -> raise ArithTypeMismatchException diff --git a/src/Core/BitVector.fsi b/src/Core/BitVector.fsi deleted file mode 100644 index 5ee10d28..00000000 --- a/src/Core/BitVector.fsi +++ /dev/null @@ -1,484 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2 - -/// BitVector is the fundamental data type for binary code. We use bigint -/// (arbitrary precision integer) for numbers because registers can have a very -/// large number, e.g., YMM0 in x86. -[] -type BitVector = - private - { - Num : uint64 - Length : RegType - BigNum : bigint - } - with - override Equals : obj -> bool - override GetHashCode : unit -> int - override ToString : unit -> string - - /// BitVector addition with uint64. - static member (+) : v: BitVector * b: uint64 -> BitVector - - /// BitVector subtraction with uint64. - static member (-) : v: BitVector * b: uint64 -> BitVector - - /// BitVector multiplication with uint64. - static member (*) : v: BitVector * b: uint64 -> BitVector - - /// BitVector Bitwise And with uint64. - static member (&&&) : v: BitVector * b: uint64 -> BitVector - - /// BitVector Bitwise Or with uint64. - static member (|||) : v: BitVector * b: uint64 -> BitVector - - /// BitVector Bitwise And with uint64. - static member (^^^) : v: BitVector * b: uint64 -> BitVector - - /// BitVector unsigned division with uint64. - static member (/) : v: BitVector * b: uint64 -> BitVector - - /// BitVector unsigned modulo with uint64. - static member (%) : v: BitVector * b: uint64 -> BitVector - - /// BitVector addition. - static member (+) : v1: BitVector * v2: BitVector -> BitVector - - /// BitVector subtraction. - static member (-) : v1: BitVector * v2: BitVector -> BitVector - - /// BitVector multiplication. - static member (*) : v1: BitVector * v2: BitVector -> BitVector - - /// BitVector Bitwise And. - static member (&&&) : v1: BitVector * v2: BitVector -> BitVector - - /// BitVector Bitwise Or. - static member (|||) : v1: BitVector * v2: BitVector -> BitVector - - /// BitVector Bitwise Xor. - static member (^^^) : v1: BitVector * v2: BitVector -> BitVector - - /// BitVector Bitwise Not. - static member (~~~) : v: BitVector -> BitVector - - /// BitVector signed division. - static member (/) : v1: BitVector * v2: BitVector -> BitVector - - /// BitVector unsigned division. - static member (|/|) : v1: BitVector * v2: BitVector -> BitVector - - /// BitVector signed modulo. - static member (%) : v1: BitVector * v2: BitVector -> BitVector - - /// BitVector unsigned modulo. - static member (|%|) : v1: BitVector * v2: BitVector -> BitVector - - /// BitVector unary negation. - static member (~-): v: BitVector -> BitVector - - /// - /// Create a BitVector from an integer. - /// - [] - static member ofInt32 : i: int32 -> RegType -> BitVector - - /// Get a BitVector from an unsigned integer. - [] - static member ofUInt32 : i: uint32 -> RegType -> BitVector - - /// Get a BitVector from a 64-bit integer. - [] - static member ofInt64 : i: int64 -> RegType -> BitVector - - /// Get a BitVector from an unsigned integer. - [] - static member ofUInt64 : i: uint64 -> RegType -> BitVector - - /// Get a BitVector from an unsigned bigint. - [] - static member ofUBInt : i: bigint -> RegType -> BitVector - - /// Get a BitVector from a byte array (in little endian). - [] - static member ofArr : byte [] -> BitVector - - /// Get a BitVector of a specified size from another BitVector. - [] - static member ofBv : BitVector -> RegType -> BitVector - - /// Get a uint64 value from a BitVector. - [] - static member toUInt64 : BitVector -> uint64 - - /// Get a int64 value from a BitVector. - [] - static member toInt64 : BitVector -> int64 - - /// Get a uint32 value from a BitVector. - [] - static member toUInt32 : BitVector -> uint32 - - /// Get a int32 value from a BitVector. - [] - static member toInt32 : BitVector -> int32 - - /// Get a numeric value from a BitVector. - [] - static member getValue : BitVector -> bigint - - /// Get a type of a BitVector. - [] - static member getType : BitVector -> RegType - - /// BitVector zero (= 0) of the bit length. - [] - static member zero : RegType -> BitVector - - /// BitVector one (= 1) of the bit length. - [] - static member one : RegType -> BitVector - - /// BitVector one (= 1) of the bit length. - [] - static member T : BitVector - - /// BitVector one (= 1) of the bit length. - [] - static member F : BitVector - - /// Cast a type of a BitVector. - [] - static member cast : BitVector -> RegType -> BitVector - - /// Extract a type of a BitVector. - [] - static member extract : BitVector -> RegType -> int -> BitVector - - /// BitVector addition. - [] - static member add : BitVector -> BitVector -> BitVector - - /// BitVector subtraction. - [] - static member sub : BitVector -> BitVector -> BitVector - - /// BitVector multiplication. - [] - static member mul : BitVector -> BitVector -> BitVector - - /// BitVector unsigned division. - [] - static member div : BitVector -> BitVector -> BitVector - - /// BitVector signed division. - [] - static member sdiv : BitVector -> BitVector -> BitVector - - /// BitVector logical shift-left. - [] - static member shl : BitVector -> BitVector -> BitVector - - /// BitVector logical shift-right. - [] - static member shr : BitVector -> BitVector -> BitVector - - /// BitVector arithmetic shift-right. - [] - static member sar : BitVector -> BitVector -> BitVector - - /// BitVector concat. - [] - static member concat : BitVector -> BitVector -> BitVector - - /// BitVector sign-extend. - [] - static member sext : BitVector -> RegType -> BitVector - - /// BitVector zero-extend. - [] - static member zext : BitVector -> RegType -> BitVector - - /// BitVector unsigned modulo. - [] - static member modulo : BitVector -> BitVector -> BitVector - - /// BitVector signed modulo. - [] - static member smodulo : BitVector -> BitVector -> BitVector - - /// BitVector Bitwise And. - [] - static member band : BitVector -> BitVector -> BitVector - - /// BitVector Bitwise Or. - [] - static member bor : BitVector -> BitVector -> BitVector - - /// BitVector Bitwise Xor. - [] - static member bxor : BitVector -> BitVector -> BitVector - - /// BitVector Bitwise Not. - [] - static member bnot : BitVector -> BitVector - - /// Make it negative. - [] - static member neg : BitVector -> BitVector - - /// BitVector equal. - [] - static member eq : BitVector -> BitVector -> BitVector - - /// BitVector equal. For high-precision floating point numbers, this - /// function performs approximate equality check. - [] - static member aeq : BitVector -> BitVector -> BitVector - - // BitVector not equal. - [] - static member neq : BitVector -> BitVector -> BitVector - - /// BitVector unsigned greater than. - [] - static member gt : BitVector -> BitVector -> BitVector - - /// BitVector unsigned greater than or equal. - [] - static member ge : BitVector -> BitVector -> BitVector - - /// BitVector signed grater than. - [] - static member sgt : BitVector -> BitVector -> BitVector - - /// BitVector signed greater than or equal. - [] - static member sge : BitVector -> BitVector -> BitVector - - /// BitVector unsigned less than. - [] - static member lt : BitVector -> BitVector -> BitVector - - /// BitVector unsigned less than or equal. - [] - static member le : BitVector -> BitVector -> BitVector - - /// BitVector signed less than. - [] - static member slt : BitVector -> BitVector -> BitVector - - /// BitVector signed less than or equal. - [] - static member sle : BitVector -> BitVector -> BitVector - - /// BitVector Absolute Value. - [] - static member abs : BitVector -> BitVector - - /// BitVector Minimum Value. - [] - static member min : BitVector -> BitVector -> BitVector - - /// BitVector Maximum Value. - [] - static member max : BitVector -> BitVector -> BitVector - - /// BitVector Signed Minimum Value. - [] - static member smin : BitVector -> BitVector -> BitVector - - /// BitVector Signed Maximum Value. - [] - static member smax : BitVector -> BitVector -> BitVector - - /// BitVector of maximum 8-bit integer. - [] - static member maxNum8 : BitVector - - /// BitVector of maximum 16-bit integer. - [] - static member maxNum16 : BitVector - - /// BitVector of maximum 32-bit integer. - [] - static member maxNum32 : BitVector - - /// BitVector of maximum 64-bit integer. - [] - static member maxNum64 : BitVector - - /// BitVector of unsigned maximum integer for given RegType. - [] - static member unsignedMax : RegType -> BitVector - - /// BitVector of unsigned minimum integer for given RegType. - [] - static member unsignedMin : RegType -> BitVector - - /// BitVector of signed maximum integer for given RegType. - [] - static member signedMax : RegType -> BitVector - - /// BitVector of signed minimum integer for given RegType. - [] - static member signedMin : RegType -> BitVector - - /// Does the bitvector represent a unsigned max value? - [] - static member isUnsignedMax: BitVector -> bool - - /// Does the bitvector represent a signed max value? - [] - static member isSignedMax: BitVector -> bool - - /// Does the bitvector represent a signed min value? - [] - static member isSignedMin: BitVector -> bool - - /// BitVector to string. - [] - static member toString : BitVector -> string - - /// A value of a BitVector to string. - [] - static member valToString : BitVector -> string - - /// Does the bitvector represent a positive number? - [] - static member isPositive : BitVector -> bool - - /// Does the bitvector represent a negative number? - [] - static member isNegative : BitVector -> bool - - /// Does the bitvector represent a value zero (0)? - [] - static member isZero : BitVector -> bool - - /// Does the bitvector represent a value one (1)? - [] - static member isOne : BitVector -> bool - - /// Does the bitvector represent false (=0)? - [] - static member isFalse : BitVector -> bool - - /// Does the bitvector represent true (<>0)? - [] - static member isTrue : BitVector -> bool - - /// Does the bitvector represent the specified integer number? - [] - static member isNum : BitVector -> uint64 -> bool - - /// BitVector floating point addition. - [] - static member fadd : BitVector -> BitVector -> BitVector - - /// BitVector floating point subtraction. - [] - static member fsub : BitVector -> BitVector -> BitVector - - /// BitVector floating point multiplication. - [] - static member fmul : BitVector -> BitVector -> BitVector - - /// BitVector floating point division. - [] - static member fdiv : BitVector -> BitVector -> BitVector - - /// Logarithm. - [] - static member flog : BitVector -> BitVector -> BitVector - - /// Power. - [] - static member fpow : BitVector -> BitVector -> BitVector - - /// BitVector float-extend. - [] - static member fext : BitVector -> RegType -> BitVector - - /// BitVector integer to float. - [] - static member itof : BitVector -> RegType -> BitVector - - /// BitVector float to integer truncated. - [] - static member ftoitrunc : BitVector -> RegType -> BitVector - - /// BitVector float to integer rounded. - [] - static member ftoiround : BitVector -> RegType -> BitVector - - /// BitVector float to integer floor. - [] - static member ftoifloor : BitVector -> RegType -> BitVector - - /// BitVector float to integer ceil. - [] - static member ftoiceil : BitVector -> RegType -> BitVector - - /// Square root function. - [] - static member fsqrt : BitVector -> BitVector - - /// Tangent. - [] - static member ftan : BitVector -> BitVector - - /// Sine. - [] - static member fsin : BitVector -> BitVector - - /// Cosine. - [] - static member fcos : BitVector -> BitVector - - /// Arc Tangent. - [] - static member fatan : BitVector -> BitVector - - /// BitVector floating point greater than. - [] - static member fgt : BitVector -> BitVector -> BitVector - - /// BitVector floating point less than. - [] - static member flt : BitVector -> BitVector -> BitVector - - /// BitVector floating point greater than or equal. - [] - static member fge : BitVector -> BitVector -> BitVector - - /// BitVector floating point less than or equal. - [] - static member fle : BitVector -> BitVector -> BitVector - - end - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/Core/ByteArray.fs b/src/Core/ByteArray.fs index 33b05d9d..3c8387aa 100644 --- a/src/Core/ByteArray.fs +++ b/src/Core/ByteArray.fs @@ -27,6 +27,7 @@ module B2R2.ByteArray open System open System.Text open System.Globalization +open System.Runtime.InteropServices let ofHexString (s: string) = Seq.windowed 2 s @@ -36,6 +37,16 @@ let ofHexString (s: string) = NumberStyles.AllowHexSpecifier)) |> Array.ofSeq +let toReadOnlySpan (bs: byte []) = + ReadOnlySpan (bs) + +let readInt32 (bs: byte []) offset = + try + let span = ReadOnlySpan (bs, offset, 4) + MemoryMarshal.Read span |> Ok + with _ -> + Error ErrorCase.InvalidMemoryRead + let rec private extractCStringFromSpanAux span (acc: StringBuilder) offset = if offset >= (span: ReadOnlySpan).Length then acc.ToString () else @@ -92,19 +103,19 @@ let rec getMatch (pattern: byte []) (buf: byte []) struct (i, j) = getMatch pattern buf struct (i - 1, j - 1) else struct (i, j) +let rec searchOne i (buf: byte []) (pattern: byte []) (d1: int[]) (d2: int[]) = + if i < buf.Length then + let struct (i, j) = getMatch pattern buf struct (i, pattern.Length - 1) + if j < 0 then Some (i + 1) + else searchOne (i + (max d1.[int buf.[i]] d2.[j])) buf pattern d1 d2 + else None + let bmSearch pattern buf = - let buflen = Array.length buf let patlen = Array.length pattern let delta1 = makeDelta1 pattern patlen let delta2 = makeDelta2 pattern patlen - let rec searchOne i = - if i < buflen then - let struct (i, j) = getMatch pattern buf struct (i, patlen - 1) - if j < 0 then Some (i + 1) - else searchOne (i + (max delta1.[int buf.[i]] delta2.[j])) - else None let rec searchAll idx ret = - match searchOne idx with + match searchOne idx buf pattern delta1 delta2 with | Some j -> searchAll (j + patlen) (j :: ret) | None -> ret searchAll (patlen - 1) [] @@ -113,17 +124,11 @@ let findIdxs offset pattern buf = bmSearch pattern buf |> List.map (fun x -> (uint64 x) + offset) let tryFindIdx offset pattern buf = - let buflen = Array.length buf let patlen = Array.length pattern let delta1 = makeDelta1 pattern patlen let delta2 = makeDelta2 pattern patlen - let rec searchOne i = - if i < buflen then - let struct (i, j) = getMatch pattern buf struct (i, patlen - 1) - if j < 0 then Some ((uint64 i) + offset) - else searchOne (i + (max delta1.[int buf.[i]] delta2.[j])) - else None - searchOne (patlen - 1) + searchOne (patlen - 1) buf pattern delta1 delta2 + |> Option.map (fun idx -> uint64 idx + offset) let toUInt32Arr (src: byte []) = let srcLen = Array.length src diff --git a/src/Core/ByteArray.fsi b/src/Core/ByteArray.fsi index eec6a17a..46068361 100644 --- a/src/Core/ByteArray.fsi +++ b/src/Core/ByteArray.fsi @@ -31,6 +31,12 @@ open System /// Convert a hex string to a byte array. val ofHexString: string -> byte [] +/// Convert a byte array into a read-only span. +val toReadOnlySpan: byte [] -> ReadOnlySpan + +/// Read int32 from the given byte array at the given offset. +val readInt32: byte [] -> offset: int -> Result + /// Extract a C-string (string that ends with a NULL char) from a byte array. val extractCString: byte [] -> int -> string diff --git a/src/ConcEval/Memory.fs b/src/Core/BytePattern.fs similarity index 50% rename from src/ConcEval/Memory.fs rename to src/Core/BytePattern.fs index 45b3189e..43fcc729 100644 --- a/src/ConcEval/Memory.fs +++ b/src/Core/BytePattern.fs @@ -22,42 +22,44 @@ SOFTWARE. *) -namespace B2R2.ConcEval +namespace B2R2 -open B2R2 -open System.Collections.Generic +open System -type Memory () = - /// Store memory contents (byte-level). - let mem = Dictionary () +type ByteValue = + /// This matches any byte, i.e., it is like a kleene star. + | AnyByte + /// This matches only one single byte value. + | OneByte of byte - member val Reader: Addr -> Addr -> byte option = fun _ _ -> None with get, set +/// Represents a byte pattern. +type BytePattern = ByteValue [] - member private __.Load (pc: Addr) addr = - if mem.ContainsKey (addr) then mem.[addr] - else - match __.Reader pc addr with - | None -> raise InvalidMemException - | Some b -> b - - member __.Read pc addr endian typ = - let len = RegType.toByteWidth typ - let v = [ for i = 0 to len - 1 do yield __.Load pc (addr + uint64 i) ] - Array.ofList (if endian = Endian.Little then v else List.rev v) - |> BitVector.ofArr - - member __.Write addr v endian = - let len = BitVector.getType v |> RegType.toByteWidth |> int - let v = BitVector.getValue v - if endian = Endian.Big then - for i = 1 to len do - let offset = i - 1 - let b = (v >>> (offset * 8)) &&& 255I |> byte - mem.[addr + uint64 (len - i)] <- b +module BytePattern = + let private isEqual bv v = + match bv with + | AnyByte -> true + | OneByte b -> b = v + + /// Check if the given byte array (bs) matches the pattern. The comparison + /// starts at the very first byte of the arrays. + let ``match`` (pattern: BytePattern) (bs: byte []) = + let patternLen = Array.length pattern + if patternLen > bs.Length then false else - for i = 1 to len do - let offset = i - 1 - let b = (v >>> (offset * 8)) &&& 255I |> byte - mem.[addr + uint64 offset] <- b + let bs = Array.sub bs 0 patternLen + Array.forall2 isEqual pattern bs - member __.Clear () = mem.Clear () + /// Check if the given span matches the pattern. The comparison starts at the + /// offset zero. + let matchSpan pattern (span: ReadOnlySpan) = + let mutable matched = true + let patternLen = Array.length pattern + if patternLen > span.Length then false + else + for i in [ 0 .. patternLen - 1 ] do + match pattern.[i] with + | AnyByte -> () + | OneByte b -> if span.[i] = b then () else matched <- false + done + matched diff --git a/src/Core/ColoredString.fs b/src/Core/ColoredString.fs new file mode 100644 index 00000000..17d92256 --- /dev/null +++ b/src/Core/ColoredString.fs @@ -0,0 +1,130 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2 + +open System + +type Color = Red | Green | Yellow | Blue | DarkCyan | DarkYellow | NoColor + +module Color = + let toString = function + | NoColor -> "nocolor" + | Red -> "red" + | Green -> "green" + | Yellow -> "yellow" + | Blue -> "blue" + | DarkCyan -> "darkcyan" + | DarkYellow -> "darkyellow" + +type ColoredSegment = Color * string + +[] +module ColoredSegment = + let private isNull b = b = 0uy + + let private isPrintable b = b >= 33uy && b <= 126uy + + let private isWhitespace b = b = 32uy || (b >= 9uy && b <= 13uy) + + let private isControl b = + b = 127uy || (b >= 1uy && b <= 8uy) || (b >= 14uy && b <= 31uy) + + let private getColor b = + if isNull b then NoColor + elif isPrintable b then Green + elif isWhitespace b then Blue + elif isControl b then Red + else Yellow + + let getRepresentation b = + if isNull b then "." + elif isPrintable b then (char b).ToString () + elif isWhitespace b then "_" + elif isControl b then "*" + else "." + + let byteToHex b = + getColor b, b.ToString ("X2") + + let byteToHexWithTail b tail = + getColor b, (b.ToString ("X2") + tail) + + let byteToAscii b = + getColor b, getRepresentation b + + let colorBytes (bs: byte []) = + let lastIdx = bs.Length - 1 + bs + |> Array.mapi (fun i b -> + if i = lastIdx then byteToHex b + else byteToHexWithTail b " ") + |> Array.toList + + let inline nocolor str: ColoredSegment = NoColor, str + let inline red str: ColoredSegment = Red, str + let inline green str: ColoredSegment = Green, str + let inline yellow str: ColoredSegment = Yellow, str + let inline blue str: ColoredSegment = Blue, str + let inline dcyan str: ColoredSegment = DarkCyan, str + let inline dyellow str: ColoredSegment = DarkYellow, str + +type ColoredString = ColoredSegment list + +[] +module ColoredString = + /// Set the color. + let private setColor = function + | NoColor -> Console.ResetColor () + | Red -> Console.ForegroundColor <- ConsoleColor.Red + | Green -> Console.ForegroundColor <- ConsoleColor.Green + | Yellow -> Console.ForegroundColor <- ConsoleColor.Yellow + | Blue -> Console.ForegroundColor <- ConsoleColor.Blue + | DarkCyan -> Console.ForegroundColor <- ConsoleColor.DarkCyan + | DarkYellow -> Console.ForegroundColor <- ConsoleColor.DarkYellow + + let compile (s: ColoredString): ColoredString = + let rec loop prev acc = function + | [] -> prev :: acc |> List.rev |> List.choose id + | col, str as cur :: rest -> + match prev with + | Some (prevCol, prevStr) when prevCol = col -> + loop (Some (prevCol, prevStr + str)) acc rest + | Some (_, _) -> loop (Some cur) (prev :: acc) rest + | None -> loop (Some cur) acc rest + loop None [] s + + let internal toConsole (s: ColoredString) = + s + |> List.iter (fun (c, s) -> + setColor c + Console.Write s) + Console.ResetColor () + + let internal toConsoleLine s = + toConsole s + Console.WriteLine () + + let toString (s: ColoredString) = + s |> List.map snd |> String.concat "" diff --git a/src/Core/ConcurrentWeakReferenceTable.fs b/src/Core/ConcurrentWeakReferenceTable.fs deleted file mode 100644 index 2a626903..00000000 --- a/src/Core/ConcurrentWeakReferenceTable.fs +++ /dev/null @@ -1,180 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2 - -open System -open System.Threading -open System.Runtime.InteropServices - -type private Node<'T> = { - Value : 'T - Hash : int - mutable Next : Node<'T> -} - -[] -module private ConcurrentWeakReferenceTableHelper = - let inline (===) e1 e2 = - LanguagePrimitives.PhysicalEquality e1 e2 - - let inline (!==) e1 e2 = - LanguagePrimitives.PhysicalEquality e1 e2 |> not - - let rec nextIntegerNotDivisibleBy357 sz = - if sz % 3 = 0 || sz % 5 = 0 || sz % 7 = 0 then - nextIntegerNotDivisibleBy357 (sz + 2) - else sz - - let inline nextSize currentSize = - nextIntegerNotDivisibleBy357 <| currentSize * 2 - - let createEmptyNodeRef _ = Unchecked.defaultof<_> - - let createEmptyLockRef _ = new Object () - - let inline getBucketNo hc _buckets = - (hc &&& 0x7fffffff) % (Array.length _buckets) - - let concurrency = Environment.ProcessorCount - -/// -/// Weak-reference table that supports concurrency. -/// -type ConcurrentWeakReferenceTable<'T when 'T : equality and 'T : not struct>() = - let mutable capacity = 31 - let mutable maxPerBucket = 251 - let mutable buckets = Array.init capacity createEmptyNodeRef - let locks = Array.init concurrency createEmptyLockRef - - member private __.TryGetValue (x, hc, [] res : byref<'T>) = - let _buckets = buckets - let bucketNo = getBucketNo hc _buckets - let mutable t = Volatile.Read>>(&_buckets.[bucketNo]) - let mutable found = false - while t !== Unchecked.defaultof<_> do - if hc = t.Hash then (* Fast Check *) - match t.Value.TryGetTarget () with - | true, v when v.Equals x -> - res <- v; t <- Unchecked.defaultof<_>; found <- true - | _ -> t <- t.Next - else t <- t.Next - found - - member private __.AcquireLocks st ed = - let mutable acquired = 0 - let mutable idx = st - while idx < ed do - let lockTaken = ref false - Monitor.Enter (locks.[idx], lockTaken) - if !lockTaken then acquired <- acquired + 1 - idx <- idx + 1 - acquired - - member private __.ReleaseLocks st ed = - let mutable idx = st - while idx < ed do Monitor.Exit locks.[idx]; idx <- idx + 1 - - member private __.Resize () = - let _buckets = buckets - (* First of All acquire Lock0 to resize *) - let mutable locksAcquired = __.AcquireLocks 0 1 - (* Confirm that any other thread does not call `resize ()` *) - if _buckets === buckets then - let nsize = nextSize capacity - let nbuckets = Array.init nsize createEmptyNodeRef - for head in buckets do - let mutable t = head - while t !== Unchecked.defaultof<_> do - match t.Value.TryGetTarget () with - | true, _ -> - let no = getBucketNo t.Hash nbuckets - (* Create new node and link *) - Volatile.Write>> - (&nbuckets.[no], { t with Next = nbuckets.[no] }) - | false, _ -> () - t <- t.Next - (* Acquire other Locks *) - locksAcquired <- locksAcquired + __.AcquireLocks 1 locks.Length - capacity <- nsize - buckets <- nbuckets - __.ReleaseLocks 0 locksAcquired - - member private __.AddValueInternal (x, hc, factory, [] sz: byref) = - let _buckets = buckets - let bucketNo = getBucketNo hc _buckets - let lockNo = bucketNo % concurrency - let lockTaken = ref false - let mutable hd = Unchecked.defaultof<_> - Monitor.Enter (locks.[lockNo], lockTaken) - if buckets === _buckets then - let mutable t = _buckets.[bucketNo] - let mutable found = false - let mutable res = Unchecked.defaultof<_> - let mutable prev = Unchecked.defaultof<_> - sz <- 0 - (* XXX: We assume that no duplicate entry exists *) - while t !== Unchecked.defaultof<_> do - match t.Value.TryGetTarget () with - | true, v -> - (* Set first none-empty cell as head *) - if hd === Unchecked.defaultof<_> then hd <- t - prev <- t - if v.Equals x then - res <- v; found <- true; t <- Unchecked.defaultof<_> - else t <- t.Next; sz <- sz + 1 - | false, _ -> (* Erase GC-ed Cell *) - if prev !== Unchecked.defaultof<_> then (* Head is dead *) - Volatile.Write>> (&prev.Next, t.Next) - t <- t.Next - if found then (* Insertion from other thread while waiting lock *) - Volatile.Write>> (&_buckets.[bucketNo], hd) - if !lockTaken then Monitor.Exit (locks.[lockNo]) |> ignore - sz <- 0; res - else - let hd = Volatile.Read>>(&_buckets.[bucketNo]) - let nV = factory x - let nVCell = WeakReference<'T> (nV) - Volatile.Write>> - (&_buckets.[bucketNo], { Value = nVCell - Hash = hc - Next = hd }) - if !lockTaken then Monitor.Exit (locks.[lockNo]) |> ignore - nV - else - if !lockTaken then Monitor.Exit (locks.[lockNo]) |> ignore - __.AddValueInternal (x, hc, factory, &sz) - - member private __.AddValue x hc factory = - let nV, sz = __.AddValueInternal (x, hc, factory) - if sz > maxPerBucket then __.Resize () - nV - - member __.GetOrApplyAndAdd x factory = - let hc = x.GetHashCode () - match __.TryGetValue (x, hc) with - | true, v -> v - | _ -> __.AddValue x hc factory - - member __.GetOrAdd x = __.GetOrApplyAndAdd x id diff --git a/src/Core/Errors.fs b/src/Core/Errors.fs new file mode 100644 index 00000000..9169125b --- /dev/null +++ b/src/Core/Errors.fs @@ -0,0 +1,82 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2 + +/// Error cases and corresponding numbers for B2R2. +type ErrorCase = + /// Failed to parse instruction(s). + | ParsingFailure = 0 + /// Invalid access to memory. + | InvalidMemoryRead = 1 + /// Invalid expression is evaluated. + | InvalidExprEvaluation = 2 + /// Symbol does not exist. + | SymbolNotFound = 3 + /// Item does not exist. + | ItemNotFound = 4 + /// Invalid file format. + | InvalidFileFormat = 5 + /// Invalid function address is encountered during a CFG analysis. + | InvalidFunctionAddress = 6 + /// The IR is not implemented yet. + | NotImplementedIR = 7 + /// Invalid use of operand has been encountered. + | InvalidOperand = 8 + /// Invalid operand size has been used. + | InvalidOperandSize = 9 + /// Invalid opcode has been used. + | InvalidOpcode = 10 + /// Invalid register has been used. + | InvalidRegister = 11 + /// Encountered register expression that is not yet handled. + | UnhandledRegExpr = 12 + /// Encountered a not executable address while parsing binaries. + | NotExecutableAddress = 13 + /// Encountered an instruction address at the middle of an exisitng + /// instruction while parsing binaries. + | IntrudingInstruction = 14 + /// Encountered fatal error while recovering CFG. + | FailedToRecoverCFG = 15 + +module ErrorCase = + let toString errCase = + match errCase with + | ErrorCase.ParsingFailure -> "Failed to parse." + | ErrorCase.InvalidMemoryRead -> "Read invalid memory." + | ErrorCase.InvalidExprEvaluation -> "Attempted to evalute invalid expr." + | ErrorCase.SymbolNotFound -> "Symbol not found." + | ErrorCase.ItemNotFound -> "Item not found." + | ErrorCase.InvalidFileFormat -> "Given invalid file format." + | ErrorCase.InvalidFunctionAddress -> "Given invalid function address." + | ErrorCase.NotImplementedIR -> "Not implemented IR." + | ErrorCase.InvalidOperand -> "Invalid operand." + | ErrorCase.InvalidOperandSize -> "Invalid operand size." + | ErrorCase.InvalidOpcode -> "Invalid opcode." + | ErrorCase.InvalidRegister -> "Invalid register." + | ErrorCase.UnhandledRegExpr -> "Unhandled register expression." + | ErrorCase.NotExecutableAddress -> "Not executable address." + | ErrorCase.IntrudingInstruction -> "Intruding instruction." + | ErrorCase.FailedToRecoverCFG -> "Failed to recover CFG." + | _ -> invalidArg (nameof errCase) "Unknown error case." diff --git a/src/Core/FileFormat.fs b/src/Core/FileFormat.fs index 52a2a9db..6a671a9e 100644 --- a/src/Core/FileFormat.fs +++ b/src/Core/FileFormat.fs @@ -47,13 +47,14 @@ module FileFormat = | "wasm" -> FileFormat.WasmBinary | _ -> FileFormat.RawBinary - let toString = function + let toString fmt = + match fmt with | FileFormat.RawBinary -> "Raw" | FileFormat.ELFBinary -> "ELF" | FileFormat.PEBinary -> "PE" | FileFormat.MachBinary -> "Mach-O" | FileFormat.WasmBinary -> "Wasm" - | _ -> invalidArg "FileFormat" "Unknown FileFormat used." + | _ -> invalidArg (nameof fmt) "Unknown FileFormat used." /// Check whether the given format is ELF. let isELF fmt = fmt = FileFormat.ELFBinary diff --git a/src/Core/FingerTree.fs b/src/Core/FingerTree.fs index 52ce5200..1b9a632c 100644 --- a/src/Core/FingerTree.fs +++ b/src/Core/FingerTree.fs @@ -53,7 +53,7 @@ type Prio<'a when 'a : comparison> = /// A monoid that represents a priority. type Priority<'a when 'a : comparison> (p) = new () = Priority (MInfty) - member __.Value: Prio<'a> = p + member inline __.Value: Prio<'a> = p override __.ToString () = match p with | MInfty -> "" @@ -62,9 +62,9 @@ type Priority<'a when 'a : comparison> (p) = member __.Zero = Priority (MInfty) member __.Assoc (rhs: Priority<'a>) = match __.Value, rhs.Value with + | Prio m, Prio n -> Priority (Prio (if m > n then m else n)) | MInfty, p | p, MInfty -> Priority (p) - | Prio m, Prio n -> Priority (Prio (max m n)) type Key<'a when 'a : comparison> = | NoKey @@ -73,7 +73,7 @@ type Key<'a when 'a : comparison> = /// A monoid that represents ordering. type Ordered<'a when 'a : comparison> (k) = new () = Ordered (NoKey) - member __.Key: Key<'a> = k + member inline __.Key: Key<'a> = k override __.ToString () = match k with | NoKey -> "" @@ -81,14 +81,15 @@ type Ordered<'a when 'a : comparison> (k) = interface IMonoid> with member __.Zero = Ordered (NoKey) member __.Assoc (rhs: Ordered<'a>) = - match k, rhs.Key with - | a, NoKey -> Ordered (a) - | _, b -> Ordered (b) + match rhs.Key with + | NoKey -> Ordered (k) + | b -> Ordered (b) /// A monoid that represents an interval (uint64 * uint64). type InterMonoid<'a when 'a : comparison> (o, p) = + let v = o, p new () = InterMonoid<'a> (new Ordered<'a>(), new Priority<'a>()) - member __.Value : Ordered<'a> * Priority<'a> = o, p + member inline __.Value: Ordered<'a> * Priority<'a> = v member __.GetMin () = o.Key member __.GetMax () = p.Value override __.ToString () = "(" + o.ToString () + "," + p.ToString () + ")" @@ -96,8 +97,9 @@ type InterMonoid<'a when 'a : comparison> (o, p) = member __.Zero = InterMonoid (new Ordered<'a>(), new Priority<'a>()) member __.Assoc (rhs: InterMonoid<'a>) = - match __.Value, rhs.Value with - | (a1, b1), (a2, b2) -> InterMonoid (a1 ++ a2, b1 ++ b2) + let a1, b1 = __.Value + let a2, b2 = rhs.Value + InterMonoid (a1 ++ a2, b1 ++ b2) /// A size monoid for random access. type Size (s) = @@ -162,10 +164,10 @@ with interface IMeasured<'v> with member this.Measurement: 'v = match this with - | One (a) -> calib a - | Two (a, b) -> calib a ++ calib b | Three (a, b, c) -> calib a ++ calib b ++ calib c + | Two (a, b) -> calib a ++ calib b | Four (a, b, c, d) -> calib a ++ calib b ++ calib c ++ calib d + | One (a) -> calib a static member Foldr fn digit acc = match digit with diff --git a/src/Core/ISA.fs b/src/Core/ISA.fs index 116d663a..df4edfcd 100644 --- a/src/Core/ISA.fs +++ b/src/Core/ISA.fs @@ -70,8 +70,16 @@ type Architecture = | TMS320C5000 = 18 /// TMS320C64x, TMS320C67x, etc. | TMS320C6000 = 19 + /// Common Intermediate Language (CIL), aka MSIL. + | CILOnly = 20 + /// CIL + x86 (PE32). + | CILIntel32 = 21 + /// CIL + x64 (PE32+). + | CILIntel64 = 22 + /// Atmel AVR 8-bit microcontroller. + | AVR = 23 /// Unknown ISA. - | UnknownISA = 20 + | UnknownISA = 30 type Arch = Architecture @@ -97,11 +105,17 @@ module ArchOperationMode = | "thumb" -> ArchOperationMode.ThumbMode | _ -> ArchOperationMode.NoMode + let toString mode = + match mode with + | ArchOperationMode.ARMMode -> "arm" + | ArchOperationMode.ThumbMode -> "thumb" + | _ -> "nomode" + /// Instruction Set Architecture (ISA). type ISA = { - Arch : Architecture - Endian : Endian - WordSize : WordSize + Arch: Architecture + Endian: Endian + WordSize: WordSize } with static member DefaultISA = @@ -128,33 +142,39 @@ with | Arch.MIPS64R2 | Arch.MIPS64R6 -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit64 } - | Arch.EVM -> (* EVM has 256-bit word, but we will use 64-bit here. *) - { Arch = arch; Endian = endian; WordSize = WordSize.Bit64 } + | Arch.EVM -> + { Arch = arch; Endian = endian; WordSize = WordSize.Bit256 } | Arch.TMS320C6000 -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit32 } + | Arch.CILOnly -> + { Arch = arch; Endian = endian; WordSize = WordSize.Bit64 } + | Arch.AVR -> + { Arch = arch; Endian = endian; WordSize = WordSize.Bit8 } | _ -> raise InvalidISAException static member OfString (s: string) = match s.ToLower () with - | "x86" | "i386" -> ISA.Init (Arch.IntelX86) Endian.Little + | "x86" | "i386" -> ISA.Init Arch.IntelX86 Endian.Little | "x64" | "x86-64" | "amd64" -> ISA.DefaultISA | "armv7" | "armv7le" - | "armel" | "armhf" -> ISA.Init (Arch.ARMv7) Endian.Little - | "armv7be" -> ISA.Init (Arch.ARMv7) Endian.Big - | "armv8a32" | "aarch32" -> ISA.Init (Arch.AARCH32) Endian.Little - | "armv8a32be" | "aarch32be" -> ISA.Init (Arch.AARCH32) Endian.Big - | "armv8a64" | "aarch64"-> ISA.Init (Arch.AARCH64) Endian.Little - | "armv8a64be" | "aarch64be" -> ISA.Init (Arch.AARCH64) Endian.Big - | "mips32r2" -> ISA.Init (Arch.MIPS32R2) Endian.Little - | "mips32r2be" -> ISA.Init (Arch.MIPS32R2) Endian.Big - | "mips32r6" -> ISA.Init (Arch.MIPS32R6) Endian.Little - | "mips32r6be" -> ISA.Init (Arch.MIPS32R6) Endian.Big - | "mips64r2" -> ISA.Init (Arch.MIPS64R2) Endian.Little - | "mips64r2be" -> ISA.Init (Arch.MIPS64R2) Endian.Big - | "mips64r6" -> ISA.Init (Arch.MIPS64R6) Endian.Little - | "mips64r6be" -> ISA.Init (Arch.MIPS64R6) Endian.Big - | "evm" -> ISA.Init (Arch.EVM) Endian.Little - | "tms320c6000" -> ISA.Init (Arch.TMS320C6000) Endian.Little + | "armel" | "armhf" -> ISA.Init Arch.ARMv7 Endian.Little + | "armv7be" -> ISA.Init Arch.ARMv7 Endian.Big + | "armv8a32" | "aarch32" -> ISA.Init Arch.AARCH32 Endian.Little + | "armv8a32be" | "aarch32be" -> ISA.Init Arch.AARCH32 Endian.Big + | "armv8a64" | "aarch64"-> ISA.Init Arch.AARCH64 Endian.Little + | "armv8a64be" | "aarch64be" -> ISA.Init Arch.AARCH64 Endian.Big + | "mips32r2" -> ISA.Init Arch.MIPS32R2 Endian.Little + | "mips32r2be" -> ISA.Init Arch.MIPS32R2 Endian.Big + | "mips32r6" -> ISA.Init Arch.MIPS32R6 Endian.Little + | "mips32r6be" -> ISA.Init Arch.MIPS32R6 Endian.Big + | "mips64r2" -> ISA.Init Arch.MIPS64R2 Endian.Little + | "mips64r2be" -> ISA.Init Arch.MIPS64R2 Endian.Big + | "mips64r6" -> ISA.Init Arch.MIPS64R6 Endian.Little + | "mips64r6be" -> ISA.Init Arch.MIPS64R6 Endian.Big + | "evm" -> ISA.Init Arch.EVM Endian.Little + | "tms320c6000" -> ISA.Init Arch.TMS320C6000 Endian.Little + | "cil" -> ISA.Init Arch.CILOnly Endian.Little + | "avr" | "avr8" -> ISA.Init Arch.AVR Endian.Little | _ -> raise InvalidISAException static member ArchToString arch = @@ -170,5 +190,7 @@ with | Arch.MIPS64R6 -> "MIPS64 Release 6" | Arch.EVM -> "EVM" | Arch.TMS320C6000 -> "TMS320C6000" + | Arch.CILOnly -> "CIL" + | Arch.AVR -> "AVR" | Arch.UnknownISA -> "Unknown" | _ -> "Not supported ISA" diff --git a/src/Core/IntervalMap.fs b/src/Core/IntervalMap.fs index 9198c89d..494a1e94 100644 --- a/src/Core/IntervalMap.fs +++ b/src/Core/IntervalMap.fs @@ -64,13 +64,13 @@ module IntervalMap = let findAll (range: AddrRange) (IntervalMap m) = let il = range.Min let ih = range.Max - let dropMatcher (e: InterMonoid) = Prio il < e.GetMax () + let dropMatcher (e: InterMonoid) = Prio il <= e.GetMax () let rec matches xs = let v = Op.DropUntil dropMatcher xs match Op.ViewL v with | Nil -> [] | Cons (x, xs) -> x :: matches xs - Op.TakeUntil (fun (elt: InterMonoid) -> Key ih <= elt.GetMin ()) m + Op.TakeUntil (fun (elt: InterMonoid) -> Key ih < elt.GetMin ()) m |> matches /// Find exactly matching interval. @@ -82,7 +82,7 @@ module IntervalMap = /// Find an interval that has the same low bound (Min) as the given address. let tryFindByMin (addr: Addr) (IntervalMap m) = let comp (elt: InterMonoid) = Key addr <= elt.GetMin () - if Prio addr < ((m :> IMeasured<_>).Measurement).GetMax () then + if Prio addr <= ((m :> IMeasured<_>).Measurement).GetMax () then let z = (m.Monoid :> IMonoid>).Zero let _, x, _ = Op.SplitTree comp z m if x.Min = addr then Some (x.Val) else None @@ -93,11 +93,11 @@ module IntervalMap = let includeRange (range: AddrRange) (IntervalMap m) = let il = range.Min let ih = range.Max - if Prio il < ((m :> IMeasured<_>).Measurement).GetMax () then + if Prio il <= ((m :> IMeasured<_>).Measurement).GetMax () then let z = (m.Monoid :> IMonoid>).Zero let _, x, _ = - Op.SplitTree (fun (e: InterMonoid) -> Prio il < e.GetMax()) z m - x.Min < ih + Op.SplitTree (fun (e: InterMonoid) -> Prio il <= e.GetMax()) z m + x.Min <= ih else false /// Check whether the given address exists in the interval tree. diff --git a/src/Core/IntervalSet.fs b/src/Core/IntervalSet.fs index bd69bf5c..49d63927 100644 --- a/src/Core/IntervalSet.fs +++ b/src/Core/IntervalSet.fs @@ -60,24 +60,24 @@ module IntervalSet = let includeRange (range: AddrRange) (IntervalSet s) = let il = range.Min let ih = range.Max - if Prio il < ((s :> IMeasured<_>).Measurement).GetMax () then + if Prio il <= ((s :> IMeasured<_>).Measurement).GetMax () then let z = (s.Monoid :> IMonoid>).Zero let (_, x, _) = - Op.SplitTree (fun (e: InterMonoid) -> Prio il < e.GetMax()) z s - x.Min < ih + Op.SplitTree (fun (e: InterMonoid) -> Prio il <= e.GetMax()) z s + x.Min <= ih else false /// Find all overlapping intervals. let findAll (range: AddrRange) (IntervalSet s) = let il = range.Min let ih = range.Max - let dropMatcher (e: InterMonoid) = Prio il < e.GetMax () + let dropMatcher (e: InterMonoid) = Prio il <= e.GetMax () let rec matches acc xs = let v = Op.DropUntil dropMatcher xs match Op.ViewL v with | Nil -> acc | Cons (x: IntervalSetElem, xs) -> matches (x.Val :: acc) xs - Op.TakeUntil (fun (elt: InterMonoid) -> Key ih <= elt.GetMin ()) s + Op.TakeUntil (fun (elt: InterMonoid) -> Key ih < elt.GetMin ()) s |> matches [] /// Find and return the first matching interval from the given range. @@ -87,10 +87,10 @@ module IntervalSet = /// Find and return the first matching interval from the given address. let tryFindByAddr addr s = - tryFind (AddrRange (addr, addr + 1UL)) s + tryFind (AddrRange (addr, addr)) s /// Check whether the given address exists in the interval set. - let containsAddr addr s = includeRange (AddrRange (addr, addr + 1UL)) s + let containsAddr addr s = includeRange (AddrRange (addr, addr)) s /// Check whether the exact interval exists in the interval set. let contains (i: AddrRange) (IntervalSet s) = @@ -105,17 +105,18 @@ module IntervalSet = else false containLoop r - let remove (i: AddrRange) (IntervalSet s) = + /// Assuming the given AddrRange is in the set, remove the range. + let remove (range: AddrRange) (IntervalSet s) = let l, r = - Op.Split (fun (e: InterMonoid) -> Key i.Min <= e.GetMin ()) s + Op.Split (fun (e: InterMonoid) -> Key range.Min <= e.GetMin ()) s let rec rmLoop l r = match Op.ViewL r with | Nil -> raise InvalidAddrRangeException | Cons (x: IntervalSetElem, xs) - when x.Min = i.Min && x.Max = i.Max -> + when x.Min = range.Min && x.Max = range.Max -> Op.Concat l xs | Cons (x, xs) -> - if i.Min = x.Min then rmLoop (Op.Snoc l x) xs + if range.Min = x.Min then rmLoop (Op.Snoc l x) xs else raise InvalidAddrRangeException IntervalSet <| rmLoop l r diff --git a/src/Core/LEB128.fs b/src/Core/LEB128.fs index 23489945..bc8a8d9d 100644 --- a/src/Core/LEB128.fs +++ b/src/Core/LEB128.fs @@ -44,7 +44,7 @@ module private LEB128Helper = | b :: rest -> let v' = v ||| (cast (b &&& 0x7fuy) <<< (offset * 7)) convLoop v' (offset + 1) rest - if bytes.Length = 0 then invalidArg "decode" "Invalid buffer length" + if bytes.Length = 0 then invalidArg (nameof bytes) "Invalid buffer length" else let len = if bytes.Length > maxLen then maxLen else bytes.Length let bs, offset = decodeLoop [] bytes 0 bytes.[0] len diff --git a/src/Core/ConcurrentLRU.fs b/src/Core/LRUCache.fs similarity index 52% rename from src/Core/ConcurrentLRU.fs rename to src/Core/LRUCache.fs index bc040fa6..58fd84ef 100644 --- a/src/Core/ConcurrentLRU.fs +++ b/src/Core/LRUCache.fs @@ -22,73 +22,79 @@ SOFTWARE. *) - namespace B2R2 open System +open System.Collections.Generic open System.Threading [] -type private DoubleLinkedListNode<'T when 'T : equality> = { - mutable Prev : DoubleLinkedListNode<'T> - mutable Next : DoubleLinkedListNode<'T> - Value : 'T +type private DoubleLinkedListNode<'K, 'T when 'K: equality and 'T: equality> = { + mutable Prev: DoubleLinkedListNode<'K, 'T> + mutable Next: DoubleLinkedListNode<'K, 'T> + Key: 'K + Value: 'T } with override __.GetHashCode () = hash __.Value - override __.Equals x = - match x with - | :? DoubleLinkedListNode<'T> as v -> v.Value = __.Value + override __.Equals rhs = + match rhs with + | :? DoubleLinkedListNode<'K, 'T> as rhs -> __.Value = rhs.Value | _ -> false -/// Least Recently Used Cache supporting concurrency. -type ConcurrentLRU<'K, 'V when 'K : equality and 'V : equality>(capacity: int) = - let nil = Unchecked.defaultof> - let dict = new Collections.Generic.Dictionary<'K, DoubleLinkedListNode<'V>> () +/// This is a cacheable operation, which will be executed when there's no +/// already cached item. +type ICacheableOperation<'Arg, 'V when 'V: equality> = + abstract Perform: 'Arg -> 'V + +/// Least Recently Used Cache supporting concurrency. The capacity decides how +/// many entries to store. +type LRUCache<'K, 'V when 'K: equality and 'V: equality> (capacity: int) = + let nil = Unchecked.defaultof> + let dict = Dictionary<'K, DoubleLinkedListNode<'K, 'V>> () let lock = ref (new Object ()) let mutable head = nil let mutable tail = nil let mutable size = 0 - member private __.AcquireLock () = + member inline private __.AcquireLock () = try Monitor.Enter (lock) finally () - member private __.ReleaseLock () = + member inline private __.ReleaseLock () = Monitor.Exit (lock) - member private __.InsertBack o = - if head = nil then head <- o (* empty *) - else tail.Next <- o - o.Prev <- tail - o.Next <- nil - tail <- o + member private __.InsertBack v = + if head = nil then head <- v else tail.Next <- v + v.Prev <- tail + v.Next <- nil + tail <- v size <- size + 1 - o + v - member private __.Remove o = - if o.Prev = nil then head <- o.Next - else o.Prev.Next <- o.Next - if o.Next = nil then tail <- o.Prev - else o.Next.Prev <- o.Prev + member private __.Remove v = + if v.Prev = nil then head <- v.Next else v.Prev.Next <- v.Next + if v.Next = nil then tail <- v.Prev else v.Next.Prev <- v.Prev size <- size - 1 member __.Count with get () = size - member __.GetOrAdd (key: 'K) (proc: 'K -> 'V) = + member __.GetOrAdd (key: 'K) (op: ICacheableOperation<_, 'V>) arg = __.AcquireLock () - let o = + let v = match dict.TryGetValue key with - | true, out -> - __.Remove out - __.InsertBack out + | true, v -> + __.Remove v + __.InsertBack v | _ -> - if size >= capacity then __.Remove head - let out = { Prev = nil; Next = nil; Value = proc key } - dict.Add (key, out) - __.InsertBack out + if size >= capacity then + dict.Remove head.Key |> ignore + __.Remove head + let v = { Prev = nil; Next = nil; Key = key; Value = op.Perform arg } + dict.Add (key, v) + __.InsertBack v __.ReleaseLock () - o.Value + v.Value member __.Clear () = __.AcquireLock () diff --git a/src/Core/Logger.fs b/src/Core/Logger.fs index 757dfd37..860525d2 100644 --- a/src/Core/Logger.fs +++ b/src/Core/Logger.fs @@ -28,7 +28,7 @@ open System.IO /// How verbose do we want to log messages? type LogLevel = - /// Most succint = level 1. + /// Most succinct = level 1. | L1 = 1 /// Normal = level 2. | L2 = 2 @@ -37,6 +37,23 @@ type LogLevel = /// Most verbose = level 4. | L4 = 4 +/// Helper module for LogLevel +[] +module LogLevel = + let ofString (str: string) = + match str.ToLower () with + | "1" | "l1" | "quiet" | "q" -> LogLevel.L1 + | "3" | "l3" | "verbose" | "v" -> LogLevel.L3 + | "4" | "l4" -> LogLevel.L4 + | _ -> LogLevel.L2 + + let toString = function + | LogLevel.L1 -> "L1" + | LogLevel.L2 -> "L2" + | LogLevel.L3 -> "L3" + | LogLevel.L4 -> "L4" + | _ -> Utils.impossible () + /// Basic logging facility. type ILogger = /// Log string (without newline). diff --git a/src/Core/OS.fs b/src/Core/OS.fs index 9483fa4c..7956d77f 100644 --- a/src/Core/OS.fs +++ b/src/Core/OS.fs @@ -35,6 +35,8 @@ type OS = | Linux = 2 /// MacOSX. | MacOSX = 3 + /// Unknown + | UnknownOS = 4 /// A helper module for OS type. module OS = @@ -56,10 +58,13 @@ module OS = | "windows" | "win" -> OS.Windows | "linux" -> OS.Linux | "macos" | "macosx" | "mac" | "osx" -> OS.MacOSX - | _ -> invalidArg "OS" "Unknown OS string" + | "unknown" -> OS.UnknownOS + | _ -> invalidArg (nameof s) "Unknown OS string" - let toString = function + let toString os = + match os with | OS.Windows -> "Windows" | OS.Linux -> "Linux" | OS.MacOSX -> "Mac" - | _ -> invalidArg "OS" "Wrong enum" + | OS.UnknownOS -> "UnknownOS" + | _ -> invalidArg (nameof os) "Wrong enum" diff --git a/src/BinGraph/Edges.fs b/src/Core/OutString.fs similarity index 64% rename from src/BinGraph/Edges.fs rename to src/Core/OutString.fs index 731f698f..0733df18 100644 --- a/src/BinGraph/Edges.fs +++ b/src/Core/OutString.fs @@ -22,17 +22,27 @@ SOFTWARE. *) -namespace B2R2.BinGraph - -/// Missing edge. -exception EdgeNotFoundException - -/// Edge ID is a tuple of two node IDs (source node ID, destination node ID). -type EdgeID = VertexID * VertexID - -/// An edge in a directed graph. -type Edge<'E> = Edge of 'E - -type E<'E> = Edge<'E> - -// vim: set tw=80 sts=2 sw=2: +namespace B2R2 + +open System + +/// OutString represents an output string generated from rear-end applications. +type OutString = + | OutputNormal of string + | OutputColored of ColoredString + | OutputNewLine + +module OutString = + let internal toConsole = function + | OutputNormal s -> Console.Write s + | OutputColored s -> ColoredString.toConsole s + | OutputNewLine -> Console.WriteLine () + + let internal toConsoleLine outstring = + toConsole outstring + Console.WriteLine () + + let toString = function + | OutputNormal s -> s + | OutputColored cs -> ColoredString.toString cs + | OutputNewLine -> Environment.NewLine diff --git a/src/BinEssence/ControlFlowGraph.fs b/src/Core/PersistentQueue.fs similarity index 53% rename from src/BinEssence/ControlFlowGraph.fs rename to src/Core/PersistentQueue.fs index 88c72b98..25ec9fe3 100644 --- a/src/BinEssence/ControlFlowGraph.fs +++ b/src/Core/PersistentQueue.fs @@ -22,34 +22,44 @@ SOFTWARE. *) -namespace B2R2.BinEssence +namespace B2R2 -open B2R2.BinGraph +/// Persistent queue using two lists. +type PersistentQueue<'T> = + private PQ of 'T list * 'T list -type ControlFlowGraph<'D, 'E when 'D :> BasicBlock and 'D : equality> - (core: GraphCore<'D, 'E, DiGraph<'D, 'E>>) = - inherit DiGraph<'D, 'E> (core) +[] +module PersistentQueue = -type IRCFG = ControlFlowGraph + /// An empty queue. + [] + let empty = PQ ([], []) -[] -module IRCFG = - let private initializer core = - IRCFG (core) :> DiGraph - - let private initImperative () = - ImperativeCore (initializer, UnknownEdge) - |> IRCFG - :> DiGraph - - let private initPersistent () = - PersistentCore (initializer, UnknownEdge) - |> IRCFG - :> DiGraph - - /// Initialize IRCFG based on the implementation type. - let init = function - | ImperativeGraph -> initImperative () - | PersistentGraph -> initPersistent () - -// vim: set tw=80 sts=2 sw=2: + /// Check if the given queue is empty. + [] + let isEmpty q = + match q with + | PQ ([], []) -> true + | _ -> false + + /// Enqueue an element to the queue. + [] + let enqueue q elt = + match q with + | PQ (front, back) -> PQ (elt :: front, back) + + /// Dequeue an element from the queue. + [] + let dequeue q = + match q with + | PQ ([], []) -> raise (System.InvalidOperationException ()) + | PQ (front, elt :: back) -> elt, PQ (front, back) + | PQ (front, []) -> + let back = List.rev front + back.Head, PQ ([], back.Tail) + + /// Filter elements based on the given predicate. + [] + let filter pred q = + match q with + | PQ (front, back) -> PQ (List.filter pred front, List.filter pred back) diff --git a/src/Core/Printer.fs b/src/Core/Printer.fs new file mode 100644 index 00000000..07f944fd --- /dev/null +++ b/src/Core/Printer.fs @@ -0,0 +1,364 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2 + +open System +open System.Text + +/// Define a column of a table with a specified width in bytes (# of chars). +type TableColumn = + | RightAligned of width: int + | LeftAligned of width: int +with + static member ofPaddedString isLast (s: string) column = + match column with + | RightAligned w -> let s = s.PadLeft (w) in if isLast then s else s + " " + | LeftAligned w -> if isLast then s else s.PadRight (w) + " " + +/// Define a output configuration of a table. +type TableConfig = TableColumn list + +module CS = ColoredSegment + +module private PrinterConst = + let [] colWidth = 24 + let [] cacheLimit = 16777216 + +/// Any B2R2's layers should *not* use System.Console or `printfn` to directly +/// output strings. Instead, they should resort to the Printer to "indirectly" +/// print out strings. +[] +type Printer () = + /// Print out the given OutString. + abstract Print: OutString -> unit + + /// Print out the given ColoredString. + abstract Print: ColoredString -> unit + + /// Print out the formated string. + abstract Print: string * [] args: obj [] -> unit + + /// Print out the given OutString with newline. + abstract PrintLine: os: OutString -> unit + + /// Print out the given ColoredString with newline. + abstract PrintLine: cs: ColoredString -> unit + + /// Print out the formated string with newline. + abstract PrintLine: s: string -> unit + + /// Print out the formated string with newline. + abstract PrintLine: fmt: string * [] args: obj [] -> unit + + /// Print out a newline. + abstract PrintLine: unit -> unit + + /// Print out a newline only if the previous output was not empty (i.e., a + /// line with only a newline). In other words, this function will not output + /// anything if the previous output was an empty line. This is to make sure we + /// output only one single empty line in some situations. + abstract PrintLineIfPrevLineWasNotEmpty: unit -> unit + + /// Print out table row for the given ColoredString list. + abstract PrintRow: bool * TableConfig * ColoredString list -> unit + + /// Print out table row for the given string list. + abstract PrintRow: bool * TableConfig * string list -> unit + + /// Print out the section title. + abstract PrintSectionTitle: string -> unit + + /// Print out the subsection title. + abstract PrintSubsectionTitle: string -> unit + + /// Print out the subsubsection title. + abstract PrintSubsubsectionTitle: string -> unit + + /// Print out a line with two columns. Each column has a predefined width. + abstract PrintTwoCols: string -> string -> unit + + /// Print out a line with two columns. Each column has a predefined width, and + /// the second column will be colored. + abstract PrintTwoColsWithColorOnSnd: string -> ColoredString -> unit + + /// Flush out everything. + abstract Flush: unit -> unit + + [] + static member printErrorToConsole str = + [ CS.nocolor "[*] Error: "; CS.red str ] |> Printer.printToConsoleLine + Printer.printToConsoleLine () + + [] + static member printToConsole s = + ColoredString.toConsole s + + [] + static member printToConsole (s: string, [] args) = + Console.Write (s, args) + + [] + static member printToConsoleLine s = + ColoredString.toConsoleLine s + + [] + static member printToConsoleLine (s: string, [] args) = + Console.WriteLine (s, args) + + [] + static member printToConsoleLine () = + Console.WriteLine () + +/// ConsolePrinter simply prints out strings to console whenever a print method +/// is called. This printer does not perform any caching, so it immediately +/// flushes out all the strings to console. +type ConsolePrinter () = + inherit Printer () + + let mutable lastLineWasEmpty = false + + override __.Print s = + OutString.toConsole s + + override __.Print s = + ColoredString.toConsole s + + override __.Print (s: string, [] args) = + Console.Write (s, args) + + override __.PrintLine os = + OutString.toConsoleLine os + lastLineWasEmpty <- false + + override __.PrintLine cs = + ColoredString.toConsoleLine cs + lastLineWasEmpty <- false + + override __.PrintLine (s: string) = + Console.WriteLine (s) + lastLineWasEmpty <- false + + override __.PrintLine (fmt: string, [] args) = + Console.WriteLine (fmt, args) + lastLineWasEmpty <- fmt.Length = 0 + + override __.PrintLine () = + Console.WriteLine () + lastLineWasEmpty <- true + + override __.PrintLineIfPrevLineWasNotEmpty () = + if lastLineWasEmpty then () + else Console.WriteLine () + lastLineWasEmpty <- true + + override __.PrintRow (indent, cfg: TableConfig, css: ColoredString list) = + let lastIdx = List.length cfg - 1 + List.zip cfg css + |> List.iteri (fun i (col, cs) -> + if indent then Console.Write (" ") else () + match cs with + | (c, s) :: rest -> + (c, TableColumn.ofPaddedString (i = lastIdx) s col) :: rest + |> __.Print + | [] -> ()) + Console.WriteLine () + lastLineWasEmpty <- false + + override __.PrintRow (indent, cfg: TableConfig, strs: string list) = + let lastIdx = List.length cfg - 1 + List.zip cfg strs + |> List.iteri (fun i (c, s) -> + if indent then + Console.Write (" ") + Console.Write (TableColumn.ofPaddedString (i = lastIdx) s c)) + Console.WriteLine () + lastLineWasEmpty <- false + + override __.PrintSectionTitle title = + [ CS.red "# "; CS.nocolor title ] + |> __.PrintLine + __.PrintLine () + lastLineWasEmpty <- true + + override __.PrintSubsectionTitle (str: string) = + __.PrintLine (" - " + str) + lastLineWasEmpty <- false + + override __.PrintSubsubsectionTitle (str: string) = + __.PrintLine (" * " + str) + lastLineWasEmpty <- false + + override __.PrintTwoCols (col1: string) (col2: string) = + __.Print (col1.PadLeft PrinterConst.colWidth + " ") + __.PrintLine col2 + lastLineWasEmpty <- false + + override __.PrintTwoColsWithColorOnSnd (col1: string) (col2: ColoredString) = + __.Print (col1.PadLeft PrinterConst.colWidth + " ") + __.PrintLine col2 + lastLineWasEmpty <- false + + override __.Flush () = () + +/// ConsoleCachedPrinter prints out non-colored strings only when the Flush +/// method is called. All the colored strings will be normalized to plain +/// strings. It will simply stack up all the output candidates before Flush is +/// called. This is useful for performance-critical applications. +type ConsoleCachedPrinter () = + inherit Printer () + + let mutable lastLineWasEmpty = false + let cache = StringBuilder () + + member private __.Add (s: string) = + cache.Append (s) |> ignore + if cache.Length <= PrinterConst.cacheLimit then () + else __.Flush () + + override __.Print s = + OutString.toString s |> __.Add + + override __.Print s = + ColoredString.toString s |> __.Add + + override __.Print (s: string, [] args) = + String.Format (s, args) |> __.Add + + override __.PrintLine os = + OutString.toString os + Environment.NewLine |> __.Add + lastLineWasEmpty <- false + + override __.PrintLine cs = + ColoredString.toString cs + Environment.NewLine |> __.Add + lastLineWasEmpty <- false + + override __.PrintLine (s: string) = + s + Environment.NewLine |> __.Add + lastLineWasEmpty <- false + + override __.PrintLine (fmt: string, [] args) = + String.Format (fmt, args) + Environment.NewLine |> __.Add + lastLineWasEmpty <- fmt.Length = 0 + + override __.PrintLine () = + __.Add Environment.NewLine + lastLineWasEmpty <- true + + override __.PrintLineIfPrevLineWasNotEmpty () = + if lastLineWasEmpty then () + else __.Add Environment.NewLine + lastLineWasEmpty <- true + + override __.PrintRow (indent, cfg: TableConfig, css: ColoredString list) = + let lastIdx = List.length cfg - 1 + List.zip cfg css + |> List.iteri (fun i (col, cs) -> + if indent then __.Add (" ") else () + match cs with + | (_, s) :: rest -> + (TableColumn.ofPaddedString (i = lastIdx) s col + + ColoredString.toString rest) + |> __.Add + | [] -> ()) + __.Add Environment.NewLine + lastLineWasEmpty <- false + + override __.PrintRow (indent, cfg: TableConfig, strs: string list) = + let lastIdx = List.length cfg - 1 + List.zip cfg strs + |> List.iteri (fun i (c, s) -> + if indent then __.Add (" ") + TableColumn.ofPaddedString (i = lastIdx) s c |> __.Add) + __.Add Environment.NewLine + lastLineWasEmpty <- false + + override __.PrintSectionTitle title = + "# " + title + Environment.NewLine + Environment.NewLine |> __.Add + lastLineWasEmpty <- true + + override __.PrintSubsectionTitle (str: string) = + (" - " + str) |> __.Add + __.Add Environment.NewLine + lastLineWasEmpty <- false + + override __.PrintSubsubsectionTitle (str: string) = + (" * " + str) |> __.Add + __.Add Environment.NewLine + lastLineWasEmpty <- false + + override __.PrintTwoCols (col1: string) (col2: string) = + col1.PadLeft PrinterConst.colWidth + " " |> __.Add + col2 |> __.Add + __.Add Environment.NewLine + lastLineWasEmpty <- false + + override __.PrintTwoColsWithColorOnSnd (col1: string) (col2: ColoredString) = + col1.PadLeft PrinterConst.colWidth + " " |> __.Add + ColoredString.toString col2 |> __.Add + __.Add Environment.NewLine + lastLineWasEmpty <- false + + override __.Flush () = + cache.ToString () |> Console.Write + cache.Clear () |> ignore + +/// ConsoleCachedPrinter does not print anything. This is the same as +/// redirecting outputs to /dev/null. +type ConsoleNullPrinter () = + inherit Printer () + + override __.Print (_: OutString) = () + + override __.Print (_: ColoredString) = () + + override __.Print (_: string, [] _args) = () + + override __.PrintLine (_: OutString) = () + + override __.PrintLine (_: ColoredString) = () + + override __.PrintLine (_: string) = () + + override __.PrintLine (_: string, [] _args) = () + + override __.PrintLine () = () + + override __.PrintLineIfPrevLineWasNotEmpty () = () + + override __.PrintRow (_: bool, _: TableConfig, _: ColoredString list) = () + + override __.PrintRow (_: bool, _: TableConfig, _: string list) = () + + override __.PrintSectionTitle _ = () + + override __.PrintSubsectionTitle (_: string) = () + + override __.PrintSubsubsectionTitle (_: string) = () + + override __.PrintTwoCols (_: string) (_: string) = () + + override __.PrintTwoColsWithColorOnSnd (_: string) (_: ColoredString) = () + + override __.Flush () = () diff --git a/src/Core/ProgramPoint.fs b/src/Core/ProgramPoint.fs index d92a56d4..925117ba 100644 --- a/src/Core/ProgramPoint.fs +++ b/src/Core/ProgramPoint.fs @@ -37,7 +37,7 @@ type ProgramPoint (addr, pos) = | :? ProgramPoint as o -> o.Address = __.Address && o.Position = __.Position | _ -> false override __.GetHashCode () = hash (__.Address, __.Position) - override __.ToString () = addr.ToString ("X") + ":" + pos.ToString () + override __.ToString () = String.u64ToHexNoPrefix addr + ":" + pos.ToString () /// Get a fake program point to represent a fake vertex, which does not exist /// in a CFG. Fake vertices are useful for representing external function @@ -46,13 +46,14 @@ type ProgramPoint (addr, pos) = static member IsFake (p: ProgramPoint) = p.Address = 0UL && p.Position = -1 static member Next (p: ProgramPoint) = - ProgramPoint (p.Address, p.Position + 1) + if ProgramPoint.IsFake p then p + else ProgramPoint (p.Address, p.Position + 1) interface System.IComparable with - member __.CompareTo (o) = - match o with - | :? ProgramPoint as o -> + member __.CompareTo (rhs) = + match rhs with + | :? ProgramPoint as rhs -> (* To lexicographically sort leaders. Being too pedantic here. *) - if __.Address = o.Address then compare __.Position o.Position - else compare __.Address o.Address - | _ -> invalidArg "ProgramPoint" "Invalid comparison" + if __.Address = rhs.Address then compare __.Position rhs.Position + else compare __.Address rhs.Address + | _ -> invalidArg (nameof rhs) "Invalid comparison" diff --git a/src/Core/README.md b/src/Core/README.md new file mode 100644 index 00000000..13f3bc1d --- /dev/null +++ b/src/Core/README.md @@ -0,0 +1,12 @@ +# B2R2.Core + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.Core Package? + +`B2R2.Core` declares types and values that are located at the top-level +namespace `B2R2`. All of them form the basis of our framework. diff --git a/src/Core/RegType.fs b/src/Core/RegType.fs index 5ad37664..fefd15b1 100644 --- a/src/Core/RegType.fs +++ b/src/Core/RegType.fs @@ -93,7 +93,7 @@ module RegType = let toByteWidth t = let t = toBitWidth t if t % 8 = 0 then t / 8 - else failwith "Failed to get byte width." + else Utils.impossible () /// /// Get the corresponding integer RegType from the given bit width. When a @@ -119,8 +119,6 @@ module RegType = /// let fromByteWidth n = fromBitWidth (n * 8) - /// Get the double width of RegType. - /// /// Get a double-sized RegType from a given RegType. /// @@ -130,37 +128,12 @@ module RegType = /// let double (t: RegType) = 2 * t - /// Get a bitmask of the given RegType size. - /// /// Get a bitmask (in integer) from the given RegType. /// /// /// A bit mask in big integer. /// - let getMask = function - | 1 -> 1I - | 8 -> 255I - | 16 -> 65535I - | 32 -> 4294967295I - | 64 -> 18446744073709551615I - | 128 -> BigInteger.mask128 - | 256 -> BigInteger.mask256 - | 512 -> BigInteger.mask512 - | t when t < 512 -> (bigint.One <<< (int t)) - bigint.One - | _ -> raise InvalidRegTypeException - - /// - /// Get a bitmask (in integer) from the given RegType. - /// - /// - /// A bit mask in uint64. - /// - let getUInt64Mask = function - | 1 -> 1UL - | 8 -> 255UL - | 16 -> 65535UL - | 32 -> 4294967295UL - | 64 -> 18446744073709551615UL - | t when t < 64 -> (1UL <<< (int t)) - 1UL - | _ -> raise InvalidRegTypeException + let getMask t = + if t <= 64 then System.UInt64.MaxValue >>> (64 - int t) |> bigint + else (bigint.One <<< (int t)) - bigint.One diff --git a/src/Core/RegisterSet.fs b/src/Core/RegisterSet.fs index ac3cc1d9..94ba2d8e 100644 --- a/src/Core/RegisterSet.fs +++ b/src/Core/RegisterSet.fs @@ -24,13 +24,196 @@ namespace B2R2 -open B2R2 +/// Raised when two RegisterSets with two distinct tags operate. +exception RegisterSetTagMismatchException + +/// A tag used in RegisterSet for identifying distinct set of registers for +/// different ISAs. +type RegisterSetTag = + | Empty = 0 + | Intel = 1 + | ARM32 = 2 + | ARM64 = 3 + | MIPS = 4 + | EVM = 5 + | TMS320C6000 = 6 + | CIL = 7 + | AVR = 8 + +/// RegisterSet is an efficient set data structure using arrays for managing a +/// set of registers. +[] +type RegisterSet () = + /// Tag identifies ISA. + abstract member Tag: RegisterSetTag + + /// Create a new RegisterSet from a given array and a set. This method should + /// be overridden by ISA-specific RegisterSet implementation. + abstract member New: uint64 [] -> Set -> RegisterSet + + /// Obtain a unique index to the internal array from a given RegisterID. + abstract member RegIDToIndex: RegisterID -> int + + /// Obtain a RegisterID from a given index. + abstract member IndexToRegID: int -> RegisterID + + /// Size of the internal array. + abstract member ArrSize: int + + /// An internal array storing the register set. + abstract member BitArray: uint64 [] + + /// A backup storage for unknown variables, which does not have a RegisterID. + /// For example, when writing a symbolic executor, we may encounter unknown + /// variables, i.e., fresh symbolic variables. We store them in this set. + abstract member AuxSet: Set + + /// Add a register to the set. + abstract member Add: RegisterID -> RegisterSet + + /// Remove a register from the set. + abstract member Remove: RegisterID -> RegisterSet + + /// Union of two register sets. + abstract member Union: RegisterSet -> RegisterSet + + /// Intersection of two register sets. + abstract member Intersect: RegisterSet -> RegisterSet + + /// Check if a register exists in the set. + abstract member Exists: RegisterID -> bool + + /// Check if the set is empty. + abstract member IsEmpty: unit -> bool + + /// Return the set of register indices. + abstract member ToSet: unit -> Set + + /// Create an internal bit array of size. + static member inline MakeInternalBitArray size = + Array.zeroCreate size + + /// Get the bucket and the offset from the given index. + static member inline GetBucketAndOffset (idx) = + struct (idx / 64, idx &&& 0x3F) + + /// Get the register index from the given bucket id and the offset. + static member inline GetIndex bucketId offset = + bucketId * 64 + offset + + /// Check if the nth bit is set on the value v. + static member inline IsBitSet nth v = + (v &&& (1UL <<< nth)) <> 0UL + +/// Empty register set. +type EmptyRegisterSet () = + inherit RegisterSet () + override __.Tag = RegisterSetTag.Empty + override __.ArrSize = 0 + override __.New _ _ = Utils.impossible () + override __.RegIDToIndex _ = Utils.impossible () + override __.IndexToRegID _ = Utils.impossible () + override __.BitArray = [||] + override __.AuxSet = Set.empty + override __.Add _ = Utils.impossible () + override __.Remove _ = __ :> RegisterSet + override __.Union o = o + override __.Intersect o = __ :> RegisterSet + override __.Exists _ = false + override __.IsEmpty () = true + override __.ToSet () = Set.empty + +module private EmptyRegisterSet = + let instance = EmptyRegisterSet () :> RegisterSet + +/// Non-empty register set. +[] +type NonEmptyRegisterSet (bitArray: uint64 [], s: Set) = + inherit RegisterSet () + +#if DEBUG + member __.CheckTag (o: RegisterSet) = + if __.Tag = o.Tag then () + else raise RegisterSetTagMismatchException +#endif + + override __.GetHashCode () = hash __.BitArray + + override __.Equals obj = + match obj with + | :? NonEmptyRegisterSet as rhs -> __.BitArray = rhs.BitArray + | _ -> false + + override __.BitArray = bitArray + + override __.AuxSet = s + + override __.Add rid = + match __.RegIDToIndex rid with + | -1 -> __.New bitArray (Set.add rid s) + | idx -> + let struct (bucket, offset) = RegisterSet.GetBucketAndOffset idx + let newArr = Array.copy bitArray + newArr.[bucket] <- newArr.[bucket] ||| (1UL <<< offset) + __.New newArr s + + override __.Remove id = + match __.RegIDToIndex id with + | -1 -> __.New bitArray (Set.remove id s) + | id -> + let struct (bucket, offset) = RegisterSet.GetBucketAndOffset id + let newArr = Array.copy bitArray + newArr.[bucket] <- newArr.[bucket] &&& ~~~(1UL <<< offset) + __.New newArr s + + override __.Union (other: RegisterSet) = + if other.Tag = RegisterSetTag.Empty then __ :> RegisterSet + else +#if DEBUG + __.CheckTag other +#endif + let newArr = Array.mapi (fun i e -> e ||| other.BitArray.[i]) bitArray + __.New newArr (Set.union __.AuxSet other.AuxSet) + + override __.Intersect (other: RegisterSet) = + if other.Tag = RegisterSetTag.Empty then EmptyRegisterSet.instance + else +#if DEBUG + __.CheckTag other +#endif + let newArr = Array.mapi (fun i e -> e &&& other.BitArray.[i]) bitArray + __.New newArr <| Set.intersect __.AuxSet other.AuxSet + + override __.Exists id = + match __.RegIDToIndex id with + | -1 -> Set.contains id __.AuxSet + | id -> + let struct (bucket, offset) = RegisterSet.GetBucketAndOffset id + (bitArray.[bucket] &&& (1UL <<< offset)) <> 0UL + + override __.IsEmpty () = + (Array.exists (fun x -> x <> 0UL) bitArray |> not) && Set.isEmpty __.AuxSet + + member private __.FoldRegIndicesAux set bid v offset = + if offset < 64 then + let set = + if (v &&& 1UL) = 1UL then Set.add (RegisterSet.GetIndex bid offset) set + else set + __.FoldRegIndicesAux set bid (v >>> 1) (offset + 1) + else set + + member private __.FoldRegIndices set bid v = __.FoldRegIndicesAux set bid v 0 + + override __.ToSet () = + Array.foldi __.FoldRegIndices Set.empty bitArray + |> fst + |> Set.map __.IndexToRegID + |> Set.union __.AuxSet /// A helper module for RegisterSet. [] -[] module RegisterSet = - let empty = EmptyRegisterSet.Instance + let empty = EmptyRegisterSet.instance let inline union (lhs: RegisterSet) rhs = lhs.Union rhs diff --git a/src/Core/TypeExtensions.fs b/src/Core/TypeExtensions.fs index 6f3c8a7d..e0224b22 100644 --- a/src/Core/TypeExtensions.fs +++ b/src/Core/TypeExtensions.fs @@ -24,12 +24,17 @@ namespace B2R2 +open System.Collections.Generic + /// Extended Array. +[] module Array = let foldi folder acc arr = - Array.fold (fun (acc, idx) elt -> (folder acc idx elt, idx + 1)) (acc, 0) arr + Array.fold (fun (acc, idx) elt -> + (folder acc idx elt, idx + 1)) (acc, 0) arr /// Extended String. +[] module String = let explode (str: string) = [for ch in str do yield ch done] @@ -42,7 +47,41 @@ module String = /// Convert a byte array to a string. let fromBytes (bs: byte []) = Array.map char bs |> System.String + let wrapParen s = + "(" + s + ")" + + let wrapSqrdBracket s = + "[" + s + "]" + + let wrapAngleBracket s = + "<" + s + ">" + + let i32ToHex (v: int32) = + "0x" + v.ToString ("x") + + let u32ToHex (v: uint32) = + "0x" + v.ToString ("x") + + let u64ToHex (v: uint64) = + "0x" + v.ToString ("x") + + let i64ToHex (v: int64) = + "0x" + v.ToString ("x") + + let inline i32ToHexNoPrefix (v: int32) = + v.ToString ("x") + + let inline u32ToHexNoPrefix (v: uint32) = + v.ToString ("x") + + let inline u64ToHexNoPrefix (v: uint64) = + v.ToString ("x") + + let inline i64ToHexNoPrefix (v: int64) = + v.ToString ("x") + /// Extended BigInteger. +[] module BigInteger = /// Bitmask of size 128 bits. let mask128 = bigint.Subtract (bigint.Pow (2I, 128), bigint.One) @@ -57,6 +96,7 @@ module BigInteger = let getMask n = bigint.Pow (2I, n) - 1I /// Extended Int64. +[] module Int64 = /// Get a power from a 64-bit integer. let pow value power = @@ -68,6 +108,7 @@ module Int64 = else loop value (power - 1L) /// Extended Option. +[] module Option = /// Unwrap an option type. If the value is None, throw the exception (exn). let getWithExn (value: 'a option) exn = @@ -75,4 +116,53 @@ module Option = | Some v -> v | None -> raise exn +/// Extended Result. +[] +module Result = + /// Get the result assuming that there is no error. + let inline get res = + match res with + | Ok (r) -> r + | Error _ -> invalidOp "The Result type had an Error, but not handled." + + /// Is the result Ok? + let inline isOk res = + match res with + | Ok _ -> true + | _ -> false + +[] +module SortedList = + let rec private binSearch value lo hi (keys: IList<_>) (comp: Comparer<_>) = + if lo < hi then + let mid = (lo + hi) / 2 + if comp.Compare (keys.[mid], value) < 0 then + binSearch value (mid + 1) hi keys comp + else + binSearch value lo (mid - 1) keys comp + else lo + + /// Find the greatest key that is less than or equal to the given key from the + /// SortedList. If there's no such key, this function returns None. + let findGreatestLowerBoundKey (key: 'T) (list: SortedList<'T, _>) = + let comp = Comparer<'T>.Default + let keys = list.Keys + if keys.Count = 0 || comp.Compare (key, keys.[0]) <= 0 then None + else + let idx = binSearch key 0 (list.Count - 1) keys comp + if comp.Compare (keys.[idx], key) < 0 then keys.[idx] else keys.[idx - 1] + |> Some + + /// Find the least key that is greater than or equal to the given key from the + /// SortedList. If there's no such key, this function returns None. + let findLeastUpperBoundKey (key: 'T) (list: SortedList<'T, _>) = + let comp = Comparer<'T>.Default + let keys = list.Keys + let lastIdx = list.Count - 1 + if keys.Count = 0 || comp.Compare (keys.[lastIdx], key) <= 0 then None + else + let idx = binSearch key 0 lastIdx keys comp + if comp.Compare (keys.[idx], key) < 0 then keys.[idx + 1] else keys.[idx] + |> Some + // vim: set tw=80 sts=2 sw=2: diff --git a/src/Core/Utils.fs b/src/Core/Utils.fs index d9c1d2b7..d3a5df31 100644 --- a/src/Core/Utils.fs +++ b/src/Core/Utils.fs @@ -28,7 +28,7 @@ open System let assertEqual a b exn = if a = b then () else raise exn -let assertByCond cond exn = if cond then () else raise exn +let assertByCond condition exn = if condition then () else raise exn let futureFeature () = let trace = Diagnostics.StackTrace (true) @@ -56,14 +56,8 @@ let inline tupleToOpt result = | false, _ -> None | true, a -> Some a -let writeB2R2 newLine = - Console.ForegroundColor <- ConsoleColor.DarkCyan - Console.Write ("B") - Console.ForegroundColor <- ConsoleColor.DarkYellow - Console.Write ("2") - Console.ForegroundColor <- ConsoleColor.DarkCyan - Console.Write ("R") - Console.ForegroundColor <- ConsoleColor.DarkYellow - Console.Write ("2") - Console.ResetColor () - if newLine then Console.WriteLine () else () +let inline tripleFst (a, _, _) = a + +let inline tripleSnd (_, a, _) = a + +let inline tripleThd (_, _, a) = a diff --git a/src/Core/Utils.fsi b/src/Core/Utils.fsi index af2af909..d3ea56cd 100644 --- a/src/Core/Utils.fsi +++ b/src/Core/Utils.fsi @@ -53,5 +53,11 @@ val inline (===) : 'a -> 'a -> bool when 'a : not struct /// the TryGetValue pattern, e.g., IDictionary. val inline tupleToOpt: bool * 'a -> 'a option -/// Write B2R2 logo to console. We can selectively append a new line at the end. -val writeB2R2: newLine: bool -> unit +/// Return the first item of a triple. +val inline tripleFst: ('a * 'b * 'c) -> 'a + +/// Return the second item of a triple. +val inline tripleSnd: ('a * 'b * 'c) -> 'b + +/// Return the third item of a triple. +val inline tripleThd: ('a * 'b * 'c) -> 'c diff --git a/src/Core/WordSize.fs b/src/Core/WordSize.fs index 755318da..543e5242 100644 --- a/src/Core/WordSize.fs +++ b/src/Core/WordSize.fs @@ -27,8 +27,12 @@ namespace B2R2 /// B2R2 represents the word size of a CPU with WordSize, which can be either /// 32- or 64-bit. type WordSize = + | Bit8 = 8 + | Bit16 = 16 | Bit32 = 32 | Bit64 = 64 + | Bit128 = 128 + | Bit256 = 256 /// This exception is raised when an invalid WordSize is encountered. exception InvalidWordSizeException @@ -37,8 +41,12 @@ exception InvalidWordSizeException module WordSize = let bitTypeOfString = function + | "8" -> WordSize.Bit8 + | "16" -> WordSize.Bit16 | "32" -> WordSize.Bit32 | "64" -> WordSize.Bit64 + | "128" -> WordSize.Bit128 + | "256" -> WordSize.Bit256 | _ -> failwith "Unknown WordSize." /// Transform a word size into a byte length. @@ -46,12 +54,25 @@ module WordSize = /// Transform a word size into a RegType. let toRegType = function - | WordSize.Bit32 -> 32 - | WordSize.Bit64 -> 64 + | WordSize.Bit8 -> 8 + | WordSize.Bit16 -> 16 + | WordSize.Bit32 -> 32 + | WordSize.Bit64 -> 64 + | WordSize.Bit128 -> 128 + | WordSize.Bit256 -> 256 | _ -> failwith "Unknown WordSize." + /// Transform a word size into a string. + let toString wordSz = (toRegType wordSz).ToString () + /// Is the given word size 32 bit? let is32 wordSz = wordSz = WordSize.Bit32 /// Is the given word size 64 bit? let is64 wordSz = wordSz = WordSize.Bit64 + + /// Is the given word size 128 bit? + let is128 wordSz = wordSz = WordSize.Bit128 + + /// Is the given word size 256 bit? + let is256 wordSz = wordSz = WordSize.Bit256 \ No newline at end of file diff --git a/src/DataFlow.Tests/B2R2.DataFlow.Tests.fsproj b/src/DataFlow.Tests/B2R2.DataFlow.Tests.fsproj deleted file mode 100644 index 3e4fd419..00000000 --- a/src/DataFlow.Tests/B2R2.DataFlow.Tests.fsproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - netcoreapp3.0 - false - - - - - - - - - - - - - - - - - - - - diff --git a/src/DataFlow.Tests/DataFlow.Tests.fs b/src/DataFlow.Tests/DataFlow.Tests.fs deleted file mode 100644 index abffece4..00000000 --- a/src/DataFlow.Tests/DataFlow.Tests.fs +++ /dev/null @@ -1,171 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.DataFlow.Tests - -open Microsoft.VisualStudio.TestTools.UnitTesting - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinEssence -open B2R2.DataFlow -open B2R2.MiddleEnd - -[] -type PersistentDataFlowTests () = - - (* - Example 1: Fibonacci function - - unsigned int fib(unsigned int m) - { - unsigned int f0 = 0, f1 = 1, f2, i; - if (m <= 1) return m; - else { - for (i = 2; i <= m; i++) { - f2 = f0 + f1; - f0 = f1; - f1 = f2; - } - return f2; - } - } - - 00000000: 8B 54 24 04 mov edx,dword ptr [esp+4] - 00000004: 56 push esi - 00000005: 33 F6 xor esi,esi - 00000007: 8D 4E 01 lea ecx,[esi+1] - 0000000A: 3B D1 cmp edx,ecx - 0000000C: 77 04 ja 00000012 - 0000000E: 8B C2 mov eax,edx - 00000010: 5E pop esi - 00000011: C3 ret - 00000012: 4A dec edx - 00000013: 8D 04 31 lea eax,[ecx+esi] - 00000016: 8D 31 lea esi,[ecx] - 00000018: 8B C8 mov ecx,eax - 0000001A: 83 EA 01 sub edx,1 - 0000001D: 75 F4 jne 00000013 - 0000001F: 5E pop esi - 00000020: C3 ret - - 8B5424045633F68D4E013BD177048BC25EC34A8D04318D318BC883EA0175F45EC3 - *) - - let binary = - [| 0x8Buy; 0x54uy; 0x24uy; 0x04uy; 0x56uy; 0x33uy; 0xF6uy; 0x8Duy; 0x4Euy; - 0x01uy; 0x3Buy; 0xD1uy; 0x77uy; 0x04uy; 0x8Buy; 0xC2uy; 0x5Euy; 0xC3uy; - 0x4Auy; 0x8Duy; 0x04uy; 0x31uy; 0x8Duy; 0x31uy; 0x8Buy; 0xC8uy; 0x83uy; - 0xEAuy; 0x01uy; 0x75uy; 0xF4uy; 0x5Euy; 0xC3uy |] - - let isa = ISA.Init Architecture.IntelX86 Endian.Little - let hdl = BinHandler.Init (isa, binary) - let ess = BinEssence.init hdl - let ess = Analyzer.run [ NoReturnAnalysis () ] ess - - [] - member __.``Reaching Definitions Test 1``() = - let cfg, root = ess.GetFunctionCFG (0UL) - let rd = ReachingDefinitions (cfg) - let ins, _outs = rd.Compute cfg root - let v = cfg.FindVertexBy (fun b -> b.VData.PPoint.Address = 0xEUL) (* 2nd *) - let result = ins.[v.GetID ()] |> Set.filter (fun v -> - match v.VarExpr with - | Regular _ -> true - | _ -> false) - let solution = [ - { ProgramPoint = ProgramPoint (0UL, 1) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } - { ProgramPoint = ProgramPoint (4UL, 2) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.ESP) } - { ProgramPoint = ProgramPoint (5UL, 2) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.ESI) } - { ProgramPoint = ProgramPoint (5UL, 3) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.OF) } - { ProgramPoint = ProgramPoint (5UL, 4) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.CF) } - { ProgramPoint = ProgramPoint (5UL, 5) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.SF) } - { ProgramPoint = ProgramPoint (5UL, 6) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.ZF) } - { ProgramPoint = ProgramPoint (5UL, 9) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.PF) } - { ProgramPoint = ProgramPoint (5UL, 10) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.AF) } - { ProgramPoint = ProgramPoint (7UL, 1) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.ECX) } - { ProgramPoint = ProgramPoint (0xAUL, 4) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.CF) } - { ProgramPoint = ProgramPoint (0xAUL, 5) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.OF) } - { ProgramPoint = ProgramPoint (0xAUL, 6) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.AF) } - { ProgramPoint = ProgramPoint (0xAUL, 7) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.SF) } - { ProgramPoint = ProgramPoint (0xAUL, 8) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.ZF) } - { ProgramPoint = ProgramPoint (0xAUL, 11) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.PF) } ] - Assert.AreEqual (result, Set.ofList solution) - - [] - member __.``Use-Def Test 1``() = - let cfg, root = ess.GetFunctionCFG (0UL) - let chain = DataFlowChain.init cfg root false - let vp = - { ProgramPoint = ProgramPoint (0xEUL, 1) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } - let res = chain.UseDefChain |> Map.find vp |> Set.toArray - let solution = [| - { ProgramPoint = ProgramPoint (0x0UL, 1) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } |] - CollectionAssert.AreEqual (solution, res) - - [] - member __.``Use-Def Test 2``() = - let cfg, root = ess.GetFunctionCFG (0UL) - let chain = DataFlowChain.init cfg root true - let vp = - { ProgramPoint = ProgramPoint (0xEUL, 0) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } - let res = chain.UseDefChain |> Map.find vp |> Set.toArray - let solution = [| - { ProgramPoint = ProgramPoint (0x0UL, 0) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } |] - CollectionAssert.AreEqual (solution, res) - - [] - member __.``Use-Def Test 3``() = - let cfg, root = ess.GetFunctionCFG (0UL) - let chain = DataFlowChain.init cfg root false - let vp = - { ProgramPoint = ProgramPoint (0x1AUL, 1) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } - let res = chain.UseDefChain |> Map.find vp |> Set.toArray - let solution = [| - { ProgramPoint = ProgramPoint (0x12UL, 4) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } - { ProgramPoint = ProgramPoint (0x1AUL, 4) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } |] - CollectionAssert.AreEqual (solution, res) diff --git a/src/DataFlow/B2R2.DataFlow.fsproj b/src/DataFlow/B2R2.DataFlow.fsproj deleted file mode 100644 index c22836af..00000000 --- a/src/DataFlow/B2R2.DataFlow.fsproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - netstandard2.1 - - - - - - - - - - - - - - - - - - - - - diff --git a/src/DataFlow/CPState.fs b/src/DataFlow/CPState.fs deleted file mode 100644 index f920fd34..00000000 --- a/src/DataFlow/CPState.fs +++ /dev/null @@ -1,159 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.DataFlow - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinIR.SSA -open B2R2.BinGraph -open B2R2.Lens -open System.Collections.Generic - -/// An ID of an SSA memory instance. -type SSAMemID = int - -type CPState = { - /// BinHandler of the current binary. - BinHandler: BinHandler - /// SSA edges - SSAEdges: SSAEdges.EdgeInfo - /// SSA var values. - RegState : Dictionary - /// SSA mem values. Only store values of constant addresses. - MemState : Dictionary> - /// Executable edges from vid to vid. If there's no element for an edge, that - /// means the edge is not executable. - ExecutableEdges: HashSet - /// Executed edges from vid to vid. - ExecutedEdges: HashSet - /// Default word size of the current analysis. - DefaultWordSize : RegType - /// Worklist for blocks. - FlowWorkList: Queue - /// Worklist for SSA stmt, this queue stores a list of def variables, and we - /// will use SSAEdges to find all related SSA statements. - SSAWorkList: Queue -} - -module CPState = - let private initStackRegister hdl (dict: Dictionary<_, _>) = - match hdl.RegisterBay.StackPointer with - | Some sp -> - let rt = hdl.RegisterBay.RegIDToRegType sp - let str = hdl.RegisterBay.RegIDToString sp - let var = { Kind = RegVar (rt, sp, str); Identifier = 0 } - dict.[var] <- Const (BitVector.ofUInt64 0x80000000UL rt) - dict - | None -> dict - - let private initMemory (dict: Dictionary<_, _>) = - dict.[0] <- Map.empty - dict - - let initState hdl ssaCfg = - { BinHandler = hdl - SSAEdges = SSAEdges.compute ssaCfg - RegState = Dictionary () |> initStackRegister hdl - MemState = Dictionary () |> initMemory - ExecutableEdges = HashSet () - ExecutedEdges = HashSet () - DefaultWordSize = hdl.ISA.WordSize |> WordSize.toRegType - FlowWorkList = Queue () - SSAWorkList = Queue () } - - let markExecutable st src dst = - if st.ExecutableEdges.Add (src, dst) then st.FlowWorkList.Enqueue (src, dst) - else () - - let isExecuted st src dst = - st.ExecutedEdges.Contains (src, dst) - - let tryFindReg st r = - match st.RegState.TryGetValue r with - | true, v -> Some v - | false, _ -> - if r.Identifier = 0 then Some NotAConst - else None - - let findReg st r = - match st.RegState.TryGetValue r with - | true, v -> v - | false, _ -> NotAConst - - let isDefinedMem st m rt addr = - let mid = m.Identifier - let align = RegType.toByteWidth rt |> uint64 - if st.MemState.ContainsKey mid then - if (rt = st.DefaultWordSize) && (addr % align = 0UL) then - Map.containsKey addr st.MemState.[mid] - else false - else false - - let findMem st m rt addr = - let mid = m.Identifier - let align = RegType.toByteWidth rt |> uint64 - if st.MemState.ContainsKey mid then () - else st.MemState.[mid] <- Map.empty - if (rt = st.DefaultWordSize) && (addr % align = 0UL) then - match Map.tryFind addr st.MemState.[mid] with - | Some c -> c - | None -> NotAConst - else NotAConst - - let copyMem st dstid srcid = - if st.MemState.ContainsKey srcid then () - else st.MemState.[srcid] <- Map.empty - st.MemState.[dstid] <- st.MemState.[srcid] - - let storeMem st mDst rt addr c = - let align = RegType.toByteWidth rt |> uint64 - if (rt = st.DefaultWordSize) && (addr % align = 0UL) then - let dstid = mDst.Identifier - match Map.tryFind addr st.MemState.[dstid] with - | Some old when CPValue.goingUp old c || old = c -> () - | _ -> - st.MemState.[dstid] <- Map.add addr c st.MemState.[dstid] - st.SSAWorkList.Enqueue mDst - else () - - let private mergeMemAux st1 st2 = - st1 - |> Map.fold (fun acc v c -> - match Map.tryFind v acc with - | Some c' -> Map.add v (CPValue.meet c c') acc - | None -> Map.add v c acc) st2 - - /// Merge memory mapping and return true if changed. - let mergeMem st dstid srcids = - srcids - |> Array.choose (fun mid -> st.MemState.TryGetValue mid |> Utils.tupleToOpt) - |> function - | [||] -> false - | arr -> - let merged = Array.reduce mergeMemAux arr - if not (st.MemState.ContainsKey dstid) - || st.MemState.[dstid] <> merged - then st.MemState.[dstid] <- merged; true - else false diff --git a/src/DataFlow/CPTransfer.fs b/src/DataFlow/CPTransfer.fs deleted file mode 100644 index 2fa80b00..00000000 --- a/src/DataFlow/CPTransfer.fs +++ /dev/null @@ -1,283 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.DataFlow.CPTransfer - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinIR -open B2R2.BinGraph -open B2R2.Lens -open B2R2.BinIR.SSA - -let private isGetPCThunkCode = function - | 0xc324048bUL | 0xc3241c8bUL | 0xc3240c8bUL | 0xc324148bUL - | 0xc324348bUL | 0xc3243c8bUL | 0xc3242c8bUL -> true - | _ -> false - -/// This is a heuristic to discover __x86.get_pc_thunk- family functions. -/// 1. If a function name symbol exists and its name matches, then we know it is -/// __x86.get_pc_thunk- family -/// 2. But there are some cases we don't have symbols for them. In such cases, -/// we directly compare first 4 bytes of byte code. Because __x86.get_pc_thunk- -/// family only has 4 bytes for its function body and their values are fixed. -let private isGetPCThunk hdl addr = - match hdl.FileInfo.TryFindFunctionSymbolName addr |> Utils.tupleToOpt with - | Some name -> name.StartsWith "__x86.get_pc_thunk" - | None -> BinHandler.ReadUInt (hdl, addr, 4) |> isGetPCThunkCode - -let evalLoad st m rt addr = - match addr with - | Const addr -> BitVector.toUInt64 addr |> CPState.findMem st m rt - | _ -> NotAConst - -let evalUnOp op c = - match op with - | UnOpType.NEG -> CPValue.neg c - | UnOpType.NOT -> CPValue.not c - | _ -> NotAConst - -let evalBinOp op c1 c2 = - match op with - | BinOpType.ADD -> CPValue.add c1 c2 - | BinOpType.SUB -> CPValue.sub c1 c2 - | BinOpType.MUL -> CPValue.mul c1 c2 - | BinOpType.DIV -> CPValue.div c1 c2 - | BinOpType.SDIV -> CPValue.sdiv c1 c2 - | BinOpType.MOD -> CPValue.``mod`` c1 c2 - | BinOpType.SMOD -> CPValue.smod c1 c2 - | BinOpType.SHL -> CPValue.shl c1 c2 - | BinOpType.SHR -> CPValue.shr c1 c2 - | BinOpType.SAR -> CPValue.sar c1 c2 - | BinOpType.AND -> CPValue.``and`` c1 c2 - | BinOpType.OR -> CPValue.``or`` c1 c2 - | BinOpType.XOR -> CPValue.xor c1 c2 - | BinOpType.CONCAT -> CPValue.concat c1 c2 - | _ -> NotAConst - -let evalRelOp op c1 c2 = - match op with - | RelOpType.EQ -> CPValue.eq c1 c2 - | RelOpType.NEQ -> CPValue.neq c1 c2 - | RelOpType.GT -> CPValue.gt c1 c2 - | RelOpType.GE -> CPValue.ge c1 c2 - | RelOpType.SGT -> CPValue.sgt c1 c2 - | RelOpType.SGE -> CPValue.sge c1 c2 - | RelOpType.LT -> CPValue.lt c1 c2 - | RelOpType.LE -> CPValue.le c1 c2 - | RelOpType.SLT -> CPValue.slt c1 c2 - | RelOpType.SLE -> CPValue.sle c1 c2 - | _ -> NotAConst - -let evalCast op rt c = - match op with - | CastKind.SignExt -> CPValue.signExt rt c - | CastKind.ZeroExt -> CPValue.zeroExt rt c - | _ -> NotAConst - -let evalReturn st addr ret v = - match v.Kind with - | RegVar (rt, rid, _) -> - let hdl = st.BinHandler - if hdl.RegisterBay.IsStackPointer rid then - let c = CPState.findReg st v - let wordByte = RegType.toByteWidth rt |> uint64 - let wordSize = Const (BitVector.ofUInt64 wordByte rt) - evalBinOp BinOpType.ADD c wordSize - elif isGetPCThunk hdl addr then - PCThunk (BitVector.ofUInt64 ret rt) - elif CallingConvention.isNonVolatile hdl rid then - CPState.findReg st v - else NotAConst - | _ -> Utils.impossible () - -let rec evalExpr st = function - | Num bv -> Const bv - | Var v -> CPState.findReg st v - | Load (m, rt, addr) -> evalExpr st addr |> evalLoad st m rt - | UnOp (op, _, e) -> evalExpr st e |> evalUnOp op - | BinOp (op, _, e1, e2) -> - let c1 = evalExpr st e1 - let c2 = evalExpr st e2 - evalBinOp op c1 c2 - | RelOp (op, _, e1, e2) -> - let c1 = evalExpr st e1 - let c2 = evalExpr st e2 - evalRelOp op c1 c2 - | Ite (e1, _, e2, e3) -> - let c1 = evalExpr st e1 - let c2 = evalExpr st e2 - let c3 = evalExpr st e3 - CPValue.ite c1 c2 c3 - | Cast (op, rt, e) -> - let c = evalExpr st e - evalCast op rt c - | Extract (e, rt, pos) -> - let c = evalExpr st e - CPValue.extract c rt pos - | Undefined _ -> NotAConst - | ReturnVal (addr, ret, v) -> - evalReturn st addr ret v - | _ -> Utils.impossible () - -let evalMemDef st mDst e = - match e with - | Store (mSrc, rt, addr, v) -> - let c = evalExpr st v - let addr = evalExpr st addr - CPState.copyMem st mDst.Identifier mSrc.Identifier - match addr with - | Const addr -> - let addr = BitVector.toUInt64 addr - CPState.storeMem st mDst rt addr c - | _ -> () - | ReturnVal (_, _, mSrc) -> - CPState.copyMem st mDst.Identifier mSrc.Identifier - let dstMem = - st.MemState.[mDst.Identifier] - |> Map.map (fun _ v -> - match v with - | GOT _ -> v - | _ -> NotAConst) - st.MemState.[mDst.Identifier] <- dstMem - | _ -> Utils.impossible () - -let inline updateConst st r v = - if not (st.RegState.ContainsKey r) then - st.RegState.[r] <- v - st.SSAWorkList.Enqueue r - elif st.RegState.[r] = v then () - elif CPValue.goingUp st.RegState.[r] v then () - else - st.RegState.[r] <- CPValue.meet st.RegState.[r] v - st.SSAWorkList.Enqueue r - -let evalDef st v e = - match v.Kind with - | RegVar _ | TempVar _ -> evalExpr st e |> updateConst st v - | MemVar -> evalMemDef st v e - | PCVar _ -> () - -let executableSources cfg st (blk: Vertex<_>) srcIDs = - srcIDs - |> Array.mapi (fun i srcID -> - let p = DiGraph.getPreds cfg blk |> List.item i - if not <| CPState.isExecuted st (p.GetID ()) (blk.GetID ()) then None - else Some srcID) - |> Array.choose id - -let evalPhi cfg st blk dst srcIDs = - match executableSources cfg st blk srcIDs with - | [||] -> () - | executableSrcIDs -> - match dst.Kind with - | RegVar _ | TempVar _ -> - executableSrcIDs - |> Array.map (fun i -> - { dst with Identifier = i } |> CPState.tryFindReg st) - |> Array.choose id - |> Array.reduce CPValue.meet - |> fun merged -> updateConst st dst merged - | MemVar -> - if CPState.mergeMem st dst.Identifier executableSrcIDs then - st.SSAWorkList.Enqueue dst - else () - | PCVar _ -> () - -let markAllSuccessors cfg st (blk: Vertex) = - let myid = blk.GetID () - DiGraph.getSuccs cfg blk - |> List.iter (fun succ -> - let succid = succ.GetID () - CPState.markExecutable st myid succid) - -let markSuccessorsConditionally cfg st (blk: Vertex) cond = - let myid = blk.GetID () - DiGraph.getSuccs cfg blk - |> List.iter (fun succ -> - if cond succ then - let succid = succ.GetID () - CPState.markExecutable st myid succid - else ()) - -let evalIntraCJmp cfg st blk cond trueLbl falseLbl = - match cond with - | Const bv -> - (fun (succ: Vertex) -> - let target = if BitVector.isTrue bv then trueLbl else falseLbl - match succ.VData.Stmts.[0] with - | LMark lbl -> lbl = target - | _ -> false) - |> markSuccessorsConditionally cfg st blk - | _ -> markAllSuccessors cfg st blk - -let evalInterJmp cfg st blk = function - | Num addr -> - (fun (succ: Vertex) -> - succ.VData.PPoint.Address = BitVector.toUInt64 addr) - |> markSuccessorsConditionally cfg st blk - | _ -> - let insInfos = blk.VData.InsInfos - if insInfos.[Array.length insInfos - 1].Instruction.IsCall () then - (fun (succ: Vertex) -> - succ.VData.PPoint |> ProgramPoint.IsFake) - |> markSuccessorsConditionally cfg st blk - else markAllSuccessors cfg st blk - -let evalInterCJmp cfg st blk cond trueExpr falseExpr = - match cond, trueExpr, falseExpr with - | Const bv, Num trueAddr, Num falseAddr -> - (fun (succ: Vertex) -> - let target = if BitVector.isTrue bv then trueAddr else falseAddr - succ.VData.PPoint.Address = BitVector.toUInt64 target) - |> markSuccessorsConditionally cfg st blk - | Const bv, Var _, Num falseAddr -> - (fun (succ: Vertex) -> - if BitVector.isTrue bv then - succ.VData.PPoint.Address <> BitVector.toUInt64 falseAddr - else succ.VData.PPoint.Address = BitVector.toUInt64 falseAddr) - |> markSuccessorsConditionally cfg st blk - | Const bv, Num trueAddr, Var _ -> - (fun (succ: Vertex) -> - if BitVector.isTrue bv then - succ.VData.PPoint.Address = BitVector.toUInt64 trueAddr - else succ.VData.PPoint.Address <> BitVector.toUInt64 trueAddr) - |> markSuccessorsConditionally cfg st blk - | _ -> markAllSuccessors cfg st blk - -let evalJmp cfg st blk = function - | IntraJmp _ -> markAllSuccessors cfg st blk - | IntraCJmp (cond, trueLbl, falseLbl) -> - let c = evalExpr st cond - evalIntraCJmp cfg st blk c trueLbl falseLbl - | InterJmp expr -> evalInterJmp cfg st blk expr - | InterCJmp (cond, trueExpr, falseExpr) -> - let c = evalExpr st cond - evalInterCJmp cfg st blk c trueExpr falseExpr - -let evalStmt cfg st blk = function - | Def (v, e) -> evalDef st v e - | Phi (v, ns) -> evalPhi cfg st blk v ns - | Jmp jmpTy -> evalJmp cfg st blk jmpTy - | LMark _ | SideEffect _ -> () diff --git a/src/DataFlow/CPValue.fs b/src/DataFlow/CPValue.fs deleted file mode 100644 index dda0ef38..00000000 --- a/src/DataFlow/CPValue.fs +++ /dev/null @@ -1,175 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.DataFlow - -open B2R2 - -type CPValue = - | NotAConst - | Const of BitVector - | PCThunk of BitVector - | GOT of BitVector - | Undef - -module CPValue = - - let meet c1 c2 = - match c1, c2 with - | Undef, c | c, Undef -> c - | PCThunk bv, PCThunk _ -> PCThunk bv - | GOT bv, GOT _ -> GOT bv - | Const bv1, Const bv2 -> if bv1 = bv2 then c1 else NotAConst - | _ -> NotAConst - - let unOp op = function - | Const bv -> Const (op bv) - | PCThunk bv -> Const (op bv) - | GOT bv -> Const (op bv) - | c -> c - - let neg c = unOp BitVector.neg c - - let not c = unOp BitVector.bnot c - - let binOp op c1 c2 = - match c1, c2 with - | Undef, _ | _, Undef -> Undef - | PCThunk bv1, PCThunk bv2 - | PCThunk bv1, GOT bv2 - | PCThunk bv1, Const bv2 - | GOT bv1, GOT bv2 - | GOT bv1, PCThunk bv2 - | GOT bv1, Const bv2 - | Const bv1, PCThunk bv2 - | Const bv1, GOT bv2 - | Const bv1, Const bv2 -> Const (op bv1 bv2) - | _ -> NotAConst - - let add c1 c2 = - match c1, c2 with - | Undef, _ | _, Undef -> Undef - | PCThunk bv1, Const bv2 - | Const bv1, PCThunk bv2 -> GOT (BitVector.add bv1 bv2) - | PCThunk bv1, PCThunk bv2 - | PCThunk bv1, GOT bv2 - | GOT bv1, GOT bv2 - | GOT bv1, PCThunk bv2 - | GOT bv1, Const bv2 - | Const bv1, GOT bv2 - | Const bv1, Const bv2 -> Const (BitVector.add bv1 bv2) - | _ -> NotAConst - - let sub c1 c2 = binOp BitVector.sub c1 c2 - - let mul c1 c2 = binOp BitVector.mul c1 c2 - - let divAux divop c1 c2 = - match c1, c2 with - | Undef, _ | _, Undef -> Undef - | PCThunk bv1, PCThunk bv2 - | PCThunk bv1, GOT bv2 - | PCThunk bv1, Const bv2 - | GOT bv1, GOT bv2 - | GOT bv1, PCThunk bv2 - | GOT bv1, Const bv2 - | Const bv1, PCThunk bv2 - | Const bv1, GOT bv2 - | Const bv1, Const bv2 -> - if BitVector.isZero bv2 then NotAConst - else Const (divop bv1 bv2) - | _ -> NotAConst - - let div c1 c2 = divAux BitVector.div c1 c2 - - let sdiv c1 c2 = divAux BitVector.sdiv c1 c2 - - let ``mod`` c1 c2 = binOp BitVector.modulo c1 c2 - - let smod c1 c2 = binOp BitVector.smodulo c1 c2 - - let shl c1 c2 = binOp BitVector.shl c1 c2 - - let shr c1 c2 = binOp BitVector.shr c1 c2 - - let sar c1 c2 = binOp BitVector.sar c1 c2 - - let ``and`` c1 c2 = binOp BitVector.band c1 c2 - - let ``or`` c1 c2 = binOp BitVector.bor c1 c2 - - let xor c1 c2 = binOp BitVector.bxor c1 c2 - - let concat c1 c2 = binOp BitVector.concat c1 c2 - - let relOp op c1 c2 = binOp op c1 c2 - - let eq c1 c2 = relOp BitVector.eq c1 c2 - - let neq c1 c2 = relOp BitVector.neq c1 c2 - - let gt c1 c2 = relOp BitVector.gt c1 c2 - - let ge c1 c2 = relOp BitVector.ge c1 c2 - - let sgt c1 c2 = relOp BitVector.sgt c1 c2 - - let sge c1 c2 = relOp BitVector.sge c1 c2 - - let lt c1 c2 = relOp BitVector.lt c1 c2 - - let le c1 c2 = relOp BitVector.le c1 c2 - - let slt c1 c2 = relOp BitVector.slt c1 c2 - - let sle c1 c2 = relOp BitVector.sle c1 c2 - - let ite cond c1 c2 = - match cond with - | Undef -> Undef - | PCThunk bv - | GOT bv - | Const bv -> if BitVector.isZero bv then c2 else c1 - | NotAConst -> meet c1 c2 - - let cast op rt c = - unOp (fun bv -> op bv rt) c - - let signExt rt c = cast BitVector.sext rt c - - let zeroExt rt c = cast BitVector.zext rt c - - let extract c rt pos = - unOp (fun bv -> BitVector.extract bv rt pos) c - - let goingUp a b = - match a, b with - | Const _, Undef - | PCThunk _, Undef - | GOT _, Undef - | NotAConst, Undef - | NotAConst, Const _ - | NotAConst, PCThunk _ - | NotAConst, GOT _ -> true - | _ -> false diff --git a/src/DataFlow/Chains.fs b/src/DataFlow/Chains.fs deleted file mode 100644 index f7bedc50..00000000 --- a/src/DataFlow/Chains.fs +++ /dev/null @@ -1,117 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.DataFlow - -open B2R2 -open B2R2.BinGraph -open B2R2.BinEssence - -type DataFlowChain = { - UseDefChain: Map> - DefUseChain: Map> -} - -module DataFlowChain = - let private computeInBlockDefs pp (u: VarExpr) (outset: Set) = - outset - |> Seq.filter (fun vp -> - vp.VarExpr = u - && vp.ProgramPoint < (pp: ProgramPoint)) - |> Seq.sortBy (fun vp -> vp.ProgramPoint) - |> Seq.tryLast (* Picking the def that has the largest position idx *) - - /// When there are more than one defs for the same variable, we should choose - /// the last one. - let private filterLastDefInBlock defs = - defs - |> Set.fold (fun map d -> - let addr = d.ProgramPoint.Address - match Map.tryFind addr map with - | None -> Map.add addr d map - | Some old -> - if old.ProgramPoint.Position > d.ProgramPoint.Position then map - else Map.add addr d map) Map.empty - |> Map.toList - |> List.map snd - - let private computeOutBlockDefs (u: VarExpr) (inset: Set) = - inset - |> Set.filter (fun d -> d.VarExpr = u) - |> filterLastDefInBlock - - let private initUDChain cfg (ins: RDMap) (outs: RDMap) = - Map.empty - |> DiGraph.foldVertex cfg (fun map (v: Vertex) -> - v.VData.GetInsInfos () - |> Array.fold (fun map info -> - info.Stmts - |> Array.foldi (fun map idx stmt -> - let pp = ProgramPoint (info.Instruction.Address, idx) - let inset = ins.[v.GetID ()] - let outset = outs.[v.GetID ()] - let uses = Utils.extractUses stmt - uses |> Set.fold (fun map u -> - let usepoint = { VarExpr = u; ProgramPoint = pp } - let set = computeOutBlockDefs u inset |> Set.ofList - let set = - match computeInBlockDefs pp u outset with - | Some def -> Set.add def set - | None -> set - Map.add usepoint set map - ) map - ) map |> fst - ) map) - - let private initDUChain udchain = - udchain - |> Map.fold (fun map u ds -> - ds - |> Set.fold (fun map d -> - match Map.tryFind d map with - | None -> Map.add d (Set.singleton u) map - | Some us -> Map.add d (Set.add u us) map) map) Map.empty - - let private normalizeVP (vp: VarPoint) = - let addr = vp.ProgramPoint.Address - { vp with ProgramPoint = ProgramPoint (addr, 0) } - - let private filterDisasm isDisasmLevel chain = - if not isDisasmLevel then chain - else - chain - |> Map.fold (fun map vp set -> - let vp = normalizeVP vp - let newSet = set |> Set.map normalizeVP - match Map.tryFind vp map with - | None -> Map.add vp newSet map - | Some old -> Map.add vp (Set.union old newSet) map) Map.empty - - [] - let init cfg root isDisasmLevel = - let rd = ReachingDefinitions (cfg) - let ins, outs = rd.Compute cfg root - let udchain = initUDChain cfg ins outs |> filterDisasm isDisasmLevel - let duchain = initDUChain udchain |> filterDisasm isDisasmLevel - { UseDefChain = udchain; DefUseChain = duchain } diff --git a/src/DataFlow/ConstantPropagation.fs b/src/DataFlow/ConstantPropagation.fs deleted file mode 100644 index a987613f..00000000 --- a/src/DataFlow/ConstantPropagation.fs +++ /dev/null @@ -1,80 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.DataFlow - -open B2R2.BinIR.SSA -open B2R2.BinGraph -open B2R2.BinEssence -open B2R2.Lens - -/// Modified version of sparse conditional constant propagation of Wegman et al. -type ConstantPropagation (hdl, ssaCFG: DiGraph) = - inherit DataFlowAnalysis () - - override __.Top = Undef - - member private __.GetNumIncomingExecutedEdges st (blk: Vertex) = - let myid = blk.GetID () - DiGraph.getPreds ssaCFG blk - |> List.map (fun p -> p.GetID (), myid) - |> List.filter (fun (src, dst) -> CPState.isExecuted st src dst) - |> List.length - - member private __.ProcessSSA st = - while st.SSAWorkList.Count > 0 do - let def = st.SSAWorkList.Dequeue () - match Map.tryFind def st.SSAEdges.Uses with - | Some uses -> - uses - |> Set.iter (fun (vid, idx) -> - let v = DiGraph.findVertexByID ssaCFG vid - if __.GetNumIncomingExecutedEdges st v > 0 then - CPTransfer.evalStmt ssaCFG st v v.VData.Stmts.[idx] - else ()) - | None -> () - - member private __.ProcessFlow st = - if st.FlowWorkList.Count > 0 then - let parentid, myid = st.FlowWorkList.Dequeue () - st.ExecutedEdges.Add (parentid, myid) |> ignore - let blk = DiGraph.findVertexByID ssaCFG myid - blk.VData.Stmts - |> Array.iter (fun stmt -> CPTransfer.evalStmt ssaCFG st blk stmt) - match blk.VData.GetLastStmt () with - | Jmp _ -> () - | _ -> - DiGraph.getSuccs ssaCFG blk - |> List.iter (fun succ -> - let succid = succ.GetID () - CPState.markExecutable st myid succid) - else () - - member __.Compute (root: Vertex<_>) = - let st = CPState.initState hdl ssaCFG - st.FlowWorkList.Enqueue (0, root.GetID ()) - while st.FlowWorkList.Count > 0 || st.SSAWorkList.Count > 0 do - __.ProcessFlow st - __.ProcessSSA st - st diff --git a/src/DataFlow/DataFlowAnalysis.fs b/src/DataFlow/DataFlowAnalysis.fs deleted file mode 100644 index b8a16fba..00000000 --- a/src/DataFlow/DataFlowAnalysis.fs +++ /dev/null @@ -1,123 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.DataFlow - -open B2R2 -open B2R2.BinGraph -open System.Collections.Generic - -/// Defined variable. -type VarExpr = - | Regular of RegisterID - | Temporary of int - | Memory of Addr - -/// Program point of a defined variable. -type VarPoint = { - ProgramPoint: ProgramPoint - VarExpr: VarExpr -} - -/// Either forward or backward analysis. -type DataFlowDirection = - | Forward - | Backward - -/// Data-flow analysis framework. 'L is a lattice, 'V is a vertex data type of a -/// graph. -[] -type DataFlowAnalysis<'L, 'V when 'L: equality - and 'V :> VertexData> () = - /// The top of the lattice. A data-flow analysis solution is computed by - /// iterating down from top to bottom. - abstract Top: 'L - -/// Classic data-flow analysis with topological worklist algorithm. -[] -type TopologicalDataFlowAnalysis<'L, 'V - when 'L: equality - and 'V :> VertexData and 'V : equality> (direction) = - inherit DataFlowAnalysis<'L, 'V> () - - /// Exit lattice per vertex. - let outs = Dictionary () - - /// Entry lattice per vertex. - let ins = Dictionary () - - /// Neighboring vertices to compute dataflow. This is dependent on the - /// direction of the analysis. - let neighbor g = - match direction with - | Forward -> fun (v: Vertex<'V>) -> DiGraph.getPreds g v - | Backward -> fun (v: Vertex<'V>) -> DiGraph.getSuccs g v - - /// Expand the worklist depending on the direction of the analysis. - let addToWorklist g = - match direction with - | Forward -> - fun (worklist: Queue>) (v: Vertex<'V>) -> - DiGraph.getSuccs g v |> List.iter worklist.Enqueue - | Backward -> - fun (worklist: Queue>) (v: Vertex<'V>) -> - DiGraph.getPreds g v |> List.iter worklist.Enqueue - - /// Initialize worklist queue. This should be a topologically sorted list to - /// be efficient. - let initWorklist g (root: Vertex<'V>) = - let q = Queue> () - Traversal.iterRevPostorder g root q.Enqueue - q - - /// Meet operation of the lattice. - abstract Meet: 'L -> 'L -> 'L - - /// The transfer function from an input lattice to an output lattice. The - /// second parameter is to specify the current block of interest. - abstract Transfer: 'L -> Vertex<'V> -> 'L - - /// Initialize ints and outs. - member private __.InitInsOuts g (root: Vertex<'V>) = - Traversal.iterPreorder g root (fun v -> - let blkid = v.GetID () - outs.[blkid] <- __.Top - ins.[blkid] <- __.Top) - - /// Compute data-flow with the iterative worklist algorithm. - member __.Compute g (root: Vertex<'V>) = - __.InitInsOuts g root - let worklist = initWorklist g root - while worklist.Count <> 0 do - let blk = worklist.Dequeue () - let blkid = blk.GetID () - ins.[blkid] <- - neighbor g blk - |> List.fold (fun eff v -> __.Meet eff outs.[v.GetID()]) __.Top - let outeffect = __.Transfer ins.[blkid] blk - if outs.[blkid] <> outeffect then - outs.[blkid] <- outeffect - addToWorklist g worklist blk - else () - ins, outs diff --git a/src/DataFlow/ReachingDefinitions.fs b/src/DataFlow/ReachingDefinitions.fs deleted file mode 100644 index 52b0af78..00000000 --- a/src/DataFlow/ReachingDefinitions.fs +++ /dev/null @@ -1,86 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.DataFlow - -open B2R2 -open B2R2.BinIR.LowUIR -open B2R2.BinGraph -open B2R2.BinEssence -open System.Collections.Generic - -type RDMap = Dictionary> - -type ReachingDefinitions (cfg: DiGraph) as this = - inherit TopologicalDataFlowAnalysis, IRBasicBlock> (Forward) - - let gens = RDMap () - let kills = RDMap () - - do this.Initialize () - - member private __.FindDefs (v: Vertex) = - v.VData.GetInsInfos () - |> Array.fold (fun list info -> - info.Stmts - |> Array.foldi (fun list idx stmt -> - match stmt with - | Put (TempVar (_, n), _) -> - let pp = ProgramPoint (info.Instruction.Address, idx) - { ProgramPoint = pp; VarExpr = Temporary n } :: list - | Put (Var (_, id, _, _), _) -> - let pp = ProgramPoint (info.Instruction.Address, idx) - { ProgramPoint = pp; VarExpr = Regular id } :: list - | _ -> list) list - |> fst) [] - - member private __.Initialize () = - let vpPerVar = Dictionary> () - let vpPerVertex = Dictionary () - DiGraph.iterVertex cfg (fun v -> - let vid = v.GetID () - let defs = __.FindDefs v - gens.[vid] <- defs |> Set.ofList - vpPerVertex.[vid] <- defs - defs |> List.iter (fun ({ VarExpr = v } as vp) -> - if vpPerVar.ContainsKey v then vpPerVar.[v] <- Set.add vp vpPerVar.[v] - else vpPerVar.[v] <- Set.singleton vp - ) - ) - DiGraph.iterVertex cfg (fun v -> - let vid = v.GetID () - let vars = vpPerVertex.[vid] |> List.map (fun vp -> vp.VarExpr) - let vps = vpPerVertex.[vid] |> Set.ofList - let alldefs = - vars |> List.fold (fun set v -> Set.union set vpPerVar.[v]) Set.empty - kills.[vid] <- Set.difference alldefs vps - ) - - override __.Meet a b = Set.union a b - - override __.Top = Set.empty - - override __.Transfer i v = - let vid = v.GetID () - Set.union gens.[vid] (Set.difference i kills.[vid]) diff --git a/src/FrontEnd.Tests/B2R2.FrontEnd.Tests.fsproj b/src/FrontEnd.Tests/B2R2.FrontEnd.Tests.fsproj deleted file mode 100644 index a7ae5988..00000000 --- a/src/FrontEnd.Tests/B2R2.FrontEnd.Tests.fsproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - netcoreapp3.0 - false - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/FrontEnd/ARM64/B2R2.FrontEnd.ARM64.fsproj b/src/FrontEnd/ARM64/B2R2.FrontEnd.ARM64.fsproj deleted file mode 100644 index 1ce7a157..00000000 --- a/src/FrontEnd/ARM64/B2R2.FrontEnd.ARM64.fsproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - netstandard2.1 - false - false - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/FrontEnd/BinFile.Tests/B2R2.FrontEnd.BinFile.Tests.fsproj b/src/FrontEnd/BinFile.Tests/B2R2.FrontEnd.BinFile.Tests.fsproj new file mode 100644 index 00000000..4064178e --- /dev/null +++ b/src/FrontEnd/BinFile.Tests/B2R2.FrontEnd.BinFile.Tests.fsproj @@ -0,0 +1,22 @@ + + + + net5.0 + false + + + + + + + + + + + + + + + + + diff --git a/src/BinFile.Tests/BinFile.Tests.fs b/src/FrontEnd/BinFile.Tests/BinFile.Tests.fs similarity index 97% rename from src/BinFile.Tests/BinFile.Tests.fs rename to src/FrontEnd/BinFile.Tests/BinFile.Tests.fs index 25851659..8e8074d5 100644 --- a/src/BinFile.Tests/BinFile.Tests.fs +++ b/src/FrontEnd/BinFile.Tests/BinFile.Tests.fs @@ -25,7 +25,7 @@ namespace B2R2.BinFile.Tests open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile open Microsoft.VisualStudio.TestTools.UnitTesting open System.IO open System.IO.Compression @@ -70,9 +70,9 @@ module PE = new PEFileInfo (bytes, file, pdbBytes) let checkSymbol (fileInfo : PEFileInfo) addr symName = - let found, n = fileInfo.TryFindFunctionSymbolName addr - Assert.IsTrue (found) - Assert.AreEqual(n, symName) + match fileInfo.TryFindFunctionSymbolName addr with + | Ok n -> Assert.AreEqual (n, symName) + | Error _ -> Assert.Fail () [] type TestClass () = @@ -117,9 +117,9 @@ module Mach = new MachFileInfo (bytes, fileName, isa) let checkSymbol (fileInfo : MachFileInfo) addr symName = - let found, n = fileInfo.TryFindFunctionSymbolName addr - Assert.IsTrue (found) - Assert.AreEqual(symName, n) + match fileInfo.TryFindFunctionSymbolName addr with + | Ok n -> Assert.AreEqual (n, symName) + | Error _ -> Assert.Fail () [] type TestClass () = @@ -194,9 +194,9 @@ module ELF = new ELFFileInfo (bytes, fileName) let checkSymbol (fileInfo : ELFFileInfo) addr symName = - let found, n = fileInfo.TryFindFunctionSymbolName addr - Assert.IsTrue (found) - Assert.AreEqual(n, symName) + match fileInfo.TryFindFunctionSymbolName addr with + | Ok n -> Assert.AreEqual (n, symName) + | Error _ -> Assert.Fail () [] type TestClass () = @@ -211,7 +211,7 @@ module ELF = Assert.AreEqual (fi.GetSections () |> Seq.length, 31) Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 793) Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 131) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 113) + Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 114) Assert.AreEqual (fi.TextStartAddr, 0x8049CD0UL) Assert.AreEqual (fi.WordSize, WordSize.Bit32) checkSymbol fi 0x080495b0UL "unsetenv" @@ -227,7 +227,7 @@ module ELF = Assert.AreEqual (fi.GetSections () |> Seq.length, 29) Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 0) Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 131) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 113) + Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 114) Assert.AreEqual (fi.TextStartAddr, 0x8049CD0UL) Assert.AreEqual (fi.WordSize, WordSize.Bit32) checkSymbol fi 0x080495b0UL "unsetenv" @@ -243,7 +243,7 @@ module ELF = Assert.AreEqual (fi.GetSections () |> Seq.length, 38) Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 635) Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 126) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 109) + Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 110) Assert.AreEqual (fi.TextStartAddr, 0x4027C0UL) Assert.AreEqual (fi.WordSize, WordSize.Bit64) checkSymbol fi 0x004020e0UL "__ctype_toupper_loc" @@ -259,7 +259,7 @@ module ELF = Assert.AreEqual (fi.GetSections () |> Seq.length, 29) Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 0) Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 126) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 109) + Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 110) Assert.AreEqual (fi.TextStartAddr, 0x4027C0UL) Assert.AreEqual (fi.WordSize, WordSize.Bit64) checkSymbol fi 0x004020e0UL "__ctype_toupper_loc" diff --git a/src/BinFile.Tests/ELF/README.md b/src/FrontEnd/BinFile.Tests/ELF/README.md similarity index 100% rename from src/BinFile.Tests/ELF/README.md rename to src/FrontEnd/BinFile.Tests/ELF/README.md diff --git a/src/BinFile.Tests/ELF/elf_aarch64_ls.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_aarch64_ls.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_aarch64_ls.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_aarch64_ls.zip diff --git a/src/BinFile.Tests/ELF/elf_aarch64_ls_stripped.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_aarch64_ls_stripped.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_aarch64_ls_stripped.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_aarch64_ls_stripped.zip diff --git a/src/BinFile.Tests/ELF/elf_arm32_ls.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_arm32_ls.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_arm32_ls.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_arm32_ls.zip diff --git a/src/BinFile.Tests/ELF/elf_arm32_ls_stripped.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_arm32_ls_stripped.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_arm32_ls_stripped.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_arm32_ls_stripped.zip diff --git a/src/BinFile.Tests/ELF/elf_mips32_ls_stripped.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_mips32_ls_stripped.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_mips32_ls_stripped.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_mips32_ls_stripped.zip diff --git a/src/BinFile.Tests/ELF/elf_mips32_ls_stripped_le.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_mips32_ls_stripped_le.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_mips32_ls_stripped_le.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_mips32_ls_stripped_le.zip diff --git a/src/BinFile.Tests/ELF/elf_mips64_ls_stripped.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_mips64_ls_stripped.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_mips64_ls_stripped.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_mips64_ls_stripped.zip diff --git a/src/BinFile.Tests/ELF/elf_thumb_ls.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_thumb_ls.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_thumb_ls.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_thumb_ls.zip diff --git a/src/BinFile.Tests/ELF/elf_thumb_ls_stripped.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_thumb_ls_stripped.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_thumb_ls_stripped.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_thumb_ls_stripped.zip diff --git a/src/BinFile.Tests/ELF/elf_x64_ls.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_x64_ls.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_x64_ls.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_x64_ls.zip diff --git a/src/BinFile.Tests/ELF/elf_x64_ls_stripped.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_x64_ls_stripped.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_x64_ls_stripped.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_x64_ls_stripped.zip diff --git a/src/BinFile.Tests/ELF/elf_x86_ls.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_x86_ls.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_x86_ls.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_x86_ls.zip diff --git a/src/BinFile.Tests/ELF/elf_x86_ls_stripped.zip b/src/FrontEnd/BinFile.Tests/ELF/elf_x86_ls_stripped.zip similarity index 100% rename from src/BinFile.Tests/ELF/elf_x86_ls_stripped.zip rename to src/FrontEnd/BinFile.Tests/ELF/elf_x86_ls_stripped.zip diff --git a/src/BinFile.Tests/Mach/README.md b/src/FrontEnd/BinFile.Tests/Mach/README.md similarity index 100% rename from src/BinFile.Tests/Mach/README.md rename to src/FrontEnd/BinFile.Tests/Mach/README.md diff --git a/src/BinFile.Tests/Mach/mach_x64_wc.zip b/src/FrontEnd/BinFile.Tests/Mach/mach_x64_wc.zip similarity index 100% rename from src/BinFile.Tests/Mach/mach_x64_wc.zip rename to src/FrontEnd/BinFile.Tests/Mach/mach_x64_wc.zip diff --git a/src/BinFile.Tests/Mach/mach_x64_wc_stripped.zip b/src/FrontEnd/BinFile.Tests/Mach/mach_x64_wc_stripped.zip similarity index 100% rename from src/BinFile.Tests/Mach/mach_x64_wc_stripped.zip rename to src/FrontEnd/BinFile.Tests/Mach/mach_x64_wc_stripped.zip diff --git a/src/BinFile.Tests/Mach/mach_x86_rm_stripped.zip b/src/FrontEnd/BinFile.Tests/Mach/mach_x86_rm_stripped.zip similarity index 100% rename from src/BinFile.Tests/Mach/mach_x86_rm_stripped.zip rename to src/FrontEnd/BinFile.Tests/Mach/mach_x86_rm_stripped.zip diff --git a/src/BinFile.Tests/PE/README.md b/src/FrontEnd/BinFile.Tests/PE/README.md similarity index 100% rename from src/BinFile.Tests/PE/README.md rename to src/FrontEnd/BinFile.Tests/PE/README.md diff --git a/src/BinFile.Tests/PE/pe_x64.zip b/src/FrontEnd/BinFile.Tests/PE/pe_x64.zip similarity index 100% rename from src/BinFile.Tests/PE/pe_x64.zip rename to src/FrontEnd/BinFile.Tests/PE/pe_x64.zip diff --git a/src/BinFile.Tests/PE/pe_x64_without_pdb.zip b/src/FrontEnd/BinFile.Tests/PE/pe_x64_without_pdb.zip similarity index 100% rename from src/BinFile.Tests/PE/pe_x64_without_pdb.zip rename to src/FrontEnd/BinFile.Tests/PE/pe_x64_without_pdb.zip diff --git a/src/BinFile.Tests/PE/pe_x86.zip b/src/FrontEnd/BinFile.Tests/PE/pe_x86.zip similarity index 100% rename from src/BinFile.Tests/PE/pe_x86.zip rename to src/FrontEnd/BinFile.Tests/PE/pe_x86.zip diff --git a/src/BinFile.Tests/PE/pe_x86_without_pdb.zip b/src/FrontEnd/BinFile.Tests/PE/pe_x86_without_pdb.zip similarity index 100% rename from src/BinFile.Tests/PE/pe_x86_without_pdb.zip rename to src/FrontEnd/BinFile.Tests/PE/pe_x86_without_pdb.zip diff --git a/src/BinFile.Tests/Wasm/wasm_basic.zip b/src/FrontEnd/BinFile.Tests/Wasm/wasm_basic.zip similarity index 100% rename from src/BinFile.Tests/Wasm/wasm_basic.zip rename to src/FrontEnd/BinFile.Tests/Wasm/wasm_basic.zip diff --git a/src/BinFile/B2R2.BinFile.fsproj b/src/FrontEnd/BinFile/B2R2.FrontEnd.BinFile.fsproj similarity index 60% rename from src/BinFile/B2R2.BinFile.fsproj rename to src/FrontEnd/BinFile/B2R2.FrontEnd.BinFile.fsproj index 809aece2..a193ded8 100644 --- a/src/BinFile/B2R2.BinFile.fsproj +++ b/src/FrontEnd/BinFile/B2R2.FrontEnd.BinFile.fsproj @@ -1,12 +1,15 @@ - + - netstandard2.1 + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 file parsing engine. - - - + + @@ -20,11 +23,13 @@ + + @@ -46,8 +51,21 @@ + + + + + + + + + + + + + - + diff --git a/src/FrontEnd/BinFile/BinaryPointer.fs b/src/FrontEnd/BinFile/BinaryPointer.fs new file mode 100644 index 00000000..946687cb --- /dev/null +++ b/src/FrontEnd/BinFile/BinaryPointer.fs @@ -0,0 +1,73 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open B2R2 +open System + +/// A pointer to binary, which is used to exclusively point to a portion of a +/// binary, e.g., a section. It holds both the virtual address as well as the +/// file offset. +type BinaryPointer = + struct + /// Virtual address. + val Addr: Addr + /// File offset. + val Offset: int + /// Max offset that this pointer can point to. + val MaxOffset: int + + /// Initializer + new (addr, offset, max) = { Addr = addr; Offset = offset; MaxOffset = max } + end +with + static member Null = BinaryPointer (0UL, 0, 0) + + static member inline IsValid (bp: BinaryPointer) = + bp.Offset < bp.MaxOffset + + static member inline IsValidAccess (bp: BinaryPointer) size = + (bp.Offset + size) <= bp.MaxOffset + + static member OfSection (s: Section) = + BinaryPointer (s.Address, + Convert.ToInt32 s.FileOffset, + Convert.ToInt32 s.FileOffset + Convert.ToInt32 s.Size) + + static member OfSectionOpt section = + match section with + | Some s -> BinaryPointer.OfSection s + | None -> BinaryPointer.Null + + static member IsNull bp = + bp = BinaryPointer.Null + + static member Advance (bp: BinaryPointer) amount = + BinaryPointer (bp.Addr + uint64 amount, bp.Offset + amount, bp.MaxOffset) + + override __.ToString () = + String.u64ToHexNoPrefix __.Addr + + " (" + String.i32ToHexNoPrefix __.Offset + + " of " + String.i32ToHexNoPrefix __.MaxOffset + ")" diff --git a/src/BinFile/ELF.fs b/src/FrontEnd/BinFile/ELF.fs similarity index 73% rename from src/BinFile/ELF.fs rename to src/FrontEnd/BinFile/ELF.fs index 458bb1c0..f000269f 100644 --- a/src/BinFile/ELF.fs +++ b/src/FrontEnd/BinFile/ELF.fs @@ -22,33 +22,34 @@ SOFTWARE. *) -namespace B2R2.BinFile +namespace B2R2.FrontEnd.BinFile open B2R2 -open B2R2.BinFile.ELF -open B2R2.BinFile.ELF.Helper +open B2R2.FrontEnd.BinFile.ELF +open B2R2.FrontEnd.BinFile.ELF.Helper /// /// This class represents an ELF binary file. /// -type ELFFileInfo (bytes, path, baseAddr) = - inherit FileInfo (baseAddr) - let elf = Parser.parse baseAddr bytes +type ELFFileInfo (bytes, path, baseAddr, regbay) = + inherit FileInfo () + let elf = Parser.parse bytes baseAddr regbay - new (bytes, path) = ELFFileInfo (bytes, path, 0UL) + new (bytes, path) = ELFFileInfo (bytes, path, None, None) override __.BinReader = elf.BinReader override __.FileFormat = FileFormat.ELFBinary - override __.ISA = ISA.Init elf.ELFHdr.MachineType elf.ELFHdr.Endian + override __.ISA = elf.ISA override __.FileType = convFileType elf.ELFHdr.ELFFileType override __.FilePath = path override __.WordSize = elf.ELFHdr.Class override __.IsStripped = not (Map.containsKey ".symtab" elf.SecInfo.SecByName) override __.IsNXEnabled = isNXEnabled elf override __.IsRelocatable = isRelocatable elf - override __.BaseAddress = getBaseAddr elf + override __.BaseAddress = elf.BaseAddr override __.EntryPoint = Some elf.ELFHdr.EntryPoint override __.TextStartAddr = getTextStartAddr elf override __.TranslateAddress addr = translateAddr addr elf + override __.AddSymbol addr symbol = Utils.futureFeature () override __.GetSymbols () = getSymbols elf override __.GetStaticSymbols () = getStaticSymbols elf override __.GetDynamicSymbols (?exc) = getDynamicSymbols exc elf @@ -59,8 +60,13 @@ type ELFFileInfo (bytes, path, baseAddr) = override __.GetTextSections () = getTextSections elf override __.GetSegments (isLoadable) = getSegments elf isLoadable override __.GetLinkageTableEntries () = getPLT elf - override __.IsLinkageTable addr = isPLT elf addr - override __.TryFindFunctionSymbolName (addr, n) = tryFindFuncSymb elf addr &n + override __.IsLinkageTable addr = isInPLT elf addr + override __.TryFindFunctionSymbolName (addr) = tryFindFuncSymb elf addr + override __.ExceptionTable = elf.ExceptionTable + override __.ToBinaryPointer addr = + BinaryPointer.OfSectionOpt (getSectionsByAddr elf addr |> Seq.tryHead) + override __.ToBinaryPointer name = + BinaryPointer.OfSectionOpt (getSectionsByName elf name |> Seq.tryHead) override __.IsValidAddr addr = isValidAddr elf addr override __.IsValidRange range = isValidRange elf range override __.IsInFileAddr addr = isInFileAddr elf addr @@ -68,7 +74,10 @@ type ELFFileInfo (bytes, path, baseAddr) = override __.IsExecutableAddr addr = isExecutableAddr elf addr override __.GetNotInFileIntervals range = getNotInFileIntervals elf range override __.GetFunctionAddresses () = - base.GetFunctionAddresses () |> getFunctionAddrs elf + base.GetFunctionAddresses () |> addExtraFunctionAddrs elf false + override __.GetFunctionAddresses (useExcInfo) = + base.GetFunctionAddresses () |> addExtraFunctionAddrs elf useExcInfo member __.ELF with get() = elf + member __.RegisterBay = regbay // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinFile/ELFDwarfTypes.fs b/src/FrontEnd/BinFile/ELFDwarfTypes.fs new file mode 100644 index 00000000..865ca66c --- /dev/null +++ b/src/FrontEnd/BinFile/ELFDwarfTypes.fs @@ -0,0 +1,514 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.ELF + +open LanguagePrimitives +open B2R2 +open B2R2.BinIR +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinFile + +/// Raised when an unhandled encoding is encountered. +exception UnhandledEncoding + +type ExceptionHeaderValue = + /// No value is present. + | DW_EH_PE_omit = 0xff + /// A literal pointer whose size is determined by the architecture. + | DW_EH_PE_absptr = 0x00 + /// Unsigned value is encoded using the LEB128. + | DW_EH_PE_uleb128 = 0x01 + /// A 2-byte unsigned value. + | DW_EH_PE_udata2 = 0x02 + /// A 4-byte unsigned value. + | DW_EH_PE_udata4 = 0x03 + /// A 8-byte unsigned value. + | DW_EH_PE_udata8 = 0x04 + /// A signed value whose size is determined by the architecture. + | DW_EH_PE_signed = 0x08 + /// Signed value is encoded using the LEB128. + | DW_EH_PE_sleb128 = 0x09 + /// A 2-byte signed value. + | DW_EH_PE_sdata2 = 0x0a + /// A 4-byte signed value. + | DW_EH_PE_sdata4 = 0x0b + /// A 8-byte signed value. + | DW_EH_PE_sdata8 = 0x0c + +type ExceptionHeaderApplication = + /// Value is used with no modification. + | DW_EH_PE_absptr = 0x00 + /// Value is relative to the current program counter. + | DW_EH_PE_pcrel = 0x10 + /// Value is relative to the beginning of the .eh_frame_hdr section. + | DW_EH_PE_datarel = 0x30 + /// No value is present. + | DW_EH_PE_omit = 0xff + +module ExceptionHeaderEncoding = + let parseULEB128 (reader: BinReader) offset = + let span = reader.PeekSpan (offset) + let v, cnt = LEB128.DecodeUInt64 span + v, offset + cnt + + let parseSLEB128 (reader: BinReader) offset = + let span = reader.PeekSpan (offset) + let v, cnt = LEB128.DecodeSInt64 span + v, offset + cnt + + let computeValue cls (reader: BinReader) venc offset = + match venc with + | ExceptionHeaderValue.DW_EH_PE_absptr -> + FileHelper.readUIntOfType reader cls offset + | ExceptionHeaderValue.DW_EH_PE_uleb128 -> + let cv, offset = parseULEB128 reader offset + struct (cv, offset) + | ExceptionHeaderValue.DW_EH_PE_sleb128 -> + let cv, offset = parseSLEB128 reader offset + struct (uint64 cv, offset) + | ExceptionHeaderValue.DW_EH_PE_udata2 -> + let struct (cv, offset) = reader.ReadUInt16 offset + struct (uint64 cv, offset) + | ExceptionHeaderValue.DW_EH_PE_sdata2 -> + let struct (cv, offset) = reader.ReadInt16 offset + struct (uint64 cv, offset) + | ExceptionHeaderValue.DW_EH_PE_udata4 -> + let struct (cv, offset) = reader.ReadUInt32 offset + struct (uint64 cv, offset) + | ExceptionHeaderValue.DW_EH_PE_sdata4 -> + let struct (cv, offset) = reader.ReadInt32 offset + struct (uint64 cv, offset) + | ExceptionHeaderValue.DW_EH_PE_udata8 -> + reader.ReadUInt64 offset + | ExceptionHeaderValue.DW_EH_PE_sdata8 -> + let struct (cv, offset) = reader.ReadInt64 offset + struct (uint64 cv, offset) + | _ -> printfn "%A" venc; raise UnhandledEncoding + + let parseEncoding b = + if b &&& 0xFFuy = 255uy then + let v = EnumOfValue 0xff + let app = EnumOfValue 0xff + struct (v, app) + else + let v = int (b &&& 0x0Fuy) + |> EnumOfValue + let app = int (b &&& 0xF0uy) + |> EnumOfValue + struct (v, app) + +/// Dwarf instructions used for unwinding stack. +type DWCFAInstruction = + | DW_CFA_set_loc = 0x01uy + | DW_CFA_advance_loc = 0x40uy + | DW_CFA_advance_loc1 = 0x02uy + | DW_CFA_advance_loc2 = 0x03uy + | DW_CFA_advance_loc4 = 0x04uy + | DW_CFA_def_cfa = 0x0cuy + | DW_CFA_def_cfa_sf = 0x12uy + | DW_CFA_def_cfa_register = 0x0duy + | DW_CFA_def_cfa_offset = 0x0euy + | DW_CFA_def_cfa_offset_sf = 0x13uy + | DW_CFA_def_cfa_expression = 0x0fuy + | DW_CFA_undefined = 0x07uy + | DW_CFA_same_value = 0x08uy + | DW_CFA_offset = 0x80uy + | DW_CFA_offset_extended = 0x05uy + | DW_CFA_offset_extended_sf = 0x11uy + | DW_CFA_val_offset = 0x14uy + | DW_CFA_val_offset_sf = 0x15uy + | DW_CFA_register = 0x09uy + | DW_CFA_expression = 0x10uy + | DW_CFA_val_expression = 0x16uy + | DW_CFA_restore = 0xc0uy + | DW_CFA_restore_extended = 0x06uy + | DW_CFA_remember_state = 0x0auy + | DW_CFA_restore_state = 0x0buy + | DW_CFA_GNU_args_size = 0x2euy + | DW_CFA_GNU_negative_offset_extended = 0x2fuy + | DW_CFA_nop = 0x00uy + +[] +module DWCFAInstruction = + let parse (b: byte) = EnumOfValue b + +/// Dwarf opcodes. +type DWOperation = + | DW_OP_lit0 = 0x30uy + | DW_OP_lit1 = 0x31uy + | DW_OP_lit2 = 0x32uy + | DW_OP_lit3 = 0x33uy + | DW_OP_lit4 = 0x34uy + | DW_OP_lit5 = 0x35uy + | DW_OP_lit6 = 0x36uy + | DW_OP_lit7 = 0x37uy + | DW_OP_lit8 = 0x38uy + | DW_OP_lit9 = 0x39uy + | DW_OP_lit10 = 0x3auy + | DW_OP_lit11 = 0x3buy + | DW_OP_lit12 = 0x3cuy + | DW_OP_lit13 = 0x3duy + | DW_OP_lit14 = 0x3euy + | DW_OP_lit15 = 0x3fuy + | DW_OP_lit16 = 0x40uy + | DW_OP_lit17 = 0x41uy + | DW_OP_lit18 = 0x42uy + | DW_OP_lit19 = 0x43uy + | DW_OP_lit20 = 0x44uy + | DW_OP_lit21 = 0x45uy + | DW_OP_lit22 = 0x46uy + | DW_OP_lit23 = 0x47uy + | DW_OP_lit24 = 0x48uy + | DW_OP_lit25 = 0x49uy + | DW_OP_lit26 = 0x4auy + | DW_OP_lit27 = 0x4buy + | DW_OP_lit28 = 0x4cuy + | DW_OP_lit29 = 0x4duy + | DW_OP_lit30 = 0x4euy + | DW_OP_lit31 = 0x4fuy + | DW_OP_addr = 0x03uy + | DW_OP_const1u = 0x08uy + | DW_OP_const1s = 0x09uy + | DW_OP_const2u = 0x0auy + | DW_OP_const2s = 0x0buy + | DW_OP_const4u = 0x0cuy + | DW_OP_const4s = 0x0duy + | DW_OP_const8u = 0x0euy + | DW_OP_const8s = 0x0fuy + | DW_OP_constu = 0x10uy + | DW_OP_consts = 0x11uy + | DW_OP_fbreg = 0x91uy + | DW_OP_reg0 = 0x50uy + | DW_OP_reg1 = 0x51uy + | DW_OP_reg2 = 0x52uy + | DW_OP_reg3 = 0x53uy + | DW_OP_reg4 = 0x54uy + | DW_OP_reg5 = 0x55uy + | DW_OP_reg6 = 0x56uy + | DW_OP_reg7 = 0x57uy + | DW_OP_reg8 = 0x58uy + | DW_OP_reg9 = 0x59uy + | DW_OP_reg10 = 0x5auy + | DW_OP_reg11 = 0x5buy + | DW_OP_reg12 = 0x5cuy + | DW_OP_reg13 = 0x5duy + | DW_OP_reg14 = 0x5euy + | DW_OP_reg15 = 0x5fuy + | DW_OP_reg16 = 0x60uy + | DW_OP_reg17 = 0x61uy + | DW_OP_reg18 = 0x62uy + | DW_OP_reg19 = 0x63uy + | DW_OP_reg20 = 0x64uy + | DW_OP_reg21 = 0x65uy + | DW_OP_reg22 = 0x66uy + | DW_OP_reg23 = 0x67uy + | DW_OP_reg24 = 0x68uy + | DW_OP_reg25 = 0x69uy + | DW_OP_reg26 = 0x6auy + | DW_OP_reg27 = 0x6buy + | DW_OP_reg28 = 0x6cuy + | DW_OP_reg29 = 0x6duy + | DW_OP_reg30 = 0x6euy + | DW_OP_reg31 = 0x6fuy + | DW_OP_regx = 0x90uy + | DW_OP_breg0 = 0x70uy + | DW_OP_breg1 = 0x71uy + | DW_OP_breg2 = 0x72uy + | DW_OP_breg3 = 0x73uy + | DW_OP_breg4 = 0x74uy + | DW_OP_breg5 = 0x75uy + | DW_OP_breg6 = 0x76uy + | DW_OP_breg7 = 0x77uy + | DW_OP_breg8 = 0x78uy + | DW_OP_breg9 = 0x79uy + | DW_OP_breg10 = 0x7auy + | DW_OP_breg11 = 0x7buy + | DW_OP_breg12 = 0x7cuy + | DW_OP_breg13 = 0x7duy + | DW_OP_breg14 = 0x7euy + | DW_OP_breg15 = 0x7fuy + | DW_OP_breg16 = 0x80uy + | DW_OP_breg17 = 0x81uy + | DW_OP_breg18 = 0x82uy + | DW_OP_breg19 = 0x83uy + | DW_OP_breg20 = 0x84uy + | DW_OP_breg21 = 0x85uy + | DW_OP_breg22 = 0x86uy + | DW_OP_breg23 = 0x87uy + | DW_OP_breg24 = 0x88uy + | DW_OP_breg25 = 0x89uy + | DW_OP_breg26 = 0x8auy + | DW_OP_breg27 = 0x8buy + | DW_OP_breg28 = 0x8cuy + | DW_OP_breg29 = 0x8duy + | DW_OP_breg30 = 0x8euy + | DW_OP_breg31 = 0x8fuy + | DW_OP_bregx = 0x92uy + | DW_OP_dup = 0x12uy + | DW_OP_drop = 0x13uy + | DW_OP_over = 0x14uy + | DW_OP_pick = 0x15uy + | DW_OP_swap = 0x16uy + | DW_OP_rot = 0x17uy + | DW_OP_deref = 0x06uy + | DW_OP_deref_size = 0x94uy + | DW_OP_xderef = 0x18uy + | DW_OP_xderef_size = 0x95uy + | DW_OP_push_object_address = 0x97uy + | DW_OP_form_tls_address = 0x9buy + | DW_OP_call_frame_cfa = 0x9cuy + | DW_OP_abs = 0x19uy + | DW_OP_and = 0x1auy + | DW_OP_div = 0x1buy + | DW_OP_minus = 0x1cuy + | DW_OP_mod = 0x1duy + | DW_OP_mul = 0x1euy + | DW_OP_neg = 0x1fuy + | DW_OP_not = 0x20uy + | DW_OP_or = 0x21uy + | DW_OP_plus = 0x22uy + | DW_OP_plus_uconst = 0x23uy + | DW_OP_shl = 0x24uy + | DW_OP_shr = 0x25uy + | DW_OP_shra = 0x26uy + | DW_OP_xor = 0x27uy + | DW_OP_bra = 0x28uy + | DW_OP_eq = 0x29uy + | DW_OP_ge = 0x2auy + | DW_OP_gt = 0x2buy + | DW_OP_le = 0x2cuy + | DW_OP_lt = 0x2duy + | DW_OP_ne = 0x2euy + | DW_OP_skip = 0x2fuy + | DW_OP_call2 = 0x98uy + | DW_OP_call4 = 0x99uy + | DW_OP_call_ref = 0x9auy + | DW_OP_nop = 0x96uy + | DW_OP_implicit_value = 0x9euy + | DW_OP_stack_value = 0x9fuy + | DW_OP_piece = 0x93uy + | DW_OP_bit_piece = 0x9duy + +[] +module DWOperation = + let parse (b: byte) = EnumOfValue b + +module DWRegister = + let private toIntelx86Register = function + | 0uy -> Intel.Register.toRegID Intel.Register.EAX + | 1uy -> Intel.Register.toRegID Intel.Register.ECX + | 2uy -> Intel.Register.toRegID Intel.Register.EDX + | 3uy -> Intel.Register.toRegID Intel.Register.EBX + | 4uy -> Intel.Register.toRegID Intel.Register.ESP + | 5uy -> Intel.Register.toRegID Intel.Register.EBP + | 6uy -> Intel.Register.toRegID Intel.Register.ESI + | 7uy -> Intel.Register.toRegID Intel.Register.EDI + | 8uy -> Intel.Register.toRegID Intel.Register.EIP + | _ -> Utils.futureFeature () + + let private toIntelx64Register = function + | 0uy -> Intel.Register.toRegID Intel.Register.RAX + | 1uy -> Intel.Register.toRegID Intel.Register.RDX + | 2uy -> Intel.Register.toRegID Intel.Register.RCX + | 3uy -> Intel.Register.toRegID Intel.Register.RBX + | 4uy -> Intel.Register.toRegID Intel.Register.RSI + | 5uy -> Intel.Register.toRegID Intel.Register.RDI + | 6uy -> Intel.Register.toRegID Intel.Register.RBP + | 7uy -> Intel.Register.toRegID Intel.Register.RSP + | 8uy -> Intel.Register.toRegID Intel.Register.R8 + | 9uy -> Intel.Register.toRegID Intel.Register.R9 + | 10uy -> Intel.Register.toRegID Intel.Register.R10 + | 11uy -> Intel.Register.toRegID Intel.Register.R11 + | 12uy -> Intel.Register.toRegID Intel.Register.R12 + | 13uy -> Intel.Register.toRegID Intel.Register.R13 + | 14uy -> Intel.Register.toRegID Intel.Register.R14 + | 15uy -> Intel.Register.toRegID Intel.Register.R15 + | 16uy -> Intel.Register.toRegID Intel.Register.RIP + | 17uy -> Intel.Register.toRegID Intel.Register.XMM0 + | 18uy -> Intel.Register.toRegID Intel.Register.XMM1 + | 19uy -> Intel.Register.toRegID Intel.Register.XMM2 + | 20uy -> Intel.Register.toRegID Intel.Register.XMM3 + | 21uy -> Intel.Register.toRegID Intel.Register.XMM4 + | 22uy -> Intel.Register.toRegID Intel.Register.XMM5 + | 23uy -> Intel.Register.toRegID Intel.Register.XMM6 + | 24uy -> Intel.Register.toRegID Intel.Register.XMM7 + | 25uy -> Intel.Register.toRegID Intel.Register.XMM8 + | 26uy -> Intel.Register.toRegID Intel.Register.XMM9 + | 27uy -> Intel.Register.toRegID Intel.Register.XMM10 + | 28uy -> Intel.Register.toRegID Intel.Register.XMM11 + | 29uy -> Intel.Register.toRegID Intel.Register.XMM12 + | 30uy -> Intel.Register.toRegID Intel.Register.XMM13 + | 31uy -> Intel.Register.toRegID Intel.Register.XMM14 + | 32uy -> Intel.Register.toRegID Intel.Register.XMM15 + | _ -> Utils.futureFeature () + + let private toAArch64Register = function + | 0uy -> ARM64.Register.toRegID ARM64.Register.X0 + | 1uy -> ARM64.Register.toRegID ARM64.Register.X1 + | 2uy -> ARM64.Register.toRegID ARM64.Register.X2 + | 3uy -> ARM64.Register.toRegID ARM64.Register.X3 + | 4uy -> ARM64.Register.toRegID ARM64.Register.X4 + | 5uy -> ARM64.Register.toRegID ARM64.Register.X5 + | 6uy -> ARM64.Register.toRegID ARM64.Register.X6 + | 7uy -> ARM64.Register.toRegID ARM64.Register.X7 + | 8uy -> ARM64.Register.toRegID ARM64.Register.X8 + | 9uy -> ARM64.Register.toRegID ARM64.Register.X9 + | 10uy -> ARM64.Register.toRegID ARM64.Register.X10 + | 11uy -> ARM64.Register.toRegID ARM64.Register.X11 + | 12uy -> ARM64.Register.toRegID ARM64.Register.X12 + | 13uy -> ARM64.Register.toRegID ARM64.Register.X13 + | 14uy -> ARM64.Register.toRegID ARM64.Register.X14 + | 15uy -> ARM64.Register.toRegID ARM64.Register.X15 + | 16uy -> ARM64.Register.toRegID ARM64.Register.X16 + | 17uy -> ARM64.Register.toRegID ARM64.Register.X17 + | 18uy -> ARM64.Register.toRegID ARM64.Register.X18 + | 19uy -> ARM64.Register.toRegID ARM64.Register.X19 + | 20uy -> ARM64.Register.toRegID ARM64.Register.X20 + | 21uy -> ARM64.Register.toRegID ARM64.Register.X21 + | 22uy -> ARM64.Register.toRegID ARM64.Register.X22 + | 23uy -> ARM64.Register.toRegID ARM64.Register.X23 + | 24uy -> ARM64.Register.toRegID ARM64.Register.X24 + | 25uy -> ARM64.Register.toRegID ARM64.Register.X25 + | 26uy -> ARM64.Register.toRegID ARM64.Register.X26 + | 27uy -> ARM64.Register.toRegID ARM64.Register.X27 + | 28uy -> ARM64.Register.toRegID ARM64.Register.X28 + | 29uy -> ARM64.Register.toRegID ARM64.Register.X29 + | 30uy -> ARM64.Register.toRegID ARM64.Register.X30 + | 31uy -> ARM64.Register.toRegID ARM64.Register.SP + | 64uy -> ARM64.Register.toRegID ARM64.Register.V0 + | 65uy -> ARM64.Register.toRegID ARM64.Register.V1 + | 66uy -> ARM64.Register.toRegID ARM64.Register.V2 + | 67uy -> ARM64.Register.toRegID ARM64.Register.V3 + | 68uy -> ARM64.Register.toRegID ARM64.Register.V4 + | 69uy -> ARM64.Register.toRegID ARM64.Register.V5 + | 70uy -> ARM64.Register.toRegID ARM64.Register.V6 + | 71uy -> ARM64.Register.toRegID ARM64.Register.V7 + | 72uy -> ARM64.Register.toRegID ARM64.Register.V8 + | 73uy -> ARM64.Register.toRegID ARM64.Register.V9 + | 74uy -> ARM64.Register.toRegID ARM64.Register.V10 + | 75uy -> ARM64.Register.toRegID ARM64.Register.V11 + | 76uy -> ARM64.Register.toRegID ARM64.Register.V12 + | 77uy -> ARM64.Register.toRegID ARM64.Register.V13 + | 78uy -> ARM64.Register.toRegID ARM64.Register.V14 + | 79uy -> ARM64.Register.toRegID ARM64.Register.V15 + | 80uy -> ARM64.Register.toRegID ARM64.Register.V16 + | 81uy -> ARM64.Register.toRegID ARM64.Register.V17 + | 82uy -> ARM64.Register.toRegID ARM64.Register.V18 + | 83uy -> ARM64.Register.toRegID ARM64.Register.V19 + | 84uy -> ARM64.Register.toRegID ARM64.Register.V20 + | 85uy -> ARM64.Register.toRegID ARM64.Register.V21 + | 86uy -> ARM64.Register.toRegID ARM64.Register.V22 + | 87uy -> ARM64.Register.toRegID ARM64.Register.V23 + | 88uy -> ARM64.Register.toRegID ARM64.Register.V24 + | 89uy -> ARM64.Register.toRegID ARM64.Register.V25 + | 90uy -> ARM64.Register.toRegID ARM64.Register.V26 + | 91uy -> ARM64.Register.toRegID ARM64.Register.V27 + | 92uy -> ARM64.Register.toRegID ARM64.Register.V28 + | 93uy -> ARM64.Register.toRegID ARM64.Register.V29 + | 94uy -> ARM64.Register.toRegID ARM64.Register.V30 + | 95uy -> ARM64.Register.toRegID ARM64.Register.V31 + | x -> Utils.futureFeature () + + let toRegID isa regnum = + match isa.Arch with + | Architecture.IntelX86 -> toIntelx86Register regnum + | Architecture.IntelX64 -> toIntelx64Register regnum + | Architecture.AARCH64 -> toAArch64Register regnum + | _ -> Utils.futureFeature () + + let toRegisterExpr isa (regbay: RegisterBay) regnum = + toRegID isa regnum |> regbay.RegIDToRegExpr + +/// The CFA. Machine-independent representation of the current frame address. +/// For example, (esp+8) on x86. +type CanonicalFrameAddress = + | RegPlusOffset of RegisterID * int + | Expression of LowUIR.Expr + | UnknownCFA + +module CanonicalFrameAddress = + let regPlusOffset isa regbay regnum offset = + RegPlusOffset (DWRegister.toRegID isa regnum, offset) + + let toString (regbay: RegisterBay) = function + | RegPlusOffset (rid, offset) -> + regbay.RegIDToString rid + (offset.ToString ("+0;-#")) + | Expression exp -> + LowUIR.Pp.expToString exp + | UnknownCFA -> "unknown" + +/// How does a target value get stored on the stack frame. +type Action = + /// Has no recoverable value in the previous frame. + | Undefined + /// The register has not been modified from the previous frame. + | SameValue + /// The previous value of this register is saved at the address CFA+N where + /// CFA is the current CFA value and N is a signed offset. + | Offset of int64 + /// The previous value of this register is the value CFA+N where CFA is the + /// current CFA value and N is a signed offset. + | ValOffset of int + /// The previous value of this register is stored in another register numbered + /// R. + | Register of RegisterID + /// The previous value is represented as the expression. + | ActionExpr of LowUIR.Expr + +module Action = + let toString = function + | Undefined -> "undef" + | SameValue -> "samevalue" + | Offset o -> "c" + (o.ToString ("+0;-#")) + | ValOffset o -> "v" + (o.ToString ("+0;-#")) + | Register rid -> "r(" + rid.ToString () + ")" + | ActionExpr e -> "exp:" + LowUIR.Pp.expToString e + +/// Either a return address or a normal register is stored on the stack. +type Target = + | ReturnAddress + | NormalReg of RegisterID + +/// Rule that describes how a given register/return address has been saved on +/// the stack frame. +type Rule = Map + +module Rule = + let getTarget isa returnAddressReg (reg: byte) = + if returnAddressReg = reg then ReturnAddress + else DWRegister.toRegID isa reg |> NormalReg + + let offset isa rr reg v = + getTarget isa rr reg, Offset v + +/// An entry (a row) of the call frame information table (unwinding table). +type UnwindingEntry = { + /// Instruction location. + Location: Addr + /// CFA. + CanonicalFrameAddress: CanonicalFrameAddress + /// Unwinding rule. + Rule: Rule +} diff --git a/src/FrontEnd/BinFile/ELFExceptionFrames.fs b/src/FrontEnd/BinFile/ELFExceptionFrames.fs new file mode 100644 index 00000000..45b849e2 --- /dev/null +++ b/src/FrontEnd/BinFile/ELFExceptionFrames.fs @@ -0,0 +1,715 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +[] +module internal B2R2.FrontEnd.BinFile.ELF.ExceptionFrames + +open System +open System.Runtime.InteropServices +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.FrontEnd.BinFile.ELF.ExceptionHeaderEncoding + +/// Raised when an unhandled eh_frame version is encountered. +exception UnhandledExceptionHandlingFrameVersion + +/// Raised when an unhandled augment string is encountered. +exception UnhandledAugString + +/// Raised when CIE is not found by FDE +exception CIENotFoundByFDE + +/// Raised when invalid sequence of dwarf instructions encountered. +exception InvalidDWInstructionExpression + +let [] ehframe = ".eh_frame" + +let inline readInt (reader: BinReader) offset = + reader.ReadInt32 offset + +let inline readUInt64 (reader: BinReader) offset = + reader.ReadUInt64 offset + +let computeNextOffset len (reader: BinReader) offset = + if len = -1 then + let struct (len, offset) = readUInt64 reader offset + int len + offset, offset + else len + offset, offset + +let parseReturnRegister (reader: BinReader) version offset = + if version = 1uy then reader.PeekByte offset, offset + 1 + else + let r, offset = parseULEB128 reader offset + byte r, offset + +let personalityRoutinePointerSize addrSize = function + | 2uy -> 2 + | 3uy -> 4 + | 4uy -> 8 + | _ -> addrSize + +let obtainAugData addrSize (arr: byte []) data offset = function + | 'L' -> + let struct (v, app) = parseEncoding arr.[offset] + { Format = 'L' + ValueEncoding = v + ApplicationEncoding = app + PersonalityRoutionPointer = [||] } :: data, offset + 1 + | 'P' -> + let struct (v, app) = parseEncoding arr.[offset] + let psz = arr.[offset] &&& 7uy |> personalityRoutinePointerSize addrSize + let prp = arr.[ offset + 1 .. offset + psz ] + { Format = 'P' + ValueEncoding = v + ApplicationEncoding = app + PersonalityRoutionPointer = prp } :: data, offset + psz + 1 + | 'R' -> + let struct (v, app) = parseEncoding arr.[offset] + { Format = 'R' + ValueEncoding = v + ApplicationEncoding = app + PersonalityRoutionPointer = [||] } :: data, offset + 1 + | 'S' -> data, offset (* This is a signal frame. *) + | _ -> raise UnhandledAugString + +let parseAugmentationData (reader: BinReader) offset addrSize augstr = + if (augstr: string).StartsWith ('z') then + let len, offset = parseULEB128 reader offset + let span = reader.PeekSpan (int len, offset) + let arr = span.ToArray () + augstr.[ 1.. ] + |> Seq.fold (fun (data, idx) ch -> + obtainAugData addrSize arr data idx ch) ([], 0) + |> fst |> List.rev, offset + int len + else [], offset + +let num isa n = + let rt = isa.WordSize |> WordSize.toRegType + AST.num (BitVector.ofUInt64 n rt) + +let regPlusNum isa regbay reg n = + let regexp = DWRegister.toRegisterExpr isa regbay reg + AST.binop BinOpType.ADD regexp (num isa n) + +let parseOpBReg isa regbay exprs (span: ReadOnlySpan) idx reg = + let offset, cnt = LEB128.DecodeUInt64 (span.Slice (idx)) + let exprs = regPlusNum isa regbay reg offset :: exprs + struct (exprs, idx + cnt) + +let pop exprs = + match exprs with + | fst :: rest -> struct (fst, rest) + | _ -> Utils.impossible () + +let pop2 exprs = + match exprs with + | fst :: snd :: rest -> struct (fst, snd, rest) + | _ -> Utils.impossible () + +let inline hasLessThanTwoOperands exprs = + match exprs with + | [ _ ] | [] -> true + | _ -> false + +let parseBinop op exprs = + let struct (fst, snd, exprs) = pop2 exprs + AST.binop op snd fst :: exprs + +let parsePlusUconst isa exprs (span: ReadOnlySpan) idx = + let n, cnt = LEB128.DecodeUInt64 (span.Slice (idx)) + let n = num isa n + let struct (fst, exprs) = pop exprs + let exprs = AST.binop BinOpType.ADD fst n :: exprs + struct (exprs, idx + cnt) + +let parseRel isa op exprs = + let struct (fst, snd, exprs) = pop2 exprs + let rt = isa.WordSize |> WordSize.toRegType + AST.cast CastKind.ZeroExt rt (AST.relop op snd fst) :: exprs + +let parseLoad isa exprs = + let struct (addr, exprs) = pop exprs + let rt = isa.WordSize |> WordSize.toRegType + AST.loadLE rt addr :: exprs + +let rec parseExprs isa regbay exprs (span: ReadOnlySpan) i maxIdx = + if i >= maxIdx then + match exprs with + | [ exp ] -> exp + | _ -> raise InvalidDWInstructionExpression + else + match span.[i] |> DWOperation.parse with + | DWOperation.DW_OP_breg0 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 0uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg1 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 1uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg2 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 2uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg3 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 3uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg4 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 4uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg5 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 5uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg6 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 6uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg7 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 7uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg8 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 8uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg9 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 9uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg10 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 10uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg11 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 11uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg12 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 12uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg13 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 13uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg14 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 14uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg15 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 15uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg16 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 16uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg17 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 17uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg18 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 18uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg19 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 19uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg20 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 20uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg21 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 21uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg22 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 22uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg23 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 23uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg24 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 24uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg25 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 25uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg26 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 26uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg27 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 27uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg28 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 28uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg29 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 29uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg30 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 30uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_breg31 -> + let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 31uy + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_const1u -> + let exprs = num isa (uint64 span.[i + 1]) :: exprs + parseExprs isa regbay exprs span (i + 2) maxIdx + | DWOperation.DW_OP_const1s -> + let exprs = num isa (int64 span.[i + 1] |> uint64) :: exprs + parseExprs isa regbay exprs span (i + 2) maxIdx + | DWOperation.DW_OP_const2u -> + let c = MemoryMarshal.Read (span.Slice (i + 1)) + let exprs = num isa (uint64 c) :: exprs + parseExprs isa regbay exprs span (i + 3) maxIdx + | DWOperation.DW_OP_const2s -> + let c = MemoryMarshal.Read (span.Slice (i + 1)) + let exprs = num isa (int64 c |> uint64) :: exprs + parseExprs isa regbay exprs span (i + 3) maxIdx + | DWOperation.DW_OP_const4u -> + let c = MemoryMarshal.Read (span.Slice (i + 1)) + let exprs = num isa (uint64 c) :: exprs + parseExprs isa regbay exprs span (i + 5) maxIdx + | DWOperation.DW_OP_const4s -> + let c = MemoryMarshal.Read (span.Slice (i + 1)) + let exprs = num isa (int64 c |> uint64) :: exprs + parseExprs isa regbay exprs span (i + 5) maxIdx + | DWOperation.DW_OP_lit0 -> + let exprs = num isa 0UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit1 -> + let exprs = num isa 1UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit2 -> + let exprs = num isa 2UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit3 -> + let exprs = num isa 3UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit4 -> + let exprs = num isa 4UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit5 -> + let exprs = num isa 5UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit6 -> + let exprs = num isa 6UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit7 -> + let exprs = num isa 7UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit8 -> + let exprs = num isa 8UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit9 -> + let exprs = num isa 9UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit10 -> + let exprs = num isa 10UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit11 -> + let exprs = num isa 11UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit12 -> + let exprs = num isa 12UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit13 -> + let exprs = num isa 13UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit14 -> + let exprs = num isa 14UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit15 -> + let exprs = num isa 15UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit16 -> + let exprs = num isa 16UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit17 -> + let exprs = num isa 17UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit18 -> + let exprs = num isa 18UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit19 -> + let exprs = num isa 19UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit20 -> + let exprs = num isa 20UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit21 -> + let exprs = num isa 21UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit22 -> + let exprs = num isa 22UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit23 -> + let exprs = num isa 23UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit24 -> + let exprs = num isa 24UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit25 -> + let exprs = num isa 25UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit26 -> + let exprs = num isa 26UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit27 -> + let exprs = num isa 27UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit28 -> + let exprs = num isa 28UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit29 -> + let exprs = num isa 29UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit30 -> + let exprs = num isa 30UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit31 -> + let exprs = num isa 31UL :: exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_and -> + let exprs = parseBinop BinOpType.AND exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_or -> + let exprs = parseBinop BinOpType.OR exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_xor -> + let exprs = parseBinop BinOpType.XOR exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_div -> + let exprs = parseBinop BinOpType.DIV exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_minus -> + (* There is an exceptional case where ICC compbiler uses DW_OP_minus with + a single opearnd. This is not the standard way. *) + let exprs = + if hasLessThanTwoOperands exprs then [ num isa 0UL ] + else parseBinop BinOpType.SUB exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_plus -> + let exprs = parseBinop BinOpType.ADD exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_plus_uconst -> + let struct (exprs, i') = parsePlusUconst isa exprs span (i + 1) + parseExprs isa regbay exprs span i' maxIdx + | DWOperation.DW_OP_mul -> + let exprs = parseBinop BinOpType.MUL exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_shl -> + let exprs = parseBinop BinOpType.SHL exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_shr -> + let exprs = parseBinop BinOpType.SHR exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_shra -> + let exprs = parseBinop BinOpType.SAR exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_le -> + let exprs = parseRel isa RelOpType.LE exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_ge -> + let exprs = parseRel isa RelOpType.GE exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_eq -> + let exprs = parseRel isa RelOpType.EQ exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lt -> + let exprs = parseRel isa RelOpType.LT exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_gt -> + let exprs = parseRel isa RelOpType.GT exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_ne -> + let exprs = parseRel isa RelOpType.NEQ exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | DWOperation.DW_OP_deref -> + let exprs = parseLoad isa exprs + parseExprs isa regbay exprs span (i + 1) maxIdx + | op -> printfn "TODO: %A" op; Utils.futureFeature () + +let extractOldOffset = function + | RegPlusOffset (_, o) -> o + | _ -> Utils.impossible () + +let restoreOne initialRule currentRule target = + match Map.tryFind target initialRule with + | Some oldVal -> Map.add target oldVal currentRule + | None -> Map.remove target currentRule + +let rec getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i loc = + if i >= (span: ReadOnlySpan).Length then + { Location = loc + CanonicalFrameAddress = cfa + Rule = rule } :: acc |> List.rev, cfa, lr + else + let op = span.[i] + let oparg = span.[i] &&& 0x3fuy + let i = i + 1 + let op = if op &&& 0xc0uy > 0uy then op &&& 0xc0uy else op + match DWCFAInstruction.parse op with + | DWCFAInstruction.DW_CFA_def_cfa -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let i = i + cnt + let offset, cnt = LEB128.DecodeUInt64 (span.Slice i) + let cfa = CanonicalFrameAddress.regPlusOffset isa rbay reg (int offset) + getUnwind acc cfa irule rst rule isa rbay reg cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_def_cfa_offset -> + let offset, cnt = LEB128.DecodeUInt64 (span.Slice i) + let cfa = CanonicalFrameAddress.regPlusOffset isa rbay lr (int offset) + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_def_cfa_offset_sf -> + let offset, cnt = LEB128.DecodeSInt64 (span.Slice i) + let offset = int (offset * df) + let cfa = CanonicalFrameAddress.regPlusOffset isa rbay lr offset + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_def_cfa_expression -> + let v, cnt = LEB128.DecodeUInt64 (span.Slice i) + let i = i + cnt + let nextIdx = int v + i + let cfa = parseExprs isa rbay [] span i nextIdx |> Expression + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span nextIdx loc + | DWCFAInstruction.DW_CFA_def_cfa_register -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let rid = DWRegister.toRegID isa reg + let oldOffset = extractOldOffset cfa + let cfa = RegPlusOffset (rid, oldOffset) + getUnwind acc cfa irule rst rule isa rbay reg cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_offset -> + let v, cnt = LEB128.DecodeUInt64 (span.Slice i) + let offset = int64 v * df + let target, action = Rule.offset isa rr oparg offset + let rule = Map.add target action rule + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_offset_extended -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let i = i + cnt + let offset, cnt = LEB128.DecodeUInt64 (span.Slice i) + let target, action = Rule.offset isa rr reg (int64 offset) + let rule = Map.add target action rule + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_offset_extended_sf -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let i = i + cnt + let v, cnt = LEB128.DecodeSInt64 (span.Slice i) + let offset = v * df + let target, action = Rule.offset isa rr reg offset + let rule = Map.add target action rule + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_undefined -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let target = Rule.getTarget isa rr reg + let rule = Map.remove target rule + getUnwind acc cfa irule rst rule isa rbay reg cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_register -> + let reg1, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg1 = byte reg1 + let i = i + cnt + let reg2, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg2 = byte reg2 + let target = Rule.getTarget isa rr reg1 + let action = Register (DWRegister.toRegID isa reg2) + let rule = Map.add target action rule + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_expression -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let i = i + cnt + let v, cnt = LEB128.DecodeUInt64 (span.Slice i) + let i = i + cnt + let nextIdx = int v + i + let target = Rule.getTarget isa rr reg + let action = parseExprs isa rbay [] span i nextIdx |> ActionExpr + let rule = Map.add target action rule + getUnwind acc cfa irule rst rule isa rbay reg cf df rr span nextIdx loc + | DWCFAInstruction.DW_CFA_advance_loc -> + let loc' = loc + uint64 oparg * cf + let ent = { Location = loc; CanonicalFrameAddress = cfa; Rule = rule } + let acc = ent :: acc + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i loc' + | DWCFAInstruction.DW_CFA_advance_loc1 -> + let loc' = loc + uint64 span.[i] + let i' = i + 1 + let ent = { Location = loc; CanonicalFrameAddress = cfa; Rule = rule } + let acc = ent :: acc + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i' loc' + | DWCFAInstruction.DW_CFA_advance_loc2 -> + let loc' = loc + uint64 (MemoryMarshal.Read (span.Slice (i))) + let i' = i + 2 + let ent = { Location = loc; CanonicalFrameAddress = cfa; Rule = rule } + let acc = ent :: acc + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i' loc' + | DWCFAInstruction.DW_CFA_advance_loc4 -> + let loc' = loc + uint64 (MemoryMarshal.Read (span.Slice (i))) + let i' = i + 4 + let ent = { Location = loc; CanonicalFrameAddress = cfa; Rule = rule } + let acc = ent :: acc + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i' loc' + | DWCFAInstruction.DW_CFA_remember_state -> + let rst = (cfa, rule) :: rst + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i loc + | DWCFAInstruction.DW_CFA_restore -> + let target = Rule.getTarget isa rr oparg + let rule = restoreOne irule rule target + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i loc + | DWCFAInstruction.DW_CFA_restore_extended -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let target = Rule.getTarget isa rr (byte reg) + let rule = restoreOne irule rule target + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_restore_state -> + let cfa, rule = List.head rst + let rst = List.tail rst + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i loc + | DWCFAInstruction.DW_CFA_GNU_args_size -> + let _, cnt = LEB128.DecodeUInt64 (span.Slice i) + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_nop -> + getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i loc + | op -> printfn "%A" op; Utils.futureFeature () + +let extractRule unwindingInfo = + match unwindingInfo with + | [ row ] -> row.Rule + | _ -> Map.empty + +let parseCIE cls isa rbay (reader: BinReader) offset nextOffset = + let struct (version, offset) = reader.ReadByte offset + if version = 1uy || version = 3uy then + let span = reader.PeekSpan offset + let augstr = ByteArray.extractCStringFromSpan span 0 + let addrSize = WordSize.toByteWidth cls + let offset = offset + augstr.Length + 1 + let offset = if augstr.Contains "eh" then offset + addrSize else offset + let cf, offset = parseULEB128 reader offset + let df, offset = parseSLEB128 reader offset + let rr, offset = parseReturnRegister reader version offset + let augs, offset = parseAugmentationData reader offset addrSize augstr + let instrLen = nextOffset - offset + if instrLen > 0 then + let span = reader.PeekSpan (instrLen, offset) + let rule = Map.empty + getUnwind [] UnknownCFA rule [] rule isa rbay rr cf df rr span 0 0UL + else [], UnknownCFA, rr + |> fun (info, cfa, reg) -> + { Version = version + AugmentationString = augstr + CodeAlignmentFactor = cf + DataAlignmentFactor = df + ReturnAddressRegister = byte rr + InitialRule = extractRule info + InitialCFARegister = reg + InitialCFA = cfa + Augmentations = augs } + else + raise UnhandledExceptionHandlingFrameVersion + +let tryFindAugmentation cie format = + cie.Augmentations |> List.tryFind (fun aug -> aug.Format = format) + +let adjustAddr app myAddr addr = + match app with + | ExceptionHeaderApplication.DW_EH_PE_pcrel -> addr + myAddr + | _ -> addr + +let parsePCInfo cls reader sAddr venc aenc offset = + let myAddr = sAddr + uint64 offset + let struct (addr, offset) = computeValue cls reader venc offset + let struct (range, offset) = computeValue cls reader venc offset + let beginAddr = adjustAddr aenc myAddr addr + let endAddr = beginAddr + range + beginAddr, endAddr, offset + +let parseLSDA cls reader sAddr aug offset = + let _, offset = parseULEB128 reader offset + let myAddr = sAddr + uint64 offset + let struct (addr, offset) = computeValue cls reader aug.ValueEncoding offset + Some (adjustAddr aug.ApplicationEncoding myAddr addr), offset + +let parseCallFrameInstrs cie isa regbay reader offset nextOffset loc = + let span = (reader: BinReader).PeekSpan (nextOffset - offset, offset) + let insarr = span.ToArray () + if Array.forall (fun b -> b = 0uy) insarr then [] + else + let cf = cie.CodeAlignmentFactor + let df = cie.DataAlignmentFactor + let rr = cie.ReturnAddressRegister + let ir = cie.InitialCFARegister + let r = cie.InitialRule + let cfa = cie.InitialCFA + let info, _, _ = getUnwind [] cfa r [] r isa regbay ir cf df rr span 0 loc + info + +let parseFDE cls isa regbay reader sAddr offset nextOffset cie = + match cie with + | Some cie -> + let venc, aenc = + match tryFindAugmentation cie 'R' with + | Some aug -> aug.ValueEncoding, aug.ApplicationEncoding + | None -> ExceptionHeaderValue.DW_EH_PE_absptr, + ExceptionHeaderApplication.DW_EH_PE_absptr + let b, e, offset = + parsePCInfo cls reader sAddr venc aenc offset + let lsdaPointer, offset = + match tryFindAugmentation cie 'L' with + | Some aug -> parseLSDA cls reader sAddr aug offset + | None -> None, offset + let info = parseCallFrameInstrs cie isa regbay reader offset nextOffset b + { PCBegin = b + PCEnd = e + LSDAPointer = lsdaPointer + UnwindingInfo = info } + | None -> raise CIENotFoundByFDE + +let accumulateCFIs cfis cie fdes = + match cie with + | Some cie -> + { CIERecord = cie + FDERecord = List.rev fdes |> List.toArray } :: cfis + | None -> cfis + +let rec parseCFI cls isa regbay reader sAddr cie cies fdes offset cfis = + if offset >= ((reader: BinReader).Length ()) then accumulateCFIs cfis cie fdes + else + let originalOffset = offset + let struct (len, offset) = readInt reader offset + if len = 0 then accumulateCFIs cfis cie fdes + else + let nextOffset, offset = computeNextOffset len reader offset + let mybase = offset + let struct (id, offset) = readInt reader offset + if id = 0 then + let cfis = accumulateCFIs cfis cie fdes + let cie = parseCIE cls isa regbay reader offset nextOffset + let cies = Map.add originalOffset cie cies + parseCFI cls isa regbay reader sAddr (Some cie) cies [] nextOffset cfis + else + let cieOffset = mybase - id (* id = a CIE pointer, when id <> 0 *) + let fde = + Map.tryFind cieOffset cies + |> parseFDE cls isa regbay reader sAddr offset nextOffset + let fdes = fde :: fdes + parseCFI cls isa regbay reader sAddr cie cies fdes nextOffset cfis + +let parse (reader: BinReader) cls (secs: SectionInfo) isa regbay = + match Map.tryFind ehframe secs.SecByName with + | Some sec when Option.isSome regbay -> + let size = Convert.ToInt32 sec.SecSize + let offset = Convert.ToInt32 sec.SecOffset + let reader = reader.SubReader offset size + let regbay = Option.get regbay + parseCFI cls isa regbay reader sec.SecAddr None Map.empty [] 0 [] + |> List.rev + | _ -> [] diff --git a/src/FrontEnd/BinFile/ELFGccExceptTable.fs b/src/FrontEnd/BinFile/ELFGccExceptTable.fs new file mode 100644 index 00000000..6726d1da --- /dev/null +++ b/src/FrontEnd/BinFile/ELFGccExceptTable.fs @@ -0,0 +1,159 @@ +(* +B2R2 - the Next-Generation Reversing Platform + +Copyright (c) SoftSec Lab. @ KAIST, since 2016 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*) + +[] +module internal B2R2.FrontEnd.BinFile.ELF.ELFGccExceptTable + +open System +open B2R2 +open B2R2.FrontEnd.BinFile.ELF.ExceptionHeaderEncoding + +let [] gccExceptTable = ".gcc_except_table" + +let parseHeader cls (reader: BinReader) sAddr offset = + let struct (b, offset) = reader.ReadByte offset + let struct (lpv, lpapp) = parseEncoding b + let struct (lpstart, offset) = + if lpv = ExceptionHeaderValue.DW_EH_PE_omit then struct (None, offset) + else + let struct (cv, offset) = computeValue cls reader lpv offset + struct (Some (sAddr + uint64 offset + cv), offset) + let struct (b, offset) = reader.ReadByte offset + let struct (ttv, ttapp) = parseEncoding b + let struct (ttbase, offset) = + if ttv = ExceptionHeaderValue.DW_EH_PE_omit then struct (None, offset) + else + let cv, offset = parseULEB128 reader offset + struct (Some (sAddr + uint64 offset + cv), offset) + let struct (b, offset) = reader.ReadByte offset + let struct (csv, csapp) = parseEncoding b + let cstsz, offset = parseULEB128 reader offset + { LPValueEncoding = lpv + LPAppEncoding = lpapp + LPStart = lpstart + TTValueEncoding = ttv + TTAppEncoding = ttapp + TTBase = ttbase + CallSiteValueEncoding = csv + CallSiteAppEncoding = csapp + CallSiteTableSize = cstsz }, offset + +let rec parseCallSiteTable acc cls (reader: BinReader) offset csv hasAction = + if offset >= (reader.Length ()) then List.rev acc, hasAction + else + let struct (start, offset) = computeValue cls reader csv offset + let struct (length, offset) = computeValue cls reader csv offset + let struct (landingPad, offset) = computeValue cls reader csv offset + let actionOffset, offset = parseULEB128 reader offset + let acc = { Position = start + Length = length + LandingPad = landingPad + ActionOffset = int actionOffset + ActionTypeFilters = [] } :: acc + let hasAction = if actionOffset > 0UL then true else hasAction + parseCallSiteTable acc cls reader offset csv hasAction + +let rec parseActionEntries acc reader offset actOffset = + if actOffset > 0 then + let tfilter, offset = parseSLEB128 reader (actOffset - 1 + offset) + let next, offset = parseSLEB128 reader offset + let acc = tfilter :: acc + parseActionEntries acc reader offset (int next) + else List.rev acc + +let rec parseActionTable acc reader offset callsites = + match callsites with + | csEntry :: tl -> + let filters = parseActionEntries [] reader offset csEntry.ActionOffset + let acc = { csEntry with ActionTypeFilters = filters } :: acc + parseActionTable acc reader offset tl + | [] -> List.rev acc + +let findMinOrZero lst = + match lst with + | [] -> 0L + | _ -> List.min lst + +let findMinFilter callsites = + if List.isEmpty callsites then 0L + else + callsites + |> List.map (fun cs -> cs.ActionTypeFilters |> findMinOrZero) + |> List.min + +let rec readUntilNull (reader: BinReader) offset = + if reader.PeekByte offset = 0uy then (offset + 1) + else readUntilNull reader (offset + 1) + +/// We currently just skip the type table by picking up the minimum filter value +/// as we don't use the type table. +let skipTypeTable reader ttbase callsites = + let minFilter = findMinFilter callsites + if minFilter < 0L then + let offset = ttbase - int minFilter - 1 + readUntilNull reader offset (* Consume exception spec table. *) + else ttbase + +/// Sometimes, we observe dummy zero bytes inserted by the compiler (icc); this +/// is nothing to do with the alignment. This is likely to be the compiler +/// error, but we should safely ignore those dummy bytes. +let rec skipDummyAlign (reader: BinReader) offset = + if offset >= (reader.Length ()) then offset + else + let b = reader.PeekByte offset + if b = 0uy then skipDummyAlign reader (offset + 1) + else offset + +/// Parse language-specific data area. +let rec parseLSDA cls (reader: BinReader) sAddr offset lsdas = + if offset >= (reader.Length ()) then List.rev lsdas + else + let lsdaAddr = sAddr + uint64 offset + let header, offset = parseHeader cls reader sAddr offset + let subrdr = reader.SubReader offset (int header.CallSiteTableSize) + let callsites, hasAction = + parseCallSiteTable [] cls subrdr 0 header.CallSiteValueEncoding false + let offset = offset + int header.CallSiteTableSize + let callsites = + if hasAction then parseActionTable [] reader offset callsites + else callsites + let offset = + match header.TTBase with + | Some ttbase -> int (ttbase - sAddr) + | None -> offset + let offset = skipTypeTable reader offset callsites + let offset = skipDummyAlign reader offset + let lsdas = { LSDAAddr = lsdaAddr + Header = header + CallSiteTable = callsites } :: lsdas + parseLSDA cls reader sAddr offset lsdas + +let parse (reader: BinReader) cls (secs: SectionInfo) = + match Map.tryFind gccExceptTable secs.SecByName with + | Some sec -> + let size = Convert.ToInt32 sec.SecSize + let offset = Convert.ToInt32 sec.SecOffset + let reader = reader.SubReader offset size + parseLSDA cls reader sec.SecAddr 0 [] + | None -> [] diff --git a/src/BinFile/ELFHeader.fs b/src/FrontEnd/BinFile/ELFHeader.fs similarity index 88% rename from src/BinFile/ELFHeader.fs rename to src/FrontEnd/BinFile/ELFHeader.fs index 4dab3859..caa6807a 100644 --- a/src/BinFile/ELFHeader.fs +++ b/src/FrontEnd/BinFile/ELFHeader.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.BinFile.ELF.Header +module internal B2R2.FrontEnd.BinFile.ELF.Header open System open B2R2 -open B2R2.BinFile.FileHelper +open B2R2.FrontEnd.BinFile.FileHelper let private elfMagicNumber = [| 0x7fuy; 0x45uy; 0x4cuy; 0x46uy |] @@ -78,17 +78,24 @@ let peekArch (reader: BinReader) cls offset = | 0xB7s -> Arch.AARCH64 | 0x08s | 0x0as -> getMIPSISA reader cls offset + | 0x53s -> Arch.AVR | _ -> Arch.UnknownISA +let computeNewBaseAddr ftype baseAddr = + match ftype with + | ELFFileType.Executable -> 0UL (* Non-pie executable must have zero base. *) + | _ -> defaultArg baseAddr 0UL + let parse baseAddr offset (reader: BinReader) = let cls = peekClass reader offset - { - Class = cls + let ftype = peekELFFileType reader offset + let baseAddr = computeNewBaseAddr ftype baseAddr + { Class = cls Endian = peekEndianness reader offset Version = peekHeaderU32 reader cls offset 6 6 OSABI = offset + 7 |> reader.PeekByte |> LanguagePrimitives.EnumOfValue OSABIVersion = offset + 8 |> reader.PeekByte |> uint32 - ELFFileType = peekELFFileType reader offset + ELFFileType = ftype MachineType = peekArch reader cls offset EntryPoint = peekHeaderNative reader cls offset 24 24 + baseAddr PHdrTblOffset = peekHeaderNative reader cls offset 28 32 @@ -99,5 +106,4 @@ let parse baseAddr offset (reader: BinReader) = PHdrNum = peekHeaderU16 reader cls offset 44 56 SHdrEntrySize = peekHeaderU16 reader cls offset 46 58 SHdrNum = peekHeaderU16 reader cls offset 48 60 - SHdrStrIdx = peekHeaderU16 reader cls offset 50 62 - } + SHdrStrIdx = peekHeaderU16 reader cls offset 50 62 }, baseAddr diff --git a/src/BinFile/ELFHelper.fs b/src/FrontEnd/BinFile/ELFHelper.fs similarity index 77% rename from src/BinFile/ELFHelper.fs rename to src/FrontEnd/BinFile/ELFHelper.fs index 00709ce4..64faf435 100644 --- a/src/BinFile/ELFHelper.fs +++ b/src/FrontEnd/BinFile/ELFHelper.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.BinFile.ELF.Helper +module internal B2R2.FrontEnd.BinFile.ELF.Helper open System open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile let [] secText = ".text" @@ -49,14 +49,6 @@ let isRelocatable elf = && Section.getDynamicSectionEntries elf.BinReader elf.SecInfo |> List.exists pred -let getBaseAddr (elf: ELF) = - let lowestPH = - elf.ProgHeaders - |> List.filter (fun ph -> ph.PHType = ProgramHeaderType.PTLoad) - |> List.filter(fun ph -> ph.PHFileSize > 0UL && ph.PHMemSize > 0UL) - |> List.minBy (fun ph -> ph.PHAddr) - lowestPH.PHAddr - let inline getTextStartAddr elf = (Map.find secText elf.SecInfo.SecByName).SecAddr @@ -87,12 +79,12 @@ let translateAddr addr elf = let isFuncSymb s = s.SymType = SymbolType.STTFunc || s.SymType = SymbolType.STTGNUIFunc -let inline tryFindFuncSymb elf addr (name: byref) = +let inline tryFindFuncSymb elf addr = match Map.tryFind addr elf.SymInfo.AddrToSymbTable with - | None -> false + | None -> Error ErrorCase.SymbolNotFound | Some s -> - if isFuncSymb s then name <- s.SymName; true - else false + if isFuncSymb s then Ok s.SymName + else Error ErrorCase.SymbolNotFound let getStaticSymbols elf = Symbol.getStaticSymArray elf @@ -126,18 +118,19 @@ let getRelocSymbols elf = |> Map.toSeq |> Seq.choose translate -let secFlagToSectionKind flag entrySize = - if flag &&& SectionFlag.SHFExecInstr = SectionFlag.SHFExecInstr then - if entrySize > 0UL then SectionKind.LinkageTableSection +let secFlagToSectionKind sec = + if sec.SecFlags &&& SectionFlag.SHFExecInstr = SectionFlag.SHFExecInstr then + if PLT.isPLTSectionName sec.SecName then SectionKind.LinkageTableSection else SectionKind.ExecutableSection - elif flag &&& SectionFlag.SHFWrite = SectionFlag.SHFWrite then + elif sec.SecFlags &&& SectionFlag.SHFWrite = SectionFlag.SHFWrite then SectionKind.WritableSection else SectionKind.ExtraSection let elfSectionToSection sec = { Address = sec.SecAddr - Kind = secFlagToSectionKind sec.SecFlags sec.SecEntrySize + FileOffset = sec.SecOffset + Kind = secFlagToSectionKind sec Size = sec.SecSize Name = sec.SecName } @@ -180,7 +173,7 @@ let getPLT elf = |> List.sortBy (fun entry -> entry.TrampolineAddress) |> List.toSeq -let isPLT elf addr = +let isInPLT elf addr = ARMap.containsAddr addr elf.PLT let inline isValidAddr elf addr = @@ -203,13 +196,37 @@ let getNotInFileIntervals elf range = |> List.map (FileHelper.trimByRange range) |> List.toSeq -let getFunctionAddrs elf addrs = - let addrSet = Set.ofSeq addrs - elf.ExceptionFrame - |> List.fold (fun set cfi -> - cfi.FDERecord - |> Array.fold (fun set fde -> - Set.add fde.PCBegin set - ) set +let getFunctionAddrsFromLibcArray elf s = + let offset = int s.SecOffset + let entrySize = int s.SecEntrySize + let readType: WordSize = LanguagePrimitives.EnumOfValue (entrySize * 8) + let size = int s.SecSize + if entrySize = 0 then Seq.empty + else + [| offset .. entrySize .. offset + size - entrySize |] + |> Array.map (FileHelper.peekUIntOfType elf.BinReader readType) + |> Seq.ofArray + +let getAddrsFromInitArray elf = + match Map.tryFind ".init_array" elf.SecInfo.SecByName with + | Some s -> getFunctionAddrsFromLibcArray elf s + | None -> Seq.empty + +let getAddrsFromFiniArray elf = + match Map.tryFind ".fini_array" elf.SecInfo.SecByName with + | Some s -> getFunctionAddrsFromLibcArray elf s + | None -> Seq.empty + +let addExtraFunctionAddrs elf useExceptionInfo addrs = + let addrSet = + [ addrs; getAddrsFromInitArray elf; getAddrsFromFiniArray elf ] + |> Seq.concat + |> Set.ofSeq + if useExceptionInfo then (* XXX *) + elf.ExceptionFrame + |> List.fold (fun set cfi -> + cfi.FDERecord + |> Array.fold (fun set fde -> Set.add fde.PCBegin set) set ) addrSet - |> Set.toSeq + |> Set.toSeq + else addrSet |> Set.toSeq diff --git a/src/FrontEnd/BinFile/ELFPLT.fs b/src/FrontEnd/BinFile/ELFPLT.fs new file mode 100644 index 00000000..87c19bf5 --- /dev/null +++ b/src/FrontEnd/BinFile/ELFPLT.fs @@ -0,0 +1,371 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinFile.ELF.PLT + +open System +open B2R2 +open B2R2.Monads.OrElse + +type CodeKind = + | PIC + | NonPIC + | DontCare + +type PLTLinkMethod = + | LazyBinding + | EagerBinding + +type PLTEntryInfo = { + EntryRelocAddr: Addr + NextEntryAddr: Addr +} + +type PLTDescriptor = { + /// PLT start address. + StartAddr: Addr + /// PIC or non-PIC. + CodeKind: CodeKind + /// Lazy vs. Non-lazy (eager) binding. + LinkMethod: PLTLinkMethod + /// Is secondary PLT? + IsSecondary: bool + /// Entry size of the PLT. + EntrySize: int + /// Offset from a start of a PLT entry to the index to the GOT. + GOTOffset: Addr + /// Size of the instruction that refers to the GOT. + InstrSize: Addr + /// Compute a EntryInfo from (Entry index, current entry address, + /// PLTDescriptor, BinReader, gotBaseAddr). Each PLT has its own getter. + InfoGetter: + Addr + -> int + -> PLTDescriptor + -> BinReader + -> ELFSection + -> Addr + -> Result +} + +type PLTType = + /// The regular PLT. + | PLT of desc: PLTDescriptor + /// The PLT pattern is unknown. + | UnknownPLT + +let newPLT start kind lm isSecondary size gotoff inslen getter = + PLT { StartAddr = start + CodeKind = kind + LinkMethod = lm + IsSecondary = isSecondary + EntrySize = size + GOTOffset = gotoff + InstrSize = inslen + InfoGetter = getter } + +let isPLTSectionName name = + name = ".plt" || name = ".plt.sec" || name = ".plt.got" || name = ".plt.bnd" + +let isSecondaryLazy desc = + desc.IsSecondary && desc.LinkMethod = LazyBinding + +let gotAddr sections = + match Map.tryFind ".got.plt" sections.SecByName with + | Some s -> Some s.SecAddr + | None -> + match Map.tryFind ".got" sections.SecByName with + | Some s -> Some s.SecAddr + | None -> None + +let findFirstPLTGOTAddr reloc sections = + match Map.tryFind ".rel.plt" sections.SecByName with + | Some s -> + reloc.RelocByAddr + |> Map.fold (fun minval addr r -> + if r.RelSecNumber = s.SecNum then + if r.RelOffset < minval then r.RelOffset else minval + else minval) UInt64.MaxValue + | None -> 0UL + +let findFirstJumpSlot reloc sections = + reloc.RelocByAddr + |> Map.fold (fun minval addr r -> + match r.RelType with + | RelocationARMv8 RelocationARMv8.RelocAARCH64JmpSlot -> + if r.RelOffset < minval then r.RelOffset else minval + | _ -> minval) UInt64.MaxValue + +let findGOTBase arch reloc sections = + let got = gotAddr sections + match arch with + | Arch.IntelX86 + | Arch.IntelX64 -> got + | Arch.ARMv7 + | Arch.AARCH32 -> + got |> Option.map (fun _ -> findFirstPLTGOTAddr reloc sections) + | Arch.AARCH64 -> + got |> Option.map (fun _ -> findFirstJumpSlot reloc sections) + | _ -> got + +let filterPLTSections sections = + sections.SecByName |> Map.fold (fun acc _ s -> + if isPLTSectionName s.SecName then s :: acc else acc) [] + |> List.rev (* .plt, .plt.got, .plt.sec *) + +let x86NonPICGetter addr _idx typ (reader: BinReader) sec _gotBase = + let addrDiff = int (addr - typ.StartAddr) + let offset = addrDiff + int typ.GOTOffset + int sec.SecOffset + { EntryRelocAddr = reader.PeekInt32 offset |> uint64 + NextEntryAddr = addr + uint64 typ.EntrySize } |> Ok + +let x86PICGetter addr _idx typ (reader: BinReader) sec gotBase = + let addrDiff = int (addr - typ.StartAddr) + let offset = addrDiff + int typ.GOTOffset + int sec.SecOffset + { EntryRelocAddr = (reader.PeekInt32 offset |> uint64) + gotBase + NextEntryAddr = addr + uint64 typ.EntrySize } |> Ok + +let x86PICLazy (reader: BinReader) sec = + let plt = reader.PeekSpan (int sec.SecSize, int sec.SecOffset) + let zeroEntry = (* push indirect addr; jmp; *) + [| OneByte 0xffuy; OneByte 0xb3uy; OneByte 0x04uy; AnyByte; AnyByte; AnyByte + OneByte 0xffuy; OneByte 0xa3uy; OneByte 0x08uy; AnyByte; AnyByte; AnyByte + |] + let ibtEntry = (* (Ind-Branch-Tracking) endbr32; push; jmp rel; *) + [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfbuy; + OneByte 0x68uy; AnyByte; AnyByte; AnyByte; AnyByte + OneByte 0xe9uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte |] + if BytePattern.matchSpan zeroEntry plt then + let isIBT = BytePattern.matchSpan ibtEntry (plt.Slice 16) + let gotoff = if isIBT then 6UL else 2UL + newPLT sec.SecAddr PIC LazyBinding isIBT 16 gotoff 0UL x86PICGetter |> Some + else None + +let x86NonPICLazy (reader: BinReader) sec = + let plt = reader.PeekSpan (int sec.SecSize, int sec.SecOffset) + let zeroEntry = (* push absolute addr; jmp; *) + [| OneByte 0xffuy; OneByte 0x35uy; AnyByte; AnyByte; AnyByte; AnyByte + OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte |] + let ibtEntry = (* (Ind-Branch-Tracking) endbr32; jmp got; *) + [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfbuy; + OneByte 0x68uy; AnyByte; AnyByte; AnyByte; AnyByte + OneByte 0xe9uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte |] + if BytePattern.matchSpan zeroEntry plt then + let isIBT = BytePattern.matchSpan ibtEntry (plt.Slice 16) + let gotoff = if isIBT then 6UL else 2UL + newPLT sec.SecAddr NonPIC LazyBinding isIBT 16 gotoff 0UL x86NonPICGetter + |> Some + else None + +let x86PICNonLazy (reader: BinReader) sec = + let plt = reader.PeekSpan (int sec.SecSize, int sec.SecOffset) + let entry = (* jmp indirect addr; nop *) + [| OneByte 0xffuy; OneByte 0xa3uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte |] + let ibtEntry = (* endbr32; jmp got; *) + [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfbuy + OneByte 0xffuy; OneByte 0xa3uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte; AnyByte; AnyByte; AnyByte; AnyByte |] + if BytePattern.matchSpan entry plt then + newPLT sec.SecAddr PIC EagerBinding false 8 2UL 0UL x86PICGetter |> Some + elif BytePattern.matchSpan ibtEntry plt then + newPLT sec.SecAddr PIC EagerBinding true 8 6UL 0UL x86PICGetter |> Some + else None + +let x86NonPICNonLazy (reader: BinReader) sec = + let plt = reader.PeekSpan (int sec.SecSize, int sec.SecOffset) + let entry = (* jmp indirect addr; nop *) + [| OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte |] + let ibtEntry = (* endbr32; jmp got; *) + [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfbuy + OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte; AnyByte; AnyByte; AnyByte; AnyByte |] + if BytePattern.matchSpan entry plt then + newPLT sec.SecAddr NonPIC EagerBinding false 8 2UL 0UL x86NonPICGetter + |> Some + elif BytePattern.matchSpan ibtEntry plt then + newPLT sec.SecAddr NonPIC EagerBinding true 8 6UL 0UL x86NonPICGetter + |> Some + else None + +let x64Getter addr _idx typ (reader: BinReader) sec _gotBase = + let addrDiff = int (addr - typ.StartAddr) + let offset = addrDiff + int typ.GOTOffset + int sec.SecOffset + let v = reader.PeekInt32 offset + { EntryRelocAddr = addr + typ.InstrSize + uint64 v + NextEntryAddr = addr + uint64 typ.EntrySize } |> Ok + +let x64Lazy (reader: BinReader) sec = + let plt = reader.PeekSpan (int sec.SecSize, int sec.SecOffset) + let zeroEntry = (* push [got+8]; jmp [got+16]; *) + [| OneByte 0xffuy; OneByte 0x35uy; AnyByte; AnyByte; AnyByte; AnyByte + OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte |] + let ibtZeroEntry = (* (Ind-Branch-Tracking) push [got+8]; bnd jmp [got+16]; *) + [| OneByte 0xffuy; OneByte 0x35uy; AnyByte; AnyByte; AnyByte; AnyByte + OneByte 0xf2uy; OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte + AnyByte; AnyByte |] + let ibtEntry = (* endbr64; push imm; bnd jmp rel; *) + [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfauy + OneByte 0x68uy; AnyByte; AnyByte; AnyByte; AnyByte + OneByte 0xf2uy; OneByte 0xe9uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte |] + if BytePattern.matchSpan zeroEntry plt then + newPLT sec.SecAddr DontCare LazyBinding false 16 2UL 6UL x64Getter |> Some + elif BytePattern.matchSpan ibtZeroEntry plt then + let off, inssz = + if BytePattern.matchSpan ibtEntry (plt.Slice 16) then 7UL, 11UL + else 3UL, 7UL (* bnd *) + newPLT sec.SecAddr DontCare LazyBinding true 16 off inssz x64Getter |> Some + else None + +let x64NonLazy (reader: BinReader) sec = + let plt = reader.PeekSpan (int sec.SecSize, int sec.SecOffset) + let entry = (* jmp [got+16]; *) + [| OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte |] + if BytePattern.matchSpan entry plt then + newPLT sec.SecAddr DontCare EagerBinding false 8 2UL 6UL x64Getter |> Some + else None + +let x64IBT (reader: BinReader) sec = + let plt = reader.PeekSpan (int sec.SecSize, int sec.SecOffset) + let bndEntry = (* bnd jmp [got+n]] *) + [| OneByte 0xf2uy; OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte |] + let ibtEntry = (* endbr64; bnd jmp [got+n]] *) + [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfauy + OneByte 0xf2uy; OneByte 0xffuy; OneByte 0x25uy; + AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte; AnyByte; AnyByte; AnyByte |] + if BytePattern.matchSpan bndEntry plt then + newPLT sec.SecAddr DontCare EagerBinding true 16 3UL 7UL x64Getter |> Some + elif BytePattern.matchSpan ibtEntry plt then + newPLT sec.SecAddr DontCare EagerBinding true 16 7UL 11UL x64Getter |> Some + else None + +let computeARMPLTEntrySize (reader: BinReader) sec headerSize delta = + if reader.PeekInt32 (int sec.SecOffset) = 0xf8dfb500 then (* THUMB-only *) + Ok 16 + else + let offset = int sec.SecOffset + int headerSize + delta + let size = if reader.PeekInt16 offset = 0x4778s then 4 else 0 + let offset = offset + size + let ins = reader.PeekInt32 offset &&& 0xffffff00 (* strip immediate *) + if (headerSize = 16UL && ins = 0xe28fc600) || ins = 0xe28fc200 then + Ok (size + 16) + elif ins = 0xe28fc600 then Ok (size + 12) + else Error ErrorCase.InvalidFileFormat + +/// Get the size of the header of PLT (PLT Zero) +let computeARMPLTHeaderSize (reader: BinReader) sec = + let v = reader.PeekInt32 (int sec.SecOffset) + if v = 0xe52de004 then (* str lr, [sp, #-4] *) + let v = reader.PeekInt32 (int sec.SecOffset + 16) + if v = 0xe28fc600 then (* add ip, pc, #0, 12 *) Some 16UL + else Some 20UL + elif v = 0xf8dfb500 then (* push {lr} *) Some 16UL + else None + +let armv7Getter addr idx typ reader sec gotBase = + let addrDiff = int (addr - typ.StartAddr) + let hdrSize = computeARMPLTHeaderSize reader sec |> Option.get + match computeARMPLTEntrySize reader sec hdrSize addrDiff with + | Ok entSize -> + { EntryRelocAddr = gotBase + uint64 (idx * 4) + NextEntryAddr = addr + uint64 entSize } |> Ok + | Error _ -> (* Just ignore this entry using the default entry size 16. *) + { EntryRelocAddr = 0UL; NextEntryAddr = addr + 16UL } |> Ok + +let armv7PLT reader sec = + match computeARMPLTHeaderSize reader sec with + | Some headerSize -> + let startAddr = sec.SecAddr + headerSize + if reader.PeekInt32 (int sec.SecOffset) = 0xf8dfb500 then (* push {lr} *) + newPLT startAddr DontCare LazyBinding false 16 4UL 4UL armv7Getter + else + match computeARMPLTEntrySize reader sec headerSize 0 with + | Ok sz -> + newPLT startAddr DontCare LazyBinding false sz 4UL 4UL armv7Getter + | Error _ -> UnknownPLT + | None -> UnknownPLT + +let aarch64Getter addr idx _typ _reader _sec gotBase = + { EntryRelocAddr = gotBase + uint64 (idx * 8) + NextEntryAddr = addr + 16UL } |> Ok + +let aarchPLT _reader sec = + let startAddr = sec.SecAddr + 32UL + newPLT startAddr DontCare LazyBinding false 16 0UL 4UL aarch64Getter + +let findPLTType arch reader sec = + match arch with + | Arch.IntelX86 -> + orElse { + yield! x86PICLazy reader sec + yield! x86NonPICLazy reader sec + yield! x86PICNonLazy reader sec + yield! x86NonPICNonLazy reader sec + } |> Option.defaultValue UnknownPLT + | Arch.IntelX64 -> + orElse { + yield! x64Lazy reader sec + yield! x64NonLazy reader sec + yield! x64IBT reader sec + } |> Option.defaultValue UnknownPLT + | Arch.ARMv7 + | Arch.AARCH32 -> armv7PLT reader sec + | Arch.AARCH64 -> aarchPLT reader sec + | _ -> Utils.futureFeature () + +let private parsePLT gotBase typ reloc (reader: BinReader) (s: ELFSection) map = + let startAddr, endAddr = typ.StartAddr, s.SecAddr + s.SecSize + let rec parseLoop idx map addr = + if addr >= endAddr then map + else + let info = typ.InfoGetter addr idx typ reader s gotBase |> Result.get + // printfn "%x -> %x" addr info.EntryRelocAddr + let nextAddr = info.NextEntryAddr + let ar = AddrRange (addr, nextAddr - 1UL) + match Map.tryFind info.EntryRelocAddr reloc.RelocByAddr with + | Some r when r.RelSymbol.IsSome -> + let symb = Option.get r.RelSymbol + let symb = { symb with Addr = r.RelOffset } + let map = ARMap.add ar symb map + parseLoop (idx + 1) map nextAddr + | _ -> parseLoop (idx + 1) map nextAddr + parseLoop 0 map startAddr + +let parse arch sections reloc (reader: BinReader) = + let gotBase = findGOTBase arch reloc sections + filterPLTSections sections + |> List.fold (fun map s -> + match gotBase, findPLTType arch reader s with + | Some gotBase, PLT desc -> + if isSecondaryLazy desc then map (* Ignore secondary lazy plt. *) + else parsePLT gotBase desc reloc reader s map + | _, _ -> map + ) ARMap.empty diff --git a/src/BinFile/ELFParser.fs b/src/FrontEnd/BinFile/ELFParser.fs similarity index 55% rename from src/BinFile/ELFParser.fs rename to src/FrontEnd/BinFile/ELFParser.fs index 53d7c944..1dd47a14 100644 --- a/src/BinFile/ELFParser.fs +++ b/src/FrontEnd/BinFile/ELFParser.fs @@ -22,51 +22,10 @@ SOFTWARE. *) -module internal B2R2.BinFile.ELF.Parser +module internal B2R2.FrontEnd.BinFile.ELF.Parser -open System open B2R2 -open B2R2.BinFile - -let pltSkipBytes = function - | Arch.IntelX86 - | Arch.IntelX64 -> 0x10UL - | Arch.ARMv7 -> 0x14UL - | Arch.AARCH64 -> 0x20UL - | _ -> Utils.futureFeature () - -let isThumbPltELFSymbol sAddr (plt: ELFSection) (reader: BinReader) = - let offset = Convert.ToInt32 (sAddr - plt.SecAddr + plt.SecOffset) - let pltThumbStubBytes = ReadOnlySpan [| 0x78uy; 0x47uy; 0xc0uy; 0x46uy |] - let span = reader.PeekSpan (4, offset) - span.SequenceEqual pltThumbStubBytes - -let findPltSize sAddr plt reader = function - | Arch.IntelX86 - | Arch.IntelX64 -> 0x10UL - | Arch.ARMv7 -> - if isThumbPltELFSymbol sAddr plt reader then 0x10UL else 0x0CUL - | Arch.AARCH64 -> 0x10UL - | _ -> failwith "Implement" - -let parsePLT arch sections (reloc: RelocInfo) reader = - match Map.tryFind ".plt" sections.SecByName with - | Some plt -> - let pltStartAddr = plt.SecAddr + pltSkipBytes arch - let folder (map, sAddr) _ (rel: RelocationEntry) = - match rel.RelType with - | RelocationX86 RelocationX86.Reloc386JmpSlot - | RelocationX64 RelocationX64.RelocX64JmpSlot - | RelocationARMv7 RelocationARMv7.RelocARMJmpSlot - | RelocationARMv8 RelocationARMv8.RelocAARCH64JmpSlot -> - let nextStartAddr = sAddr + findPltSize sAddr plt reader arch - let addrRange = AddrRange (sAddr, nextStartAddr) - let symb = Option.get rel.RelSymbol - let symb = { symb with Addr = rel.RelOffset } - ARMap.add addrRange symb map, nextStartAddr - | _ -> map, sAddr - Map.fold folder (ARMap.empty, pltStartAddr) reloc.RelocByAddr |> fst - | None -> ARMap.empty +open B2R2.FrontEnd.BinFile let parseGlobalSymbols reloc = let folder map addr (rel: RelocationEntry) = @@ -77,6 +36,51 @@ let parseGlobalSymbols reloc = | _ -> map reloc.RelocByAddr |> Map.fold folder Map.empty +let rec loadCallSiteTable lsdaPointer = function + | [] -> [] + | lsda :: rest -> + if lsdaPointer = lsda.LSDAAddr then lsda.CallSiteTable + else loadCallSiteTable lsdaPointer rest + +let rec loopCallSiteTable fde acc = function + | [] -> acc + | rcrd :: rest -> + let acc = + let landingPad = + if rcrd.LandingPad = uint64 0 then rcrd.LandingPad + else fde.PCBegin + rcrd.LandingPad + let blockStart = fde.PCBegin + rcrd.Position + let blockEnd = fde.PCBegin + rcrd.Position + rcrd.Length - 1UL + ARMap.add (AddrRange (blockStart, blockEnd)) landingPad acc + loopCallSiteTable fde acc rest + +let buildExceptionTable fde gccexctbl tbl = + match fde.LSDAPointer with + | None -> tbl + | Some lsdaPointer -> + loopCallSiteTable fde tbl (loadCallSiteTable lsdaPointer gccexctbl) + +let accumulateExceptionTableInfo fde gccexctbl map = + fde + |> Array.fold (fun map fde -> + let functionRange = AddrRange (fde.PCBegin, fde.PCEnd - 1UL) + let exceptTable = buildExceptionTable fde gccexctbl ARMap.empty + if ARMap.isEmpty exceptTable then map + else ARMap.add functionRange exceptTable map) map + +let computeExceptionTable excframes gccexctbl = + excframes + |> List.fold (fun map frame -> + accumulateExceptionTableInfo frame.FDERecord gccexctbl map) ARMap.empty + +let computeUnwindingTable excframes = + excframes + |> List.fold (fun tbl (f: CallFrameInformation) -> + f.FDERecord |> Array.fold (fun tbl fde -> + fde.UnwindingInfo |> List.fold (fun tbl i -> + Map.add i.Location i tbl) tbl + ) tbl) Map.empty + let invRanges wordSize segs getNextStartAddr = segs |> List.sortBy (fun seg -> seg.PHAddr) @@ -89,12 +93,13 @@ let execRanges segs = segs |> List.filter (fun seg -> seg.PHFlags &&& Permission.Executable = Permission.Executable) - |> List.fold (fun set seg -> - IntervalSet.add (AddrRange (seg.PHAddr, seg.PHAddr + seg.PHMemSize)) set + |> List.fold (fun set s -> + IntervalSet.add (AddrRange (s.PHAddr, s.PHAddr + s.PHMemSize - 1UL)) set ) IntervalSet.empty -let private parseELF baseAddr offset reader = - let eHdr = Header.parse baseAddr offset reader +let private parseELF baseAddr regbay offset reader = + let eHdr, baseAddr = Header.parse baseAddr offset reader + let isa = ISA.Init eHdr.MachineType eHdr.Endian let cls = eHdr.Class let secs = Section.parse baseAddr eHdr reader let proghdrs = ProgHeader.parse baseAddr eHdr reader @@ -102,10 +107,15 @@ let private parseELF baseAddr offset reader = let loadableSecNums = ProgHeader.getLoadableSecNums secs segs let symbs = Symbol.parse baseAddr eHdr secs reader let reloc = Relocs.parse baseAddr eHdr secs symbs reader - let plt = parsePLT eHdr.MachineType secs reloc reader + let plt = PLT.parse eHdr.MachineType secs reloc reader let globals = parseGlobalSymbols reloc let symbs = Symbol.updatePLTSymbols plt symbs |> Symbol.updateGlobals globals + let excframes = ExceptionFrames.parse reader cls secs isa regbay + let lsdas = ELFGccExceptTable.parse reader cls secs + let exctbls = computeExceptionTable excframes lsdas + let unwindings = computeUnwindingTable excframes { ELFHdr = eHdr + BaseAddr = baseAddr ProgHeaders = proghdrs LoadableSegments = segs LoadableSecNums = loadableSecNums @@ -114,16 +124,20 @@ let private parseELF baseAddr offset reader = RelocInfo = reloc PLT = plt Globals = globals - ExceptionFrame = ExceptionFrames.parse reader cls secs + ExceptionFrame = excframes + ExceptionTable = exctbls + LSDAs = lsdas InvalidAddrRanges = invRanges cls segs (fun s -> s.PHAddr + s.PHMemSize) NotInFileRanges = invRanges cls segs (fun s -> s.PHAddr + s.PHFileSize) ExecutableRanges = execRanges segs - BinReader = reader } + BinReader = reader + ISA = isa + UnwindingTbl = unwindings } -let parse baseAddr bytes = +let parse bytes baseAddr regbay = let reader = BinReader.Init (bytes, Endian.Little) if Header.isELF reader 0 then () else raise FileFormatMismatchException Header.peekEndianness reader 0 |> BinReader.RenewReader reader - |> parseELF baseAddr 0 + |> parseELF baseAddr regbay 0 diff --git a/src/BinFile/ELFProgHeader.fs b/src/FrontEnd/BinFile/ELFProgHeader.fs similarity index 96% rename from src/BinFile/ELFProgHeader.fs rename to src/FrontEnd/BinFile/ELFProgHeader.fs index 3b371601..caf65e17 100644 --- a/src/BinFile/ELFProgHeader.fs +++ b/src/FrontEnd/BinFile/ELFProgHeader.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -module internal B2R2.BinFile.ELF.ProgHeader +module internal B2R2.FrontEnd.BinFile.ELF.ProgHeader open System open B2R2 -open B2R2.BinFile -open B2R2.BinFile.FileHelper +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper let peekPHdrFlags (reader: BinReader) cls offset = let pHdrPHdrFlagsOffset = if cls = WordSize.Bit32 then 24 else 4 diff --git a/src/BinFile/ELFRelocs.fs b/src/FrontEnd/BinFile/ELFRelocs.fs similarity index 97% rename from src/BinFile/ELFRelocs.fs rename to src/FrontEnd/BinFile/ELFRelocs.fs index 8e2f21d6..523810a6 100644 --- a/src/BinFile/ELFRelocs.fs +++ b/src/FrontEnd/BinFile/ELFRelocs.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.BinFile.ELF.Relocs +module internal B2R2.FrontEnd.BinFile.ELF.Relocs open System open B2R2 -open B2R2.BinFile.FileHelper +open B2R2.FrontEnd.BinFile.FileHelper let peekInfoWithArch reader eHdr offset = let info = peekHeaderNative reader eHdr.Class offset 4 8 diff --git a/src/BinFile/ELFSection.fs b/src/FrontEnd/BinFile/ELFSection.fs similarity index 97% rename from src/BinFile/ELFSection.fs rename to src/FrontEnd/BinFile/ELFSection.fs index d8467c89..1fa9c940 100644 --- a/src/BinFile/ELFSection.fs +++ b/src/FrontEnd/BinFile/ELFSection.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.BinFile.ELF.Section +module internal B2R2.FrontEnd.BinFile.ELF.Section open System open B2R2 -open B2R2.BinFile.FileHelper +open B2R2.FrontEnd.BinFile.FileHelper /// Return the raw memory contents that represent the section names separated by /// null character. @@ -78,7 +78,7 @@ let secHasValidAddr baseAddr sec = let addSecToAddrMap baseAddr sec map = if secHasValidAddr baseAddr sec then - let endAddr = sec.SecAddr + sec.SecSize + let endAddr = sec.SecAddr + sec.SecSize - 1UL ARMap.addRange sec.SecAddr endAddr sec map else map diff --git a/src/BinFile/ELFSymbol.fs b/src/FrontEnd/BinFile/ELFSymbol.fs similarity index 86% rename from src/BinFile/ELFSymbol.fs rename to src/FrontEnd/BinFile/ELFSymbol.fs index 788f467e..9daa9090 100644 --- a/src/BinFile/ELFSymbol.fs +++ b/src/FrontEnd/BinFile/ELFSymbol.fs @@ -22,13 +22,13 @@ SOFTWARE. *) -module internal B2R2.BinFile.ELF.Symbol +module internal B2R2.FrontEnd.BinFile.ELF.Symbol open System open B2R2 open B2R2.Monads.Maybe -open B2R2.BinFile -open B2R2.BinFile.FileHelper +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper let getSymbKind ndx = function | SymbolType.STTObject -> SymbolKind.ObjectType @@ -50,7 +50,8 @@ let toB2R2Symbol target (symb: ELFSymbol) = Name = symb.SymName Kind = getSymbKind symb.SecHeaderIndex symb.SymType Target = target - LibraryName = versionToLibName symb.VerInfo } + LibraryName = versionToLibName symb.VerInfo + ArchOperationMode = symb.ArchOperationMode } let verName (strTab: ReadOnlySpan) vnaNameOffset = if vnaNameOffset >= strTab.Length then "" @@ -136,8 +137,19 @@ let readSymSize (reader: BinReader) cls offset = let symSizeOffset = if cls = WordSize.Bit32 then 8 else 16 offset + symSizeOffset |> peekUIntOfType reader cls -let symb baseAddr secs strTab vtbl cls reader txt symIdx pos = +let computeArchOpMode eHdr symbolName = + if eHdr.MachineType = Architecture.ARMv7 + || eHdr.MachineType = Architecture.AARCH32 + then + if symbolName = "$a" then ArchOperationMode.ARMMode + elif symbolName = "$t" then ArchOperationMode.ThumbMode + else ArchOperationMode.NoMode + else ArchOperationMode.NoMode + +let getSymbol baseAddr secs strTab vtbl eHdr reader txt symIdx pos = + let cls = eHdr.Class let nameIdx = (reader: BinReader).PeekUInt32 pos + let sname = ByteArray.extractCStringFromSpan strTab (Convert.ToInt32 nameIdx) let info = peekHeaderB reader cls pos 12 4 let other = peekHeaderB reader cls pos 13 5 let ndx = peekHeaderU16 reader cls pos 14 6 |> int @@ -146,38 +158,40 @@ let symb baseAddr secs strTab vtbl cls reader txt symIdx pos = let vssec = secs.VerSymSec let verInfo = vssec >>= parseVersData reader symIdx >>= retrieveVer vtbl { Addr = readSymAddr baseAddr reader cls parent txt pos - SymName = ByteArray.extractCStringFromSpan strTab (Convert.ToInt32 nameIdx) + SymName = sname Size = readSymSize reader cls pos Bind = info >>> 4 |> LanguagePrimitives.EnumOfValue SymType = info &&& 0xfuy |> LanguagePrimitives.EnumOfValue Vis = other &&& 0x3uy |> LanguagePrimitives.EnumOfValue SecHeaderIndex = secIdx ParentSection = parent - VerInfo = verInfo } + VerInfo = verInfo + ArchOperationMode = computeArchOpMode eHdr sname } let getVerSymSection symTblSec secByType = if symTblSec.SecType = SectionType.SHTDynSym then Map.tryFind SectionType.SHTGNUVerSym secByType else None -let nextSymOffset cls offset = - offset + if cls = WordSize.Bit32 then 16 else 24 +let nextSymOffset eHdr offset = + offset + if eHdr.Class = WordSize.Bit32 then 16 else 24 let getTextSectionOffset secs = match Map.tryFind ".text" secs.SecByName with | None -> 0UL | Some sec -> sec.SecOffset -let rec parseSymLoop baseAddr cls secs reader txt vtbl stbl cnt max offset acc = +let rec parseSymAux baseAddr eHdr secs reader txt vtbl stbl cnt max offset acc = if cnt = max then List.rev acc else - let sym = symb baseAddr secs stbl vtbl cls reader txt cnt offset + let sym = getSymbol baseAddr secs stbl vtbl eHdr reader txt cnt offset let cnt = cnt + 1UL - let offset = nextSymOffset cls offset + let offset = nextSymOffset eHdr offset let acc = sym :: acc - parseSymLoop baseAddr cls secs reader txt vtbl stbl cnt max offset acc + parseSymAux baseAddr eHdr secs reader txt vtbl stbl cnt max offset acc -let parseSymbols baseAddr cls secs (reader: BinReader) vtbl acc symTblSec = +let parseSymbols baseAddr eHdr secs (reader: BinReader) vtbl acc symTblSec = + let cls = eHdr.Class let ss = secs.SecByNum.[Convert.ToInt32 symTblSec.SecLink] (* Get the sec. *) let size = Convert.ToInt32 ss.SecSize let offset = Convert.ToInt32 ss.SecOffset @@ -185,7 +199,7 @@ let parseSymbols baseAddr cls secs (reader: BinReader) vtbl acc symTblSec = let txt = getTextSectionOffset secs let stbl = reader.PeekSpan (size, offset) (* Get the str table *) let offset = Convert.ToInt32 symTblSec.SecOffset - parseSymLoop baseAddr cls secs reader txt vtbl stbl 0UL max offset acc + parseSymAux baseAddr eHdr secs reader txt vtbl stbl 0UL max offset acc let getMergedSymbolTbl numbers symTbls = numbers @@ -211,12 +225,11 @@ let buildSymbolMap staticSymArr dynamicSymArr = dynamicSymArr |> Array.fold folder map let parse baseAddr eHdr secs reader = - let cls = eHdr.Class let vtbl = parseVersionTable secs reader let symTabNumbers = List.append secs.StaticSymSecNums secs.DynSymSecNums let getSymTables sec = List.fold (fun map (n, symTblSec) -> - let symbols = parseSymbols baseAddr cls secs reader vtbl [] symTblSec + let symbols = parseSymbols baseAddr eHdr secs reader vtbl [] symTblSec Map.add n (Array.ofList symbols) map) Map.empty sec let symTbls = List.map (fun n -> n, secs.SecByNum.[n]) symTabNumbers |> getSymTables diff --git a/src/BinFile/ELFTypes.fs b/src/FrontEnd/BinFile/ELFTypes.fs similarity index 92% rename from src/BinFile/ELFTypes.fs rename to src/FrontEnd/BinFile/ELFTypes.fs index 9247f190..f7ccc3ec 100644 --- a/src/BinFile/ELFTypes.fs +++ b/src/FrontEnd/BinFile/ELFTypes.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -namespace B2R2.BinFile.ELF +namespace B2R2.FrontEnd.BinFile.ELF open System open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile /// File type. type ELFFileType = @@ -36,6 +36,7 @@ type ELFFileType = | SharedObject = 0x3us | Core = 0x4us +/// ABI type. type OSABI = | ABISystemV = 0x0uy | ABIHPUX = 0x1uy @@ -425,6 +426,8 @@ type ELFSymbol = { ParentSection: ELFSection option /// Version information. VerInfo: SymVerInfo option + /// ArchOperationMode. + ArchOperationMode: ArchOperationMode } /// Relocation type for x86. @@ -679,7 +682,7 @@ with | Architecture.MIPS64R2 | Architecture.MIPS64R6 -> RelocationMIPS <| LanguagePrimitives.EnumOfValue n - | _ -> invalidArg "Architecture" "Unsupported architecture for relocation." + | _ -> invalidArg (nameof arch) "Unsupported architecture for relocation." /// Relocation entry. type RelocationEntry = { @@ -794,22 +797,76 @@ type ProgramHeader = { PHAlignment: uint64 } +/// Language Specific Data Area header. +type LSDAHeader = { + /// This is the value encoding of the landing pad pointer. + LPValueEncoding: ExceptionHeaderValue + /// This is the application encoding of the landing pad pointer. + LPAppEncoding: ExceptionHeaderApplication + /// The base of the landing pad pointers. + LPStart: Addr option + /// This is the value encoding of type table (TT). + TTValueEncoding: ExceptionHeaderValue + /// This is the application encoding of type table (TT). + TTAppEncoding: ExceptionHeaderApplication + /// The base of types table. + TTBase: Addr option + // This is the value encoding of the call site table. + CallSiteValueEncoding: ExceptionHeaderValue + // This is the application encoding of the call site table. + CallSiteAppEncoding: ExceptionHeaderApplication + // The size of call site table. + CallSiteTableSize: uint64 +} + +/// An entry in the callsite table of LSDA. +type CallSiteRecord = { + /// Offset of the callsite relative to the previous call site. + Position: uint64 + /// Size of the callsite instruction(s). + Length: uint64 + /// Offset of the landing pad. + LandingPad: uint64 + /// Offset to the action table. Zero means no action entry. + ActionOffset: int + /// Parsed list of type filters from the action table. + ActionTypeFilters: int64 list +} + +/// LSDA. Language Specific Data Area. +type LanguageSpecificDataArea = { + LSDAAddr: Addr + Header: LSDAHeader + CallSiteTable: CallSiteRecord list +} + +/// This tells how augmetation data is handled. +type Augmentation = { + Format: char + ValueEncoding: ExceptionHeaderValue + ApplicationEncoding: ExceptionHeaderApplication + PersonalityRoutionPointer: byte [] +} + /// CIE. Common Information Entry. type CommonInformationEntry = { Version: uint8 AugmentationString: string CodeAlignmentFactor: uint64 DataAlignmentFactor: int64 - ReturnAddressRegister: uint64 - AugmentationData: byte [] option - FDEEncoding: ExceptionHeaderValue - FDEApplication: ExceptionHeaderApplication + ReturnAddressRegister: byte + InitialRule: Rule + InitialCFARegister: byte + InitialCFA: CanonicalFrameAddress + Augmentations: Augmentation list } /// FDE. Frame Description Entry. type FrameDescriptionEntry = { PCBegin: Addr PCEnd: Addr + LSDAPointer: Addr option + UnwindingInfo: UnwindingEntry list } /// The main information block of .eh_frame. @@ -822,6 +879,8 @@ type CallFrameInformation = { type ELF = { /// ELF header. ELFHdr: ELFHeader + /// Preferred base address. + BaseAddr: Addr /// Segment information. ProgHeaders: ProgramHeader list /// Loadable segments. @@ -840,12 +899,20 @@ type ELF = { Globals: Map /// Exception frame. ExceptionFrame: CallFrameInformation list + /// Exception table. + ExceptionTable: ARMap> + /// List of LSDAs (Language Specific Data Areas). + LSDAs: LanguageSpecificDataArea list /// Invalid address ranges. InvalidAddrRanges: IntervalSet /// Not-in-file address ranges. NotInFileRanges: IntervalSet /// Executable address ranges. ExecutableRanges: IntervalSet - /// BinReader + /// BinReader. BinReader: BinReader + /// ISA. + ISA: ISA + /// Unwinding info table. + UnwindingTbl: Map } diff --git a/src/BinFile/FileHelper.fs b/src/FrontEnd/BinFile/FileHelper.fs similarity index 80% rename from src/BinFile/FileHelper.fs rename to src/FrontEnd/BinFile/FileHelper.fs index e1b66c28..ce7d7f63 100644 --- a/src/BinFile/FileHelper.fs +++ b/src/FrontEnd/BinFile/FileHelper.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module internal B2R2.BinFile.FileHelper +module internal B2R2.FrontEnd.BinFile.FileHelper open B2R2 @@ -68,7 +68,7 @@ let peekCStringOfSize (reader: BinReader) offset (size: int) = let addInvRange set saddr eaddr = if saddr = eaddr then set - else IntervalSet.add (AddrRange (saddr, eaddr)) set + else IntervalSet.add (AddrRange (saddr, eaddr - 1UL)) set let addLastInvRange wordSize (set, saddr) = let laddr = @@ -81,3 +81,17 @@ let trimByRange myrange target = let l = max (AddrRange.GetMin myrange) (AddrRange.GetMin target) let h = min (AddrRange.GetMax myrange) (AddrRange.GetMax target) AddrRange (l, h) + +let getNotInFileIntervals fileBase fileSize (range: AddrRange) = + let lastAddr = fileBase + fileSize - 1UL + if range.Max < fileBase then Seq.singleton range + elif range.Max <= lastAddr && range.Min < fileBase then + Seq.singleton (AddrRange (range.Min, fileBase - 1UL)) + elif range.Max > lastAddr && range.Min < fileBase then + [ AddrRange (range.Min, fileBase - 1UL) + AddrRange (lastAddr + 1UL, range.Max) ] + |> List.toSeq + elif range.Max > lastAddr && range.Min <= lastAddr then + Seq.singleton (AddrRange (lastAddr + 1UL, range.Max)) + elif range.Max > lastAddr && range.Min > lastAddr then Seq.singleton range + else Seq.empty diff --git a/src/BinFile/FileInfo.fs b/src/FrontEnd/BinFile/FileInfo.fs similarity index 81% rename from src/BinFile/FileInfo.fs rename to src/FrontEnd/BinFile/FileInfo.fs index 35a0de5f..1bbf582e 100644 --- a/src/BinFile/FileInfo.fs +++ b/src/FrontEnd/BinFile/FileInfo.fs @@ -22,14 +22,14 @@ SOFTWARE. *) -namespace B2R2.BinFile +namespace B2R2.FrontEnd.BinFile open B2R2 open System.Runtime.InteropServices /// FileInfo describes a binary file in a format-agnostic way. [] -type FileInfo (baseAddr) = +type FileInfo () = /// /// The corresponding binary reader. /// @@ -60,11 +60,6 @@ type FileInfo (baseAddr) = /// abstract WordSize: WordSize - /// - /// Base address where this binary is located at. - /// - member __.BaseAddr with get(): Addr = baseAddr - /// /// Is this binary stripped? /// @@ -81,8 +76,8 @@ type FileInfo (baseAddr) = abstract IsRelocatable: bool /// - /// The base address of this binary - /// (at which this binary is prefered to be loaded in memory). + /// The base address of this binary at which this binary is prefered to be + /// loaded in memory. /// abstract BaseAddress: Addr @@ -105,11 +100,20 @@ type FileInfo (baseAddr) = /// /// Returns an offset to this binary for a given virtual address. /// - /// + /// /// Thrown when the given address is out of a valid address range. /// abstract member TranslateAddress: addr: Addr -> int + /// + /// Add a symbol for the address. This function is useful when we can + /// obtain extra symbol information from outside of B2R2. + /// + /// + /// Does not return a value. + /// + abstract member AddSymbol: Addr -> Symbol -> unit + /// /// Return a list of all the symbols from the binary. /// @@ -132,10 +136,12 @@ type FileInfo (baseAddr) = /// /// Return a list of all the dynamic symbols from the binary. Dynamic /// symbols are the ones that are required to run the binary. The - /// "excludeImported" argument indicates whether to return only internally - /// defined symbols (i.e., disregard external symbols that are imported from - /// other files). In "excludeImported" argument is not given, this function - /// will simply return all possible dynamic symbols. + /// "excludeImported" argument indicates whether to exclude external symbols + /// that are imported from other files. However, even if "excludeImported" + /// is true, returned symbols may include a forwarding entry that redirects + /// to another function in an external file (cf. SymbolKind.ForwardType). + /// When "excludeImported" argument is not given, this function will simply + /// return all possible dynamic symbols. /// /// /// A sequence of dynamic symbols. @@ -243,11 +249,29 @@ type FileInfo (baseAddr) = /// Find the symbol name for a given address. /// /// - /// Returns true if a symbol exists, otherwise returns false. + /// Returns a symbol as an Ok value if a symbol exists, otherwise returns + /// an Error value. /// - abstract member TryFindFunctionSymbolName: - Addr * [] name: byref - -> bool + abstract member TryFindFunctionSymbolName: Addr -> Result + + /// + /// An exception table, which is a mapping from a function address to a set + /// of landing pads. The landing pads are mappings from a range of + /// instruction addresses to a landing pad address. + /// + abstract member ExceptionTable: ARMap> + + /// + /// Convert the section at the address (Addr) into a binary pointer, which + /// can exclusively point to binary contents of the section. + /// + abstract member ToBinaryPointer: Addr -> BinaryPointer + + /// + /// Convert the section of the name (string) into a binary pointer, which + /// can exclusively point to binary contents of the section. + /// + abstract member ToBinaryPointer: string -> BinaryPointer /// /// Check if the given address is valid for this binary. We say a given @@ -309,7 +333,7 @@ type FileInfo (baseAddr) = abstract member IsExecutableAddr: Addr -> bool /// - /// Given a range r, return a list of address ragnes (intervals) that are + /// Given a range r, return a list of address ranges (intervals) that are /// within r, and that are not in-file. /// /// @@ -332,11 +356,12 @@ type FileInfo (baseAddr) = if dict.ContainsKey s.Address then () else dict.[s.Address] <- s) dict |> Seq.map (fun (KeyValue (_, s)) -> s) - |> Seq.filter (fun s -> s.Kind = SymbolKind.FunctionType) + |> Seq.filter (fun s -> s.Kind = FunctionType) /// /// Returns a sequence of local function addresses (excluding external - /// functions) from a given FileInfo. + /// functions) from a given FileInfo. This function only considers addresses + /// that are certain. /// /// /// A sequence of function addresses. @@ -347,6 +372,23 @@ type FileInfo (baseAddr) = __.GetFunctionSymbols () |> Seq.map (fun s -> s.Address) + /// + /// Returns a sequence of local function addresses (excluding external + /// functions) from a given FileInfo. If the argument is true, then this + /// funciton utilizes exception information of the binary to infer function + /// entries. Note that the inference process is not necessarily precise, so + /// this is really just an experimental feature, and will be removed in the + /// future. + /// + /// + /// A sequence of function addresses. + /// + abstract member GetFunctionAddresses: bool -> seq + + default __.GetFunctionAddresses (_) = + __.GetFunctionSymbols () + |> Seq.map (fun s -> s.Address) + /// /// Get a sequence of executable sections including linkage table code /// sections such as PLT. @@ -360,7 +402,8 @@ type FileInfo (baseAddr) = || (s.Kind = SectionKind.LinkageTableSection)) /// - /// Convert FileType to string. + /// Convert FileType to + /// string. /// /// A FileType to convert. /// @@ -377,7 +420,7 @@ type FileInfo (baseAddr) = /// /// Convert from permission to string. /// - /// A permission to convert. + /// A permission to convert. /// /// A converted string. /// diff --git a/src/BinFile/FileTypes.fs b/src/FrontEnd/BinFile/FileTypes.fs similarity index 89% rename from src/BinFile/FileTypes.fs rename to src/FrontEnd/BinFile/FileTypes.fs index e8b16d24..4b6f0fa8 100644 --- a/src/BinFile/FileTypes.fs +++ b/src/FrontEnd/BinFile/FileTypes.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.BinFile +namespace B2R2.FrontEnd.BinFile open B2R2 @@ -38,19 +38,21 @@ exception InvalidFileTypeException /// Kinds of a symbol. type SymbolKind = /// The symbol type is not specified. - | NoType = 0 + | NoType /// The symbol is associated with a data object, such as a variable. - | ObjectType = 1 + | ObjectType /// The symbol is associated with a general function. - | FunctionType = 2 + | FunctionType /// The symbol is associated with an external (imported) function. - | ExternFunctionType = 3 + | ExternFunctionType /// The symbol is associated with a trampoline instruction, such as PLT. - | TrampolineType = 4 + | TrampolineType /// The symbol is associated with a section. - | SectionType = 5 + | SectionType /// The symbol gives the name of the source file associated with the obj file. - | FileType = 6 + | FileType + /// The symbol is associated with a forwarding entry. + | ForwardType of bin: string * func: string /// Is the symbol used for static target (static link editor) or dynamic target /// (dynamic linker)? @@ -72,6 +74,9 @@ type Symbol = { Target: TargetKind /// Corresponding library name. LibraryName: string + /// Corresponding ArchOperationMode for this symbol, which is only meaningful + /// for ARM. + ArchOperationMode: ArchOperationMode } /// Kinds of sections. @@ -90,6 +95,8 @@ type SectionKind = type Section = { /// Address of the section. Address: Addr + /// File offset of the seciton. + FileOffset: uint64 /// Section kind. Kind: SectionKind /// Size of the section. @@ -101,7 +108,7 @@ with /// Convert the section into an AddrRange based on its starting address and /// the size. member __.ToAddrRange () = - AddrRange (__.Address, __.Address + __.Size) + AddrRange (__.Address, __.Address + __.Size - 1UL) /// Linkage table entry object, which basically refers to PLT or IAT. type LinkageTableEntry = { @@ -133,9 +140,9 @@ type FileType = [] type Permission = /// File is readable. - | Readable = 4 + | Readable = 4 /// File is writable. - | Writable = 2 + | Writable = 2 /// File is executable. | Executable = 1 diff --git a/src/BinFile/FormatDetector.fs b/src/FrontEnd/BinFile/FormatDetector.fs similarity index 50% rename from src/BinFile/FormatDetector.fs rename to src/FrontEnd/BinFile/FormatDetector.fs index 67c04e62..15e594df 100644 --- a/src/BinFile/FormatDetector.fs +++ b/src/FrontEnd/BinFile/FormatDetector.fs @@ -23,51 +23,55 @@ *) /// Binary file format detector. -module B2R2.BinFile.FormatDetector +[] +module B2R2.FrontEnd.BinFile.FormatDetector open System.IO open B2R2 -let private elfBinary reader = - if ELF.Header.isELF reader 0 then Some FileFormat.ELFBinary +let private identifyELF reader = + if ELF.Header.isELF reader 0 then + let cls = ELF.Header.peekClass reader 0 + let arch = ELF.Header.peekArch reader cls 0 + let endian = ELF.Header.peekEndianness reader 0 + let isa = ISA.Init arch endian + Some (FileFormat.ELFBinary, isa) else None -let private peBinary bytes = - if PE.Helper.isPE bytes 0 then Some FileFormat.PEBinary - else None +let private identifyPE bytes = + match PE.Helper.getPEArch bytes 0 with + | Ok arch -> + let isa = ISA.Init arch Endian.Little + Some (FileFormat.PEBinary, isa) + | Error _ -> None -let private machBinary reader = - if Mach.Header.isMach reader 0 then Some FileFormat.MachBinary +let private identifyMach reader isa = + if Mach.Header.isMach reader 0 then + if Mach.Header.isFat reader 0 then + Some (FileFormat.MachBinary, isa) + else + let arch = Mach.Header.peekArch reader 0 + let endian = Mach.Header.peekEndianness reader 0 + let isa = ISA.Init arch endian + Some (FileFormat.MachBinary, isa) else None -let private wasmBinary reader = - if Wasm.Header.isWasm reader 0 then Some FileFormat.WasmBinary +let private identifyWASM reader isa = + if Wasm.Header.isWasm reader 0 then + Some (FileFormat.WasmBinary, isa) else None /// -/// Given a byte array, identify its file format and return B2R2.FileFormat. +/// Given a byte array, identify its binary file format and return +/// B2R2.FileFormat and B2R2.ISA. /// -[] -let detectBuffer bytes = +[] +let identify bytes isa = let reader = BinReader.Init (bytes) Monads.OrElse.orElse { - yield! elfBinary reader - yield! peBinary bytes - yield! machBinary reader - yield! wasmBinary reader - yield! Some FileFormat.RawBinary + yield! identifyELF reader + yield! identifyPE bytes + yield! identifyMach reader isa + yield! identifyWASM reader isa + yield! Some (FileFormat.RawBinary, isa) } |> Option.get - -/// -/// Given a binary file path, identify its file format and return -/// B2R2.FileFormat. -/// -[] -let detect file = - use f = File.OpenRead (file) - let maxBytes = 2048 (* This is more than enough for all the file formats. *) - let bytes = Array.create maxBytes 0uy - f.Read (bytes, 0, maxBytes) |> ignore - detectBuffer bytes - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/BinFile/Mach.fs b/src/FrontEnd/BinFile/Mach.fs similarity index 80% rename from src/BinFile/Mach.fs rename to src/FrontEnd/BinFile/Mach.fs index 4a04fa05..01c403fc 100644 --- a/src/BinFile/Mach.fs +++ b/src/FrontEnd/BinFile/Mach.fs @@ -22,33 +22,35 @@ SOFTWARE. *) -namespace B2R2.BinFile +namespace B2R2.FrontEnd.BinFile open B2R2 -open B2R2.BinFile.Mach -open B2R2.BinFile.Mach.Helper +open B2R2.FrontEnd.BinFile.Mach +open B2R2.FrontEnd.BinFile.Mach.Helper /// /// This class represents a Mach-O binary file. /// type MachFileInfo (bytes, path, isa, baseAddr) = - inherit FileInfo (baseAddr) + inherit FileInfo () let mach = Parser.parse baseAddr bytes isa + let isa = getISA mach - new (bytes, path, isa) = MachFileInfo (bytes, path, isa, 0UL) + new (bytes, path, isa) = MachFileInfo (bytes, path, isa, None) override __.BinReader = mach.BinReader override __.FileFormat = FileFormat.MachBinary - override __.ISA = getISA mach + override __.ISA = isa override __.FileType = convFileType mach.MachHdr.FileType override __.FilePath = path override __.WordSize = mach.MachHdr.Class override __.IsStripped = isStripped mach override __.IsNXEnabled = isNXEnabled mach override __.IsRelocatable = mach.MachHdr.Flags.HasFlag MachFlag.MHPIE - override __.BaseAddress = getBaseAddr mach + override __.BaseAddress = mach.BaseAddr override __.EntryPoint = mach.EntryPoint override __.TextStartAddr = getTextStartAddr mach override __.TranslateAddress addr = translateAddr mach addr + override __.AddSymbol addr symbol = Utils.futureFeature () override __.GetSymbols () = getSymbols mach override __.GetStaticSymbols () = getStaticSymbols mach |> Array.toSeq override __.GetDynamicSymbols (?e) = getDynamicSymbols e mach |> Array.toSeq @@ -60,12 +62,18 @@ type MachFileInfo (bytes, path, isa, baseAddr) = override __.GetSegments (isLoadable) = Segment.getSegments mach isLoadable override __.GetLinkageTableEntries () = getPLT mach override __.IsLinkageTable addr = isPLT mach addr - override __.TryFindFunctionSymbolName (addr, n) = tryFindFuncSymb mach addr &n + override __.TryFindFunctionSymbolName (addr) = tryFindFuncSymb mach addr + override __.ExceptionTable = ARMap.empty + override __.ToBinaryPointer addr = + BinaryPointer.OfSectionOpt (getSectionsByAddr mach addr |> Seq.tryHead) + override __.ToBinaryPointer name = + BinaryPointer.OfSectionOpt (getSectionsByName mach name |> Seq.tryHead) override __.IsValidAddr addr = isValidAddr mach addr override __.IsValidRange range = isValidRange mach range override __.IsInFileAddr addr = isInFileAddr mach addr override __.IsInFileRange range = isInFileRange mach range override __.IsExecutableAddr addr = isExecutableAddr mach addr override __.GetNotInFileIntervals range = getNotInFileIntervals mach range + member __.Mach with get() = mach // vim: set tw=80 sts=2 sw=2: diff --git a/src/BinFile/MachFat.fs b/src/FrontEnd/BinFile/MachFat.fs similarity index 97% rename from src/BinFile/MachFat.fs rename to src/FrontEnd/BinFile/MachFat.fs index 5eb12bb7..abe53d15 100644 --- a/src/BinFile/MachFat.fs +++ b/src/FrontEnd/BinFile/MachFat.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module internal B2R2.BinFile.Mach.Fat +module internal B2R2.FrontEnd.BinFile.Mach.Fat open B2R2 diff --git a/src/BinFile/MachHeader.fs b/src/FrontEnd/BinFile/MachHeader.fs similarity index 97% rename from src/BinFile/MachHeader.fs rename to src/FrontEnd/BinFile/MachHeader.fs index 968f890d..3b726bcc 100644 --- a/src/BinFile/MachHeader.fs +++ b/src/FrontEnd/BinFile/MachHeader.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module internal B2R2.BinFile.Mach.Header +module internal B2R2.FrontEnd.BinFile.Mach.Header open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile let peekMagic (reader: BinReader) offset = if reader.Length() > offset + sizeof diff --git a/src/BinFile/MachHelper.fs b/src/FrontEnd/BinFile/MachHelper.fs similarity index 87% rename from src/BinFile/MachHelper.fs rename to src/FrontEnd/BinFile/MachHelper.fs index 6902ceb6..6bac59c5 100644 --- a/src/BinFile/MachHelper.fs +++ b/src/FrontEnd/BinFile/MachHelper.fs @@ -22,11 +22,22 @@ SOFTWARE. *) -module internal B2R2.BinFile.Mach.Helper +module internal B2R2.FrontEnd.BinFile.Mach.Helper open System open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile + +/// Mach-specific virtual memory permission (for maxprot and initprot). Note +/// that these values are different than the B2R2.Permission type. +[] +type MachVMProt = + /// File is readable. + | Readable = 1 + /// File is writable. + | Writable = 2 + /// File is executable. + | Executable = 4 let getISA mach = let cputype = mach.MachHdr.CPUType @@ -60,7 +71,8 @@ let machSymbolToSymbol secText target sym = Name = sym.SymName Kind = machTypeToSymbKind sym secText Target = target - LibraryName = Symbol.getSymbolLibName sym } + LibraryName = Symbol.getSymbolLibName sym + ArchOperationMode = ArchOperationMode.NoMode } let getStaticSymbols mach = mach.SymInfo.Symbols @@ -69,20 +81,13 @@ let getStaticSymbols mach = let isStripped mach = getStaticSymbols mach - |> Array.exists (fun s -> s.Kind = SymbolKind.FunctionType) + |> Array.exists (fun s -> s.Kind = FunctionType) |> not let isNXEnabled mach = not (mach.MachHdr.Flags.HasFlag MachFlag.MHAllowStackExecution) || mach.MachHdr.Flags.HasFlag MachFlag.MHNoHeapExecution -let getBaseAddr (mach: Mach) = - let lowestSegment = - mach.Segments - |> List.filter (fun seg -> seg.FileSize > 0UL) - |> List.minBy (fun seg -> seg.VMAddr) - lowestSegment.VMAddr - let inline getTextStartAddr mach = (Map.find "__text" mach.Sections.SecByName).SecAddr @@ -114,9 +119,10 @@ let secFlagToSectionKind isExecutable = function let machSectionToSection segMap (sec: MachSection) = let seg = ARMap.findByAddr sec.SecAddr segMap - let perm: Permission = seg.InitProt |> LanguagePrimitives.EnumOfValue - let isExecutable = perm.HasFlag Permission.Executable + let perm: MachVMProt = seg.InitProt |> LanguagePrimitives.EnumOfValue + let isExecutable = perm.HasFlag MachVMProt.Executable { Address = sec.SecAddr + FileOffset = uint64 sec.SecOffset Kind = secFlagToSectionKind isExecutable sec.SecType Size = sec.SecSize Name = sec.SecName } @@ -150,10 +156,10 @@ let isPLT mach addr = mach.SymInfo.LinkageTable |> List.exists (fun entry -> entry.TrampolineAddress = addr) -let inline tryFindFuncSymb mach addr (name: byref) = +let inline tryFindFuncSymb mach addr = match Map.tryFind addr mach.SymInfo.SymbolMap with - | Some s -> name <- s.SymName; true - | None -> false + | Some s -> Ok s.SymName + | None -> Error ErrorCase.SymbolNotFound let inline isValidAddr mach addr = IntervalSet.containsAddr addr mach.InvalidAddrRanges |> not diff --git a/src/BinFile/MachLoadCommands.fs b/src/FrontEnd/BinFile/MachLoadCommands.fs similarity index 70% rename from src/BinFile/MachLoadCommands.fs rename to src/FrontEnd/BinFile/MachLoadCommands.fs index eec848dc..60ca2047 100644 --- a/src/BinFile/MachLoadCommands.fs +++ b/src/FrontEnd/BinFile/MachLoadCommands.fs @@ -22,14 +22,16 @@ SOFTWARE. *) -module internal B2R2.BinFile.Mach.LoadCommands +module internal B2R2.FrontEnd.BinFile.Mach.LoadCommands open System open B2R2 -open B2R2.BinFile.FileHelper +open B2R2.FrontEnd.BinFile.FileHelper -let parseSegCmd baseAddr (reader: BinReader) cls offset = - { SecOff = offset + if cls = WordSize.Bit64 then 72 else 56 +let parseSegCmd baseAddr (reader: BinReader) cls offset cmdType cmdSize = + { Cmd = cmdType + CmdSize = cmdSize + SecOff = offset + if cls = WordSize.Bit64 then 72 else 56 SegCmdName = peekCStringOfSize reader (offset + 8) 16 VMAddr = peekHeaderNative reader cls offset 24 24 + baseAddr VMSize = peekHeaderNative reader cls offset 28 32 @@ -40,14 +42,18 @@ let parseSegCmd baseAddr (reader: BinReader) cls offset = NumSecs = peekHeaderU32 reader cls offset 48 64 SegFlag = peekHeaderU32 reader cls offset 52 68 } -let parseSymCmd (reader: BinReader) offset = - { SymOff = offset + 8 |> reader.PeekInt32 +let parseSymCmd (reader: BinReader) offset cmdType cmdSize = + { Cmd = cmdType + CmdSize = cmdSize + SymOff = offset + 8 |> reader.PeekInt32 NumOfSym = offset + 12 |> reader.PeekUInt32 StrOff = offset + 16 |> reader.PeekInt32 StrSize = offset + 20 |> reader.PeekUInt32 } -let parseDySymCmd (reader: BinReader) offset = - { IdxLocalSym = offset + 8 |> reader.PeekUInt32 +let parseDySymCmd (reader: BinReader) offset cmdType cmdSize = + { Cmd = cmdType + CmdSize = cmdSize + IdxLocalSym = offset + 8 |> reader.PeekUInt32 NumLocalSym = offset + 12 |> reader.PeekUInt32 IdxExtSym = offset + 16 |> reader.PeekUInt32 NumExtSym = offset + 20 |> reader.PeekUInt32 @@ -66,8 +72,10 @@ let parseDySymCmd (reader: BinReader) offset = LocalRelOff = offset + 72 |> reader.PeekUInt32 NumLocalRel = offset + 76 |> reader.PeekUInt32 } -let parseMainCmd baseAddr (reader: BinReader) offset = - { EntryOff = (offset + 8 |> reader.PeekUInt64) + baseAddr +let parseMainCmd baseAddr (reader: BinReader) offset cmdType cmdSize = + { Cmd = cmdType + CmdSize = cmdSize + EntryOff = (offset + 8 |> reader.PeekUInt64) + baseAddr StackSize = offset + 16 |> reader.PeekUInt64 } /// Read lc_str string. @@ -77,14 +85,18 @@ let readLCStr (reader: BinReader) (size: uint32) offset = let span = reader.PeekSpan (strLen, offset + strOffset) ByteArray.extractCStringFromSpan span 0 -let parseDyLibCmd (reader: BinReader) size offset = - { DyLibName = readLCStr reader size offset +let parseDyLibCmd (reader: BinReader) offset cmdType cmdSize = + { Cmd = cmdType + CmdSize = cmdSize + DyLibName = readLCStr reader cmdSize offset DyLibTimeStamp = offset + 12 |> reader.PeekUInt32 DyLibCurVer = offset + 16 |> reader.PeekUInt32 DyLibCmpVer = offset + 20 |> reader.PeekUInt32 } -let parseDyLdInfo (reader: BinReader) offset = - { RebaseOff = offset + 8 |> reader.PeekInt32 +let parseDyLdInfo (reader: BinReader) offset cmdType cmdSize = + { Cmd = cmdType + CmdSize = cmdSize + RebaseOff = offset + 8 |> reader.PeekInt32 RebaseSize = offset + 12 |> reader.PeekUInt32 BindOff = offset + 16 |> reader.PeekInt32 BindSize = offset + 20 |> reader.PeekUInt32 @@ -95,8 +107,10 @@ let parseDyLdInfo (reader: BinReader) offset = ExportOff = offset + 40 |> reader.PeekInt32 ExportSize = offset + 44 |> reader.PeekUInt32 } -let parseFuncStarts (reader: BinReader) offset = - { DataOffset = offset + 8 |> reader.PeekInt32 +let parseFuncStarts (reader: BinReader) offset cmdType cmdSize = + { Cmd = cmdType + CmdSize = cmdSize + DataOffset = offset + 8 |> reader.PeekInt32 DataSize = offset + 12 |> reader.PeekUInt32 } let parseCmd baddr (reader: BinReader) cls offset = @@ -105,14 +119,21 @@ let parseCmd baddr (reader: BinReader) cls offset = let command = match cmdType with | LoadCmdType.LCSegment - | LoadCmdType.LCSegment64 -> Segment (parseSegCmd baddr reader cls offset) - | LoadCmdType.LCSymTab -> SymTab (parseSymCmd reader offset) - | LoadCmdType.LCDySymTab -> DySymTab (parseDySymCmd reader offset) - | LoadCmdType.LCMain -> Main (parseMainCmd baddr reader offset) - | LoadCmdType.LCLoadDyLib -> DyLib (parseDyLibCmd reader cmdSize offset) + | LoadCmdType.LCSegment64 -> + Segment (parseSegCmd baddr reader cls offset cmdType cmdSize) + | LoadCmdType.LCSymTab -> + SymTab (parseSymCmd reader offset cmdType cmdSize) + | LoadCmdType.LCDySymTab -> + DySymTab (parseDySymCmd reader offset cmdType cmdSize) + | LoadCmdType.LCMain -> + Main (parseMainCmd baddr reader offset cmdType cmdSize) + | LoadCmdType.LCLoadDyLib -> + DyLib (parseDyLibCmd reader offset cmdType cmdSize) | LoadCmdType.LCDyLDInfo - | LoadCmdType.LCDyLDInfoOnly -> DyLdInfo (parseDyLdInfo reader offset) - | LoadCmdType.LCFunStarts -> FuncStarts (parseFuncStarts reader offset) + | LoadCmdType.LCDyLDInfoOnly -> + DyLdInfo (parseDyLdInfo reader offset cmdType cmdSize) + | LoadCmdType.LCFunStarts -> + FuncStarts (parseFuncStarts reader offset cmdType cmdSize) | _ -> Unhandled { Cmd = cmdType; CmdSize = cmdSize } struct (command, Convert.ToInt32 cmdSize) diff --git a/src/BinFile/MachParser.fs b/src/FrontEnd/BinFile/MachParser.fs similarity index 90% rename from src/BinFile/MachParser.fs rename to src/FrontEnd/BinFile/MachParser.fs index 9bd5dd53..2d56abe4 100644 --- a/src/BinFile/MachParser.fs +++ b/src/FrontEnd/BinFile/MachParser.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module internal B2R2.BinFile.Mach.Parser +module internal B2R2.FrontEnd.BinFile.Mach.Parser open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile let isMainCmd = function | Main _ -> true @@ -61,12 +61,17 @@ let execRanges segs = |> List.filter (fun seg -> let perm: Permission = seg.MaxProt |> LanguagePrimitives.EnumOfValue perm &&& Permission.Executable = Permission.Executable) - |> List.fold (fun set seg -> - IntervalSet.add (AddrRange (seg.VMAddr, seg.VMAddr + seg.VMSize)) set + |> List.fold (fun set s -> + IntervalSet.add (AddrRange (s.VMAddr, s.VMAddr + s.VMSize - 1UL)) set ) IntervalSet.empty +let computeBaseAddr machHdr baseAddr = + if machHdr.Flags.HasFlag MachFlag.MHPIE then defaultArg baseAddr 0UL + else 0UL + let parseMach baseAddr reader = let machHdr = Header.parse reader 0 + let baseAddr = computeBaseAddr machHdr baseAddr let cls = machHdr.Class let cmds = LoadCommands.parse baseAddr reader machHdr let segs = Segment.extract cmds @@ -78,6 +83,7 @@ let parseMach baseAddr reader = Reloc.parseRelocs reader secs.SecByNum |> Array.map (Reloc.toSymbol symInfo.Symbols secs.SecByNum) { EntryPoint = computeEntryPoint segs cmds + BaseAddr = baseAddr SymInfo = symInfo MachHdr = machHdr Segments = segs @@ -85,6 +91,7 @@ let parseMach baseAddr reader = Sections = secs SecText = secText Relocations = relocs + Cmds = cmds InvalidAddrRanges = invRanges cls segs (fun s -> s.VMAddr + s.VMSize) NotInFileRanges = invRanges cls segs (fun s -> s.VMAddr + s.FileSize) ExecutableRanges = execRanges segs diff --git a/src/BinFile/MachReloc.fs b/src/FrontEnd/BinFile/MachReloc.fs similarity index 94% rename from src/BinFile/MachReloc.fs rename to src/FrontEnd/BinFile/MachReloc.fs index 7d4a860b..c2238b96 100644 --- a/src/BinFile/MachReloc.fs +++ b/src/FrontEnd/BinFile/MachReloc.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.BinFile.Mach.Reloc +module internal B2R2.FrontEnd.BinFile.Mach.Reloc open System open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile let parseRelocSymbol data = let n = data &&& 0xFFFFFF @@ -68,7 +68,8 @@ let toSymbol symbols secs reloc = Name = translateRelocSymbol symbols secs reloc Kind = SymbolKind.NoType (* FIXME *) Target = TargetKind.DynamicSymbol - LibraryName = "" } + LibraryName = "" + ArchOperationMode = ArchOperationMode.NoMode } let parseRelocs binReader secs = secs diff --git a/src/BinFile/MachSection.fs b/src/FrontEnd/BinFile/MachSection.fs similarity index 95% rename from src/BinFile/MachSection.fs rename to src/FrontEnd/BinFile/MachSection.fs index f502f38c..ad8b46b5 100644 --- a/src/BinFile/MachSection.fs +++ b/src/FrontEnd/BinFile/MachSection.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module internal B2R2.BinFile.Mach.Section +module internal B2R2.FrontEnd.BinFile.Mach.Section open B2R2 -open B2R2.BinFile.FileHelper +open B2R2.FrontEnd.BinFile.FileHelper let parseSection baseAddr (reader: BinReader) cls pos = let secFlag = peekHeaderI32 reader cls pos 56 64 @@ -43,7 +43,7 @@ let parseSection baseAddr (reader: BinReader) cls pos = SecReserved2 = peekHeaderI32 reader cls pos 64 72 } let foldSecInfo acc sec = - let secEnd = sec.SecAddr + sec.SecSize + let secEnd = sec.SecAddr + sec.SecSize - 1UL let secByAddr = ARMap.addRange sec.SecAddr secEnd sec acc.SecByAddr let secByName = Map.add sec.SecName sec acc.SecByName { acc with SecByAddr = secByAddr; SecByName = secByName } diff --git a/src/BinFile/MachSegment.fs b/src/FrontEnd/BinFile/MachSegment.fs similarity index 91% rename from src/BinFile/MachSegment.fs rename to src/FrontEnd/BinFile/MachSegment.fs index 9ba6e19e..f0b3f87e 100644 --- a/src/BinFile/MachSegment.fs +++ b/src/FrontEnd/BinFile/MachSegment.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module internal B2R2.BinFile.Mach.Segment +module internal B2R2.FrontEnd.BinFile.Mach.Segment open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile let extract cmds = let chooser = function @@ -36,7 +36,7 @@ let extract cmds = let buildMap (segs: SegCmd list) = segs |> List.fold (fun map s -> - ARMap.addRange s.VMAddr (s.VMAddr + s.VMSize) s map) ARMap.empty + ARMap.addRange s.VMAddr (s.VMAddr + s.VMSize - 1UL) s map) ARMap.empty let segCmdToSegment seg = { Address = seg.VMAddr diff --git a/src/BinFile/MachSymbol.fs b/src/FrontEnd/BinFile/MachSymbol.fs similarity index 98% rename from src/BinFile/MachSymbol.fs rename to src/FrontEnd/BinFile/MachSymbol.fs index 3505e7f9..2c73dae6 100644 --- a/src/BinFile/MachSymbol.fs +++ b/src/FrontEnd/BinFile/MachSymbol.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -module internal B2R2.BinFile.Mach.Symbol +module internal B2R2.FrontEnd.BinFile.Mach.Symbol open System open B2R2 -open B2R2.BinFile -open B2R2.BinFile.FileHelper +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper let [] IndirectSymbolLocal = 0x80000000 let [] IndirectSymbolABS = 0x40000000 @@ -111,7 +111,7 @@ let addFuncs secTxt starts symbols = Set.difference starts symbolAddrs |> Set.toArray |> Array.map (fun addr -> - { SymName = "func_" + addr.ToString ("X") + { SymName = Addr.toFuncName addr SymType = SymbolType.NSect IsExternal = false SecNum = secTxt + 1 diff --git a/src/BinFile/MachTypes.fs b/src/FrontEnd/BinFile/MachTypes.fs similarity index 98% rename from src/BinFile/MachTypes.fs rename to src/FrontEnd/BinFile/MachTypes.fs index 32e95c48..3577ec1c 100644 --- a/src/BinFile/MachTypes.fs +++ b/src/FrontEnd/BinFile/MachTypes.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -namespace B2R2.BinFile.Mach +namespace B2R2.FrontEnd.BinFile.Mach open System open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile /// Magic number for Mach-O header. type Magic = @@ -322,6 +322,8 @@ type LoadCommand = /// Segment command. and SegCmd = { + Cmd: LoadCmdType + CmdSize: uint32 /// The offset of the sections in the segment. If the segment has sections /// then the section structures directly follow the segment command and their /// size is in the size of the command. @@ -348,6 +350,8 @@ and SegCmd = { /// Symbol table command. and SymTabCmd = { + Cmd: LoadCmdType + CmdSize: uint32 /// An integer containing the byte offset from the start of the file to the /// location of the symbol table entries. SymOff: int @@ -362,6 +366,8 @@ and SymTabCmd = { /// Dynamic symbol table command. and DySymTabCmd = { + Cmd: LoadCmdType + CmdSize: uint32 /// An integer indicating the index of the first symbol in the group of local /// symbols. IdxLocalSym: uint32 @@ -416,6 +422,8 @@ and DySymTabCmd = { /// DYLD information command (dyld_info_command). and DyLdInfoCmd = { + Cmd: LoadCmdType + CmdSize: uint32 /// File offset to rebase info. RebaseOff: int /// The size of rebase info. @@ -440,12 +448,16 @@ and DyLdInfoCmd = { /// Function starts command (LC_FUNCTION_STARTS). and FuncStartsCmd = { + Cmd: LoadCmdType + CmdSize: uint32 DataOffset: int DataSize: uint32 } /// Main command. and MainCmd = { + Cmd: LoadCmdType + CmdSize: uint32 /// Offset of main(). EntryOff: Addr /// Initial stack size, if not zero. @@ -455,6 +467,8 @@ and MainCmd = { /// Dynamic library command: the data used by the dynamic linker to match a /// shared library against the files that have linked to it. and DyLibCmd = { + Cmd: LoadCmdType + CmdSize: uint32 /// Library's path name. DyLibName: string /// Library's build time stamp. @@ -715,6 +729,8 @@ type SymInfo = { type Mach = { /// Entry point. EntryPoint: Addr option + /// Preferred base address. + BaseAddr: Addr /// Header. MachHdr: MachHeader /// Segments. @@ -723,6 +739,8 @@ type Mach = { SegmentMap: ARMap /// Sections. Sections: SectionInfo + /// Load Commands + Cmds: LoadCommand list /// Symbol info. SymInfo: SymInfo /// Text section index. diff --git a/src/BinFile/PE.fs b/src/FrontEnd/BinFile/PE.fs similarity index 79% rename from src/BinFile/PE.fs rename to src/FrontEnd/BinFile/PE.fs index dbbd0c5d..4ecdfac5 100644 --- a/src/BinFile/PE.fs +++ b/src/FrontEnd/BinFile/PE.fs @@ -22,34 +22,37 @@ SOFTWARE. *) -namespace B2R2.BinFile +namespace B2R2.FrontEnd.BinFile open B2R2 -open B2R2.BinFile.PE.Helper +open B2R2.FrontEnd.BinFile.PE.Helper /// /// This class represents a PE binary file. /// type PEFileInfo (bytes, path, baseAddr, rawpdb) = - inherit FileInfo (baseAddr) + inherit FileInfo () let pe = PE.Parser.parse bytes path baseAddr rawpdb + let isa = getISA pe - new (bytes, path) = PEFileInfo (bytes, path, 0UL, [||]) + new (bytes, path) = PEFileInfo (bytes, path, None, [||]) new (bytes, path, baseAddr) = PEFileInfo (bytes, path, baseAddr, [||]) - new (bytes, path, rawpdb) = PEFileInfo (bytes, path, 0UL, rawpdb) + new (bytes, path, rawpdb) = PEFileInfo (bytes, path, None, rawpdb) + override __.BinReader = pe.BinReader override __.FileFormat = FileFormat.PEBinary - override __.ISA = getISA pe + override __.ISA = isa override __.FileType = getFileType pe override __.FilePath = path override __.WordSize = getWordSize pe override __.IsStripped = Array.length pe.SymbolInfo.SymbolArray = 0 override __.IsNXEnabled = isNXEnabled pe override __.IsRelocatable = isRelocatable pe - override __.BaseAddress = pe.PEHeaders.PEHeader.ImageBase + override __.BaseAddress = pe.BaseAddr override __.EntryPoint = getEntryPoint pe override __.TextStartAddr = getTextStartAddr pe override __.TranslateAddress addr = translateAddr pe addr + override __.AddSymbol addr symbol = Utils.futureFeature () override __.GetSymbols () = getSymbols pe override __.GetStaticSymbols () = getStaticSymbols pe override __.GetDynamicSymbols (?exc) = getDynamicSymbols pe exc @@ -61,12 +64,19 @@ type PEFileInfo (bytes, path, baseAddr, rawpdb) = override __.GetSegments (_isLoadable) = getSegments pe override __.GetLinkageTableEntries () = getImportTable pe override __.IsLinkageTable addr = isImportTable pe addr - override __.TryFindFunctionSymbolName (addr, n) = tryFindFuncSymb pe addr &n + override __.TryFindFunctionSymbolName (addr) = tryFindFuncSymb pe addr + override __.ExceptionTable = ARMap.empty + override __.ToBinaryPointer addr = + BinaryPointer.OfSectionOpt (getSectionsByAddr pe addr |> Seq.tryHead) + override __.ToBinaryPointer name = + BinaryPointer.OfSectionOpt (getSectionsByName pe name |> Seq.tryHead) override __.IsValidAddr addr = isValidAddr pe addr override __.IsValidRange range = isValidRange pe range override __.IsInFileAddr addr = isInFileAddr pe addr override __.IsInFileRange range = isInFileRange pe range override __.IsExecutableAddr addr = isExecutableAddr pe addr override __.GetNotInFileIntervals range = getNotInFileIntervals pe range + member __.PE with get() = pe + member __.RawPDB = rawpdb // vim: set tw=80 sts=2 sw=2: diff --git a/src/BinFile/PECoff.fs b/src/FrontEnd/BinFile/PECoff.fs similarity index 98% rename from src/BinFile/PECoff.fs rename to src/FrontEnd/BinFile/PECoff.fs index aa67ee95..26656992 100644 --- a/src/BinFile/PECoff.fs +++ b/src/FrontEnd/BinFile/PECoff.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -module internal B2R2.BinFile.PE.Coff +module internal B2R2.FrontEnd.BinFile.PE.Coff open System.Reflection.PortableExecutable open System.Runtime.InteropServices open B2R2 -open B2R2.BinFile.FileHelper +open B2R2.FrontEnd.BinFile.FileHelper type CoffSymbolTypeLSB = | ImageSymTypeNull = 0uy diff --git a/src/BinFile/PEHelper.fs b/src/FrontEnd/BinFile/PEHelper.fs similarity index 76% rename from src/BinFile/PEHelper.fs rename to src/FrontEnd/BinFile/PEHelper.fs index f765b538..b9080841 100644 --- a/src/BinFile/PEHelper.fs +++ b/src/FrontEnd/BinFile/PEHelper.fs @@ -22,27 +22,16 @@ SOFTWARE. *) -module internal B2R2.BinFile.PE.Helper +module internal B2R2.FrontEnd.BinFile.PE.Helper open System open B2R2 open B2R2.Monads -open B2R2.BinFile +open B2R2.FrontEnd.BinFile open System.Reflection.PortableExecutable let [] secText = ".text" -let machineToArch = function - | Machine.I386 -> Arch.IntelX86 - | Machine.Amd64 | Machine.IA64 -> Arch.IntelX64 - | Machine.Arm -> Arch.ARMv7 - | Machine.Arm64 -> Arch.AARCH64 - | _ -> raise InvalidISAException - -let getISA pe = - let arch = machineToArch pe.PEHeaders.CoffHeader.Machine - ISA.Init arch Endian.Little - let getFileType pe = let c = pe.PEHeaders.CoffHeader.Characteristics if c.HasFlag Characteristics.Dll then FileType.LibFile @@ -93,6 +82,7 @@ let getVirtualSectionSize (sec: SectionHeader) = let secHdrToSection pe (sec: SectionHeader) = { Address = addrFromRVA pe.BaseAddr sec.VirtualAddress + FileOffset = uint64 sec.PointerToRawData Kind = secFlagToSectionKind sec.SectionCharacteristics Size = getVirtualSectionSize sec |> uint64 Name = sec.Name } @@ -124,7 +114,8 @@ let pdbSymbolToSymbol (sym: PESymbol) = Name = sym.Name Kind = pdbTypeToSymbKind sym.Flags Target = TargetKind.StaticSymbol - LibraryName = "" } + LibraryName = "" + ArchOperationMode = ArchOperationMode.NoMode } let inline getStaticSymbols pe = pe.SymbolInfo.SymbolArray @@ -139,35 +130,51 @@ let getSymbolKindBySectionIndex pe idx = let getImportSymbols pe = let conv acc rva imp = match imp with - | ImportByOrdinal (_, dllname) -> + | ImportByOrdinal (ord, dllname) -> { Address = addrFromRVA pe.BaseAddr rva - Name = "" + Name = "#" + ord.ToString() Kind = SymbolKind.ExternFunctionType Target = TargetKind.DynamicSymbol - LibraryName = dllname } :: acc + LibraryName = dllname + ArchOperationMode = ArchOperationMode.NoMode } :: acc | ImportByName (_, funname, dllname) -> { Address = addrFromRVA pe.BaseAddr rva Name = funname Kind = SymbolKind.ExternFunctionType Target = TargetKind.DynamicSymbol - LibraryName = dllname } :: acc + LibraryName = dllname + ArchOperationMode = ArchOperationMode.NoMode } :: acc pe.ImportMap |> Map.fold conv [] |> List.rev let getExportSymbols pe = - let conv acc addr exp = + let makeLocalExportSymbol addr kind name = + { Address = addr + Name = name + Kind = kind + Target = TargetKind.DynamicSymbol + LibraryName = "" + ArchOperationMode = ArchOperationMode.NoMode } + let makeForwardedExportSymbol name (fwdBin, fwdFunc) = + { Address = 0UL + Name = name + Kind = SymbolKind.ForwardType (fwdBin, fwdFunc) + Target = TargetKind.DynamicSymbol + LibraryName = "" + ArchOperationMode = ArchOperationMode.NoMode } + let localExportFolder accSymbols addr names = let rva = int (addr - pe.BaseAddr) match pe.FindSectionIdxFromRVA rva with - | -1 -> acc + | -1 -> accSymbols | idx -> - { Address = addr - Name = exp - Kind = getSymbolKindBySectionIndex pe idx - Target = TargetKind.DynamicSymbol - LibraryName = "" } :: acc - pe.ExportMap - |> Map.fold conv [] + let kind = getSymbolKindBySectionIndex pe idx + let innerFolder acc name = makeLocalExportSymbol addr kind name :: acc + List.fold innerFolder accSymbols names + let forwardedExportFolder accSymbols name (fwdBin, fwdFunc) = + makeForwardedExportSymbol name (fwdBin, fwdFunc) :: accSymbols + Map.fold localExportFolder [] pe.ExportMap + |> Map.fold forwardedExportFolder <| pe.ForwardMap let getAllDynamicSymbols pe = let isym = getImportSymbols pe @@ -194,7 +201,7 @@ let getRelocationSymbols pe = Kind = SymbolKind.NoType Target = TargetKind.DynamicSymbol LibraryName = String.Empty - }) + ArchOperationMode = ArchOperationMode.NoMode }) let getSections pe = pe.SectionHeaders @@ -215,8 +222,8 @@ let getImportTable pe = pe.ImportMap |> Map.fold (fun acc addr info -> match info with - | ImportByOrdinal (_, dllname) -> - { FuncName = "" + | ImportByOrdinal (ord, dllname) -> + { FuncName = "#" + ord.ToString() LibraryName = dllname TrampolineAddress = 0UL TableAddress = addrFromRVA pe.BaseAddr addr } :: acc @@ -254,23 +261,23 @@ let private findSymFromIAT addr pe = let private findSymFromEAT addr pe () = match Map.tryFind addr pe.ExportMap with - | Some n -> Some n - | _ -> None + | None -> None + | Some [] -> None + | Some (n :: _) -> Some n -let tryFindSymbolFromBinary pe addr (name: byref) = +let tryFindSymbolFromBinary pe addr = match findSymFromIAT addr pe |> OrElse.bind (findSymFromEAT addr pe) with - | None -> false - | Some s -> name <- s; true + | None -> Error ErrorCase.SymbolNotFound + | Some s -> Ok s -let tryFindSymbolFromPDB pe addr (name: byref) = +let tryFindSymbolFromPDB pe addr = match Map.tryFind addr pe.SymbolInfo.SymbolByAddr with - | None -> false - | Some s -> name <- s.Name; true + | None -> Error ErrorCase.SymbolNotFound + | Some s -> Ok s.Name -let tryFindFuncSymb pe addr (name: byref) = - if pe.SymbolInfo.SymbolArray.Length = 0 then - tryFindSymbolFromBinary pe addr &name - else tryFindSymbolFromPDB pe addr &name +let tryFindFuncSymb pe addr = + if pe.SymbolInfo.SymbolArray.Length = 0 then tryFindSymbolFromBinary pe addr + else tryFindSymbolFromPDB pe addr let inline isValidAddr pe addr = IntervalSet.containsAddr addr pe.InvalidAddrRanges |> not @@ -292,14 +299,38 @@ let inline getNotInFileIntervals pe range = |> List.map (FileHelper.trimByRange range) |> List.toSeq -let isPE bytes offset = +let machineToArch = function + | Machine.I386 -> Arch.IntelX86 + | Machine.Amd64 | Machine.IA64 -> Arch.IntelX64 + | Machine.Arm -> Arch.ARMv7 + | Machine.Arm64 -> Arch.AARCH64 + | _ -> raise InvalidISAException + +let peHeadersToArch (peHeaders: PEHeaders) = + let corHeader = peHeaders.CorHeader + if isNull corHeader then + peHeaders.CoffHeader.Machine |> machineToArch + else + if corHeader.Flags = CorFlags.ILOnly then Arch.CILOnly + else + match peHeaders.CoffHeader.Machine with + | Machine.I386 -> Arch.CILIntel32 + | Machine.Amd64 | Machine.IA64 -> Arch.CILIntel64 + | _ -> raise InvalidISAException + +/// Return Architecture from the PE header. If the given binary is invalid, +/// return an Error. +let getPEArch bytes offset = try let bs = Array.sub bytes offset (Array.length bytes - offset) use stream = new IO.MemoryStream (bs) use reader = new PEReader (stream, PEStreamOptions.Default) - reader.PEHeaders.CoffHeader.Machine |> machineToArch |> ignore - true + peHeadersToArch reader.PEHeaders |> Ok with _ -> - false + Error ErrorCase.InvalidFileFormat + +let getISA pe = + let arch = peHeadersToArch pe.PEHeaders + ISA.Init arch Endian.Little // vim: set tw=80 sts=2 sw=2: diff --git a/src/BinFile/PEPDB.fs b/src/FrontEnd/BinFile/PEPDB.fs similarity index 99% rename from src/BinFile/PEPDB.fs rename to src/FrontEnd/BinFile/PEPDB.fs index 66229421..d556ca3d 100644 --- a/src/BinFile/PEPDB.fs +++ b/src/FrontEnd/BinFile/PEPDB.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.BinFile.PE.PDB +module internal B2R2.FrontEnd.BinFile.PE.PDB open System open B2R2 -open B2R2.BinFile.FileHelper +open B2R2.FrontEnd.BinFile.FileHelper /// Hold an MSF stream. type MSFStream = { diff --git a/src/BinFile/PEParser.fs b/src/FrontEnd/BinFile/PEParser.fs similarity index 87% rename from src/BinFile/PEParser.fs rename to src/FrontEnd/BinFile/PEParser.fs index 0353fc84..adda286f 100644 --- a/src/BinFile/PEParser.fs +++ b/src/FrontEnd/BinFile/PEParser.fs @@ -22,13 +22,13 @@ SOFTWARE. *) -module internal B2R2.BinFile.PE.Parser +module internal B2R2.FrontEnd.BinFile.PE.Parser open System open System.Reflection.PortableExecutable open B2R2 -open B2R2.BinFile -open B2R2.BinFile.PE.Helper +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.PE.Helper /// This is equivalent to GetContainingSectionIndex function except that we are /// using our own section header array here. This should be used instead of @@ -55,6 +55,11 @@ let isNULLImportDir tbl = && tbl.ImportDLLName = "" && tbl.ImportAddressTableRVA = 0 +let decodeForwardInfo (str: string) = + let strInfo = str.Split('.') + let dllName, funcName = strInfo.[0], strInfo.[1] + (dllName, funcName) + let readIDTEntry (binReader: BinReader) secs pos = { ImportLookupTableRVA = binReader.PeekInt32 pos ForwarderChain = binReader.PeekInt32 (pos + 8) @@ -158,20 +163,37 @@ let parseENPT (binReader: BinReader) secs edt = let offset2 = edt.OrdinalTableRVA |> getRawOffset secs loop [] edt.NumNamePointers offset1 offset2 +/// Decide the name of an exported address. The address may have been exported +/// only with ordinal, and does not have a corresponding name in export name +/// pointer table. In such case, consider its name as "#". +let private decideNameWithTable nameTbl ordBase idx = + match List.tryFind (fun (_, ord) -> int16 idx = ord) nameTbl with + | None -> sprintf "#%d" (int16 idx + ordBase) // Exported with an ordinal. + | Some (name, _) -> name // ENTP has a corresponding name for this entry. + let buildExportTable binReader baseAddr secs range edt = - let addrtbl = parseEAT binReader secs range edt - let folder map (name, ord) = - match addrtbl.[int ord] with + let addrTbl = parseEAT binReader secs range edt + let nameTbl = parseENPT binReader secs edt + let ordinalBase = int16 edt.OrdinalBase + let folder (expMap, forwMap) idx = function | ExportRVA rva -> let addr = addrFromRVA baseAddr rva - Map.add addr name map - | _ -> map - parseENPT binReader secs edt - |> List.fold folder Map.empty + let name = decideNameWithTable nameTbl ordinalBase idx + let expMap = + if not (Map.containsKey addr expMap) then Map.add addr [name] expMap + else Map.add addr (name :: Map.find addr expMap) expMap + expMap, forwMap + | ForwarderRVA rva -> + let name = decideNameWithTable nameTbl ordinalBase idx + let forwardStr = readStr secs binReader rva + let forwardInfo = decodeForwardInfo forwardStr + let forwMap = Map.add name forwardInfo forwMap + expMap, forwMap + Array.foldi folder (Map.empty, Map.empty) addrTbl |> fst let parseExports baseAddr binReader (headers: PEHeaders) secs = match headers.PEHeader.ExportTableDirectory.RelativeVirtualAddress with - | 0 -> Map.empty + | 0 -> Map.empty, Map.empty | rva -> let size = headers.PEHeader.ExportTableDirectory.Size let range = (rva, rva + size) @@ -272,18 +294,20 @@ let execRanges baseAddr secs = |> Array.fold (fun set s -> let saddr = baseAddr + uint64 s.VirtualAddress let eaddr = saddr + (uint64 <| getVirtualSectionSize s) - IntervalSet.add (AddrRange (saddr, eaddr)) set + IntervalSet.add (AddrRange (saddr, eaddr - 1UL)) set ) IntervalSet.empty let parseImage execpath rawpdb baseAddr binReader (hdrs: PEHeaders) = let wordSize = magicToWordSize hdrs.PEHeader.Magic - let baseAddr = hdrs.PEHeader.ImageBase + baseAddr + let baseAddr = defaultArg baseAddr hdrs.PEHeader.ImageBase let secs = hdrs.SectionHeaders |> Seq.toArray + let exportMap, forwardMap = parseExports baseAddr binReader hdrs secs { PEHeaders = hdrs BaseAddr = baseAddr SectionHeaders = secs ImportMap= parseImports binReader hdrs secs wordSize - ExportMap = parseExports baseAddr binReader hdrs secs + ExportMap = exportMap + ForwardMap = forwardMap RelocBlocks = parseRelocation binReader hdrs secs WordSize = wordSize SymbolInfo = getPDBSymbols execpath rawpdb |> buildPDBInfo baseAddr secs @@ -295,6 +319,7 @@ let parseImage execpath rawpdb baseAddr binReader (hdrs: PEHeaders) = let parseCoff baseAddr binReader (hdrs: PEHeaders) = let coff = hdrs.CoffHeader + let baseAddr = defaultArg baseAddr 0UL let wordSize = Coff.getWordSize coff.Machine let secs = hdrs.SectionHeaders |> Seq.toArray let idx = secs |> Array.findIndex (fun s -> s.Name.StartsWith ".text") @@ -304,6 +329,7 @@ let parseCoff baseAddr binReader (hdrs: PEHeaders) = SectionHeaders = secs ImportMap= Map.empty ExportMap = Map.empty + ForwardMap = Map.empty RelocBlocks = [] WordSize = wordSize SymbolInfo = Coff.getSymbols binReader coff diff --git a/src/BinFile/PETypes.fs b/src/FrontEnd/BinFile/PETypes.fs similarity index 96% rename from src/BinFile/PETypes.fs rename to src/FrontEnd/BinFile/PETypes.fs index b0d10d66..22fda65c 100644 --- a/src/BinFile/PETypes.fs +++ b/src/FrontEnd/BinFile/PETypes.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.BinFile.PE +namespace B2R2.FrontEnd.BinFile.PE open B2R2 open System.Reflection.PortableExecutable @@ -222,7 +222,7 @@ type SymFlags = | Managed = 0b0100 | MSIL = 0b1000 -/// PE symbol. We separate B2R2.BinFile.Symbol from format-specific symbol type +/// PE symbol. We separate B2R2.FrontEnd.BinFile.Symbol from format-specific symbol type /// for ease of analysis. type PESymbol = { Flags: SymFlags @@ -249,7 +249,9 @@ type PE = { /// RVA to import information. ImportMap: Map /// Address (VA) to exported function name. - ExportMap: Map + ExportMap: Map + /// Forward target symbol name to a (binary * function) tuple. + ForwardMap: Map /// List of relocation blocks RelocBlocks: RelocBlock list /// Word size for the binary. diff --git a/src/FrontEnd/BinFile/README.md b/src/FrontEnd/BinFile/README.md new file mode 100644 index 00000000..6b30fb43 --- /dev/null +++ b/src/FrontEnd/BinFile/README.md @@ -0,0 +1,12 @@ +# B2R2.FrontEnd.BinFile + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.BinFile Package? + +`B2R2.FrontEnd.BinFile` defines binary file parsers. It supports ELF, PE, +Mach-O, and Wasm file formats. diff --git a/src/BinFile/RawBinary.fs b/src/FrontEnd/BinFile/RawBinary.fs similarity index 68% rename from src/BinFile/RawBinary.fs rename to src/FrontEnd/BinFile/RawBinary.fs index 336a0e3a..7498b49e 100644 --- a/src/BinFile/RawBinary.fs +++ b/src/FrontEnd/BinFile/RawBinary.fs @@ -22,18 +22,25 @@ SOFTWARE. *) -namespace B2R2.BinFile +namespace B2R2.FrontEnd.BinFile open B2R2 +open System.Collections.Generic /// /// This class represents a raw binary file (containing only binary code and /// data without file format) /// -type RawFileInfo (bytes: byte [], isa, baseAddr) = - inherit FileInfo (baseAddr) +type RawFileInfo (bytes: byte [], path, isa, baseAddr) = + inherit FileInfo () + let baseAddr = defaultArg baseAddr 0UL + let size = bytes.Length + let usize = uint64 size + let reader = BinReader.Init (bytes, isa.Endian) - override __.BinReader = BinReader.Init (bytes, isa.Endian) + let symbolMap = Dictionary () + + override __.BinReader = reader override __.FileFormat = FileFormat.RawBinary @@ -41,7 +48,7 @@ type RawFileInfo (bytes: byte [], isa, baseAddr) = override __.FileType = FileType.UnknownFile - override __.FilePath = "" + override __.FilePath = path override __.WordSize = isa.WordSize @@ -59,9 +66,13 @@ type RawFileInfo (bytes: byte [], isa, baseAddr) = override __.TranslateAddress addr = System.Convert.ToInt32 (addr - baseAddr) - override __.GetSymbols () = Seq.empty + override __.AddSymbol addr symbol = + symbolMap.[addr] <- symbol + + override __.GetSymbols () = + Seq.map (fun (KeyValue(k, v)) -> v) symbolMap - override __.GetStaticSymbols () = Seq.empty + override __.GetStaticSymbols () = __.GetSymbols () override __.GetDynamicSymbols (?_excludeImported) = Seq.empty @@ -69,12 +80,13 @@ type RawFileInfo (bytes: byte [], isa, baseAddr) = override __.GetSections () = Seq.singleton { Address = baseAddr + FileOffset = 0UL Kind = SectionKind.ExecutableSection - Size = uint64 bytes.LongLength + Size = usize Name = "" } override __.GetSections (addr: Addr) = - if addr >= baseAddr && addr < (baseAddr + uint64 bytes.LongLength) then + if addr >= baseAddr && addr < (baseAddr + usize) then __.GetSections () else Seq.empty @@ -85,20 +97,30 @@ type RawFileInfo (bytes: byte [], isa, baseAddr) = override __.GetSegments (_isLoadable) = Seq.singleton { Address = baseAddr - Size = uint64 bytes.LongLength + Size = usize Permission = Permission.Readable ||| Permission.Executable } override __.GetLinkageTableEntries () = Seq.empty override __.IsLinkageTable _ = false - override __.TryFindFunctionSymbolName (_addr, _) = false + override __.TryFindFunctionSymbolName (_addr) = + if symbolMap.ContainsKey(_addr) then Ok symbolMap.[_addr].Name + else Error ErrorCase.SymbolNotFound + + override __.ExceptionTable = ARMap.empty + + override __.ToBinaryPointer addr = + if addr = baseAddr then BinaryPointer (baseAddr, 0, size) + else BinaryPointer.Null + + override __.ToBinaryPointer (_name: string) = BinaryPointer.Null override __.IsValidAddr (addr) = - addr >= baseAddr && addr < (baseAddr + uint64 bytes.LongLength) + addr >= baseAddr && addr < (baseAddr + usize) override __.IsValidRange (range) = - __.IsValidAddr range.Min && __.IsValidAddr (range.Max - 1UL) + __.IsValidAddr range.Min && __.IsValidAddr range.Max override __.IsInFileAddr (addr) = __.IsValidAddr (addr) @@ -107,16 +129,6 @@ type RawFileInfo (bytes: byte [], isa, baseAddr) = override __.IsExecutableAddr addr = __.IsValidAddr addr override __.GetNotInFileIntervals range = - let lastAddr = baseAddr + uint64 bytes.LongLength - if range.Max <= baseAddr then Seq.singleton range - elif range.Max <= lastAddr && range.Min < baseAddr then - Seq.singleton (AddrRange (range.Min, baseAddr)) - elif range.Max > lastAddr && range.Min < baseAddr then - [ AddrRange (range.Min, baseAddr); AddrRange (lastAddr, range.Max) ] - |> List.toSeq - elif range.Max > lastAddr && range.Min <= lastAddr then - Seq.singleton (AddrRange (lastAddr, range.Max)) - elif range.Max > lastAddr && range.Min > lastAddr then Seq.singleton range - else Seq.empty + FileHelper.getNotInFileIntervals baseAddr usize range // vim: set tw=80 sts=2 sw=2: diff --git a/src/BinFile/Wasm.fs b/src/FrontEnd/BinFile/Wasm.fs similarity index 79% rename from src/BinFile/Wasm.fs rename to src/FrontEnd/BinFile/Wasm.fs index f266e98d..0e090b91 100644 --- a/src/BinFile/Wasm.fs +++ b/src/FrontEnd/BinFile/Wasm.fs @@ -22,21 +22,22 @@ SOFTWARE. *) -namespace B2R2.BinFile +namespace B2R2.FrontEnd.BinFile open B2R2 -open B2R2.BinFile.Wasm -open B2R2.BinFile.Wasm.Helper +open B2R2.FrontEnd.BinFile.Wasm +open B2R2.FrontEnd.BinFile.Wasm.Helper /// /// This class represents a Web Assembly /// (Wasm Module) binary file. /// type WasmFileInfo (bytes, path, baseAddr) = - inherit FileInfo (baseAddr) + inherit FileInfo () let wm = Parser.parse bytes + let baseAddr = defaultArg baseAddr 0UL - new (bytes, path) = WasmFileInfo (bytes, path, 0UL) + new (bytes, path) = WasmFileInfo (bytes, path, None) override __.BinReader = wm.BinReader override __.FileFormat = FileFormat.WasmBinary override __.ISA = defaultISA @@ -46,10 +47,11 @@ type WasmFileInfo (bytes, path, baseAddr) = override __.IsStripped = List.length wm.CustomSections = 0 override __.IsNXEnabled = true override __.IsRelocatable = false - override __.BaseAddress = 0UL + override __.BaseAddress = baseAddr override __.EntryPoint = entryPointOf wm override __.TextStartAddr = textStartAddrOf wm override __.TranslateAddress addr = int addr + override __.AddSymbol addr symbol = Utils.futureFeature () override __.GetSymbols () = getSymbols wm override __.GetStaticSymbols () = Seq.empty override __.GetDynamicSymbols (?exc) = getDynamicSymbols wm exc @@ -61,7 +63,12 @@ type WasmFileInfo (bytes, path, baseAddr) = override __.GetSegments (_isLoadable) = Seq.empty override __.GetLinkageTableEntries () = getImports wm override __.IsLinkageTable _addr = Utils.futureFeature () // FIXME - override __.TryFindFunctionSymbolName (addr, n) = tryFindFunSymName wm addr &n + override __.TryFindFunctionSymbolName (addr) = tryFindFunSymName wm addr + override __.ExceptionTable = ARMap.empty + override __.ToBinaryPointer addr = + BinaryPointer.OfSectionOpt (getSectionsByAddr wm addr |> Seq.tryHead) + override __.ToBinaryPointer name = + BinaryPointer.OfSectionOpt (getSectionsByName wm name |> Seq.tryHead) override __.IsValidAddr (addr) = addr >= 0UL && addr < (uint64 bytes.LongLength) override __.IsValidRange range = @@ -70,4 +77,4 @@ type WasmFileInfo (bytes, path, baseAddr) = override __.IsInFileRange range = __.IsValidRange range override __.IsExecutableAddr _addr = Utils.futureFeature () // FIXME override __.GetNotInFileIntervals range = - getNotInFileIntervals range bytes.LongLength + FileHelper.getNotInFileIntervals 0UL (uint64 bytes.LongLength) range diff --git a/src/BinFile/WasmExpression.fs b/src/FrontEnd/BinFile/WasmExpression.fs similarity index 95% rename from src/BinFile/WasmExpression.fs rename to src/FrontEnd/BinFile/WasmExpression.fs index fab4ca98..0400f8ad 100644 --- a/src/BinFile/WasmExpression.fs +++ b/src/FrontEnd/BinFile/WasmExpression.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module internal B2R2.BinFile.Wasm.Expression +module internal B2R2.FrontEnd.BinFile.Wasm.Expression open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile open System let peekConstExpr (reader: BinReader) offset = diff --git a/src/BinFile/WasmHeader.fs b/src/FrontEnd/BinFile/WasmHeader.fs similarity index 96% rename from src/BinFile/WasmHeader.fs rename to src/FrontEnd/BinFile/WasmHeader.fs index a1cbd284..7cdc4324 100644 --- a/src/BinFile/WasmHeader.fs +++ b/src/FrontEnd/BinFile/WasmHeader.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module internal B2R2.BinFile.Wasm.Header +module internal B2R2.FrontEnd.BinFile.Wasm.Header open B2R2 diff --git a/src/BinFile/WasmHelper.fs b/src/FrontEnd/BinFile/WasmHelper.fs similarity index 84% rename from src/BinFile/WasmHelper.fs rename to src/FrontEnd/BinFile/WasmHelper.fs index c6b65783..19ca0594 100644 --- a/src/BinFile/WasmHelper.fs +++ b/src/FrontEnd/BinFile/WasmHelper.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module internal B2R2.BinFile.Wasm.Helper +module internal B2R2.FrontEnd.BinFile.Wasm.Helper open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile let defaultISA = //FIXME @@ -66,13 +66,12 @@ let importDescToSymKind desc = | ImpGlobal _ -> SymbolKind.ObjectType let importEntryToSymbol (importEntry: Import) = - { - Address = uint64 importEntry.Offset + { Address = uint64 importEntry.Offset Name = importEntry.Name Kind = importDescToSymKind importEntry.Desc Target = TargetKind.DynamicSymbol LibraryName = importEntry.ModuleName - } + ArchOperationMode = ArchOperationMode.NoMode } let exportDescToSymKind desc = match desc with @@ -82,13 +81,12 @@ let exportDescToSymKind desc = | ExpGlobal _ -> SymbolKind.ObjectType let exportEntryToSymbol (exportEntry: Export) = - { - Address = uint64 exportEntry.Offset + { Address = uint64 exportEntry.Offset Name = exportEntry.Name Kind = exportDescToSymKind exportEntry.Desc Target = TargetKind.DynamicSymbol LibraryName = "" - } + ArchOperationMode = ArchOperationMode.NoMode } let getDynamicSymbols wm excludeImported = let excludeImported = defaultArg excludeImported false @@ -127,12 +125,11 @@ let sectionIdToKind id = | _ -> SectionKind.ExtraSection let secSummaryToGenericSection (secSumm: SectionSummary) = - { - Address = uint64 secSumm.Offset + { Address = uint64 secSumm.Offset + FileOffset = uint64 secSumm.Offset Kind = sectionIdToKind secSumm.Id Size = uint64 (secSumm.HeaderSize + secSumm.ContentsSize) - Name = secSumm.Name - } + Name = secSumm.Name } let getSections wm = wm.SectionsInfo.SecArray @@ -174,7 +171,7 @@ let getImports wm = | None -> Seq.empty | None -> Seq.empty -let tryFindFunSymName wm addr (name: byref) = +let tryFindFunSymName wm addr = let sym = getSymbols wm |> Seq.filter (fun s -> @@ -184,20 +181,5 @@ let tryFindFunSymName wm addr (name: byref) = ) |> Seq.tryHead match sym with - | Some s -> name <- s.Name; true - | None -> false - -let getNotInFileIntervals (range: AddrRange) (len: int64) = - let maxAddr = uint64 len - if range.Max <= 0UL then Seq.singleton range - elif range.Max <= maxAddr && range.Min < 0UL - then Seq.singleton (AddrRange (range.Min, 0UL)) - elif range.Max > maxAddr && range.Min < 0UL then - [ AddrRange (range.Min, 0UL); - AddrRange (maxAddr, range.Max) ] - |> List.toSeq - elif range.Max > maxAddr && range.Min <= maxAddr - then Seq.singleton (AddrRange (maxAddr, range.Max)) - elif range.Max > maxAddr && range.Min > maxAddr - then Seq.singleton range - else Seq.empty \ No newline at end of file + | Some s -> Ok s.Name + | None -> Error ErrorCase.SymbolNotFound \ No newline at end of file diff --git a/src/BinFile/WasmParser.fs b/src/FrontEnd/BinFile/WasmParser.fs similarity index 98% rename from src/BinFile/WasmParser.fs rename to src/FrontEnd/BinFile/WasmParser.fs index f91ded12..10f72a50 100644 --- a/src/BinFile/WasmParser.fs +++ b/src/FrontEnd/BinFile/WasmParser.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.BinFile.Wasm.Parser +module internal B2R2.FrontEnd.BinFile.Wasm.Parser open B2R2 -open B2R2.BinFile -open B2R2.BinFile.Wasm.Section +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.Wasm.Section open System let sectionIdToName (secId: SectionId) (off: int) = diff --git a/src/BinFile/WasmSection.fs b/src/FrontEnd/BinFile/WasmSection.fs similarity index 98% rename from src/BinFile/WasmSection.fs rename to src/FrontEnd/BinFile/WasmSection.fs index 2c433569..810a2a13 100644 --- a/src/BinFile/WasmSection.fs +++ b/src/FrontEnd/BinFile/WasmSection.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.BinFile.Wasm.Section +module internal B2R2.FrontEnd.BinFile.Wasm.Section open B2R2 -open B2R2.BinFile -open B2R2.BinFile.Wasm.Expression +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.Wasm.Expression open System.Text let peekVectorLen (reader: BinReader) offset = diff --git a/src/BinFile/WasmTypes.fs b/src/FrontEnd/BinFile/WasmTypes.fs similarity index 98% rename from src/BinFile/WasmTypes.fs rename to src/FrontEnd/BinFile/WasmTypes.fs index 6e45a434..cd72a0f8 100644 --- a/src/BinFile/WasmTypes.fs +++ b/src/FrontEnd/BinFile/WasmTypes.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -namespace B2R2.BinFile.Wasm +namespace B2R2.FrontEnd.BinFile.Wasm open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile type Vector<'TElement> = { /// Length of encoded elements diff --git a/src/FrontEnd/BinInterface/B2R2.FrontEnd.BinInterface.fsproj b/src/FrontEnd/BinInterface/B2R2.FrontEnd.BinInterface.fsproj new file mode 100644 index 00000000..5ae7f77c --- /dev/null +++ b/src/FrontEnd/BinInterface/B2R2.FrontEnd.BinInterface.fsproj @@ -0,0 +1,37 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 frontend main interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FrontEnd/BinInterface/BinHandle.fs b/src/FrontEnd/BinInterface/BinHandle.fs new file mode 100644 index 00000000..679e9747 --- /dev/null +++ b/src/FrontEnd/BinInterface/BinHandle.fs @@ -0,0 +1,285 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinInterface + +open System +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinInterface.Helper + +type BinHandle = { + ISA: ISA + FileInfo: FileInfo + DisasmHelper: DisasmHelper + TranslationContext: TranslationContext + Parser: Parser + RegisterBay: RegisterBay + OS: OS +} +with + static member private Init (isa, mode, autoDetect, baseAddr, bs, path, os) = + let fmt, isa, os = identifyFormatAndISAAndOS bs isa os autoDetect + let struct (ctxt, regbay) = initBasis isa + let fi = newFileInfo bs baseAddr path fmt isa regbay + assert (isa = fi.ISA) + let parser = initParser isa mode fi + { ISA = isa + FileInfo = fi + DisasmHelper = DisasmHelper (fi.TryFindFunctionSymbolName) + TranslationContext = ctxt + Parser = parser + RegisterBay = regbay + OS = os } + + static member Init (isa, archMode, autoDetect, baseAddr, bytes) = + BinHandle.Init (isa, archMode, autoDetect, baseAddr, bytes, "", None) + + static member Init (isa, archMode, autoDetect, baseAddr, fileName) = + let bytes = IO.File.ReadAllBytes fileName + let fileName = IO.Path.GetFullPath fileName + BinHandle.Init (isa, archMode, autoDetect, baseAddr, bytes, fileName, None) + + static member Init (isa, baseAddr, fileName) = + let bytes = IO.File.ReadAllBytes fileName + let fileName = IO.Path.GetFullPath fileName + let defaultMode = ArchOperationMode.NoMode + BinHandle.Init (isa, defaultMode, true, baseAddr, bytes, fileName, None) + + static member Init (isa, fileName) = + BinHandle.Init (isa=isa, baseAddr=None, fileName=fileName) + + static member Init (isa, baseAddr, bytes) = + let defaultMode = ArchOperationMode.NoMode + BinHandle.Init (isa, defaultMode, false, baseAddr, bytes, "", None) + + static member Init (isa, bytes) = + BinHandle.Init (isa=isa, baseAddr=None, bytes=bytes) + + static member Init (isa, archMode) = + BinHandle.Init (isa, archMode, false, None, [||], "", None) + + static member Init (isa, os) = + let defaultMode = ArchOperationMode.NoMode + BinHandle.Init (isa, defaultMode, false, None, [||], "", Some os) + + static member Init (isa: ISA) = BinHandle.Init (isa, ([||]: byte [])) + + static member UpdateCode hdl addr bs = + { hdl with FileInfo = RawFileInfo (bs, "", hdl.ISA, Some addr) :> FileInfo } + + static member private UpdateFileInfo h fi = + { h with FileInfo = fi } + + static member PatchCode hdl addr (bs: byte []) = + let fi = hdl.FileInfo + let reader = fi.BinReader + let idx = int <| addr - fi.BaseAddress + let lastIdx = idx + bs.Length - 1 + if reader.IsOutOfRange idx || reader.IsOutOfRange lastIdx then + Error ErrorCase.InvalidMemoryRead + else + let bs = + reader.Bytes.[ idx + Array.length bs .. ] + |> Array.append bs + |> Array.append reader.Bytes.[ .. idx - 1 ] + match fi with + | :? RawFileInfo -> + RawFileInfo (bs, fi.FilePath, fi.ISA, Some fi.BaseAddress) :> FileInfo + |> BinHandle.UpdateFileInfo hdl + |> Ok + | :? ELFFileInfo as fi -> + ELFFileInfo (bs, fi.FilePath, Some fi.BaseAddress, fi.RegisterBay) + :> FileInfo + |> BinHandle.UpdateFileInfo hdl + |> Ok + | :? MachFileInfo -> + MachFileInfo (bs, fi.FilePath, fi.ISA, Some fi.BaseAddress) :> FileInfo + |> BinHandle.UpdateFileInfo hdl + |> Ok + | :? PEFileInfo as fi -> + PEFileInfo (bs, fi.FilePath, Some fi.BaseAddress, fi.RawPDB) :> FileInfo + |> BinHandle.UpdateFileInfo hdl + |> Ok + | :? WasmFileInfo -> + WasmFileInfo (bs, fi.FilePath, Some fi.BaseAddress) :> FileInfo + |> BinHandle.UpdateFileInfo hdl + |> Ok + | _ -> Error ErrorCase.InvalidFileFormat + + member __.ReadBytes (addr: Addr, nBytes) = + BinHandle.ReadBytes (__, addr, nBytes) + + member __.ReadBytes (bp: BinaryPointer, nBytes) = + BinHandle.ReadBytes (__, bp, nBytes) + + static member TryReadBytes ({ FileInfo = fi }, addr, nBytes) = + let range = AddrRange (addr, addr + uint64 nBytes - 1UL) + if fi.IsInFileRange range then + fi.BinReader.PeekBytes (nBytes, fi.TranslateAddress addr) |> Ok + elif fi.IsValidRange range then + fi.GetNotInFileIntervals range + |> classifyRanges range + |> List.fold (fun bs (range, isInFile) -> + let len = (range.Max - range.Min |> int) + 1 + if isInFile then + let addr = fi.TranslateAddress range.Min + fi.BinReader.PeekBytes (len, addr) + |> Array.append bs + else Array.create len 0uy |> Array.append bs + ) [||] + |> Ok + else Error ErrorCase.InvalidMemoryRead + + static member TryReadBytes ({ FileInfo = fi }, bp, nBytes) = + if BinaryPointer.IsValidAccess bp nBytes then + fi.BinReader.PeekBytes (nBytes, bp.Offset) |> Ok + else Error ErrorCase.InvalidMemoryRead + + static member ReadBytes (hdl, addr: Addr, nBytes) = + match BinHandle.TryReadBytes (hdl, addr, nBytes) with + | Ok bs -> bs + | Error e -> invalidArg (nameof addr) (ErrorCase.toString e) + + static member ReadBytes (hdl, bp: BinaryPointer, nBytes) = + match BinHandle.TryReadBytes (hdl, bp, nBytes) with + | Ok bs -> bs + | Error e -> invalidArg (nameof bp) (ErrorCase.toString e) + + member __.ReadInt (addr: Addr, size) = + BinHandle.ReadInt (__, addr, size) + + member __.ReadInt (bp: BinaryPointer, size) = + BinHandle.ReadInt (__, bp, size) + + static member TryReadInt ({ FileInfo = fi }, addr, size) = + let pos = fi.TranslateAddress addr + if pos >= fi.BinReader.Bytes.Length || pos < 0 then + Error ErrorCase.InvalidMemoryRead + else readIntBySize fi pos size + + static member TryReadInt ({ FileInfo = fi }, bp, size) = + if BinaryPointer.IsValidAccess bp size then + readIntBySize fi bp.Offset size + else Error ErrorCase.InvalidMemoryRead + + static member ReadInt (hdl, addr: Addr, size) = + match BinHandle.TryReadInt (hdl, addr, size) with + | Ok i -> i + | Error e -> invalidArg (nameof addr) (ErrorCase.toString e) + + static member ReadInt (hdl, bp: BinaryPointer, size) = + match BinHandle.TryReadInt (hdl, bp, size) with + | Ok i -> i + | Error e -> invalidArg (nameof bp) (ErrorCase.toString e) + + member __.ReadUInt (addr: Addr, size) = + BinHandle.ReadUInt (__, addr, size) + + member __.ReadUInt (bp: BinaryPointer, size) = + BinHandle.ReadUInt (__, bp, size) + + static member TryReadUInt ({ FileInfo = fi }, addr, size) = + let pos = fi.TranslateAddress addr + if pos >= fi.BinReader.Bytes.Length || pos < 0 then + Error ErrorCase.InvalidMemoryRead + else readUIntBySize fi pos size + + static member TryReadUInt ({ FileInfo = fi }, bp, size) = + if BinaryPointer.IsValidAccess bp size then + readUIntBySize fi bp.Offset size + else Error ErrorCase.InvalidMemoryRead + + static member ReadUInt (hdl, addr: Addr, size) = + match BinHandle.TryReadUInt (hdl, addr, size) with + | Ok i -> i + | Error e -> invalidArg (nameof addr) (ErrorCase.toString e) + + static member ReadUInt (hdl, bp: BinaryPointer, size) = + match BinHandle.TryReadUInt (hdl, bp, size) with + | Ok i -> i + | Error e -> invalidArg (nameof bp) (ErrorCase.toString e) + + member __.ReadASCII (addr: Addr) = + BinHandle.ReadASCII (__, addr) + + member __.ReadASCII (bp: BinaryPointer) = + BinHandle.ReadASCII (__, bp) + + static member ReadASCII ({ FileInfo = fi }, addr) = + let bs = fi.TranslateAddress addr |> readASCII fi + ByteArray.extractCString bs 0 + + static member ReadASCII ({ FileInfo = fi }, bp: BinaryPointer) = + let bs = readASCII fi bp.Offset + ByteArray.extractCString bs 0 + + static member ParseInstr (hdl: BinHandle, addr) = + parseInstrFromAddr hdl.FileInfo hdl.Parser addr + + static member ParseInstr (hdl: BinHandle, bp: BinaryPointer) = + parseInstrFromBinPtr hdl.FileInfo hdl.Parser bp + + static member TryParseInstr (hdl, addr) = + tryParseInstrFromAddr hdl.FileInfo hdl.Parser addr + + static member TryParseInstr (hdl, bp: BinaryPointer) = + tryParseInstrFromBinPtr hdl.FileInfo hdl.Parser bp + + static member ParseBBlock (hdl, addr) = + parseBBLFromAddr hdl.FileInfo hdl.Parser addr + + static member ParseBBlock (hdl, bp) = + parseBBLFromBinPtr hdl.FileInfo hdl.Parser bp + + static member inline LiftInstr (hdl: BinHandle) (ins: Instruction) = + ins.Translate hdl.TranslationContext + + static member LiftOptimizedInstr hdl (ins: Instruction) = + BinHandle.LiftInstr hdl ins |> LocalOptimizer.Optimize + + static member LiftBBlock (hdl: BinHandle, addr: Addr) = + liftBBLFromAddr hdl.FileInfo hdl.Parser hdl.TranslationContext addr + + static member LiftBBlock (hdl: BinHandle, bp: BinaryPointer) = + liftBBLFromBinPtr hdl.FileInfo hdl.Parser hdl.TranslationContext bp + + static member inline DisasmInstr hdl showAddr resolveSymbol ins = + (ins: Instruction).Disasm (showAddr, resolveSymbol, hdl.DisasmHelper) + + static member inline DisasmInstrSimple (ins: Instruction) = + ins.Disasm () + + static member DisasmBBlock (hdl, showAddr, resolveSymbol, addr) = + disasmBBLFromAddr + hdl.FileInfo hdl.Parser hdl.DisasmHelper showAddr resolveSymbol addr + + static member DisasmBBlock (hdl, showAddr, resolveSymbol, bp) = + disasmBBLFromBinPtr + hdl.FileInfo hdl.Parser hdl.DisasmHelper showAddr resolveSymbol bp + + static member Optimize stmts = LocalOptimizer.Optimize stmts + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinInterface/BinHandle.fsi b/src/FrontEnd/BinInterface/BinHandle.fsi new file mode 100644 index 00000000..3b9d9290 --- /dev/null +++ b/src/FrontEnd/BinInterface/BinHandle.fsi @@ -0,0 +1,630 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinInterface + +open B2R2 +open B2R2.BinIR +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinLifter + +/// The main handle for reading/parsing a binary code. BinHandle essentially +/// provides a low-level interface for a chunk of binary code. One can use +/// BinHandle to parse/lift/disassemble instructions at a specific address or to +/// access file-specific data. +type BinHandle = { + ISA: ISA + FileInfo: FileInfo + DisasmHelper: DisasmHelper + TranslationContext: TranslationContext + Parser: Parser + RegisterBay: RegisterBay + OS: OS +} +with + /// + /// Return the byte array of size (nBytes) at the addr from the current + /// binary. + /// + /// The address. + /// The size of the byte array (in bytes). + /// + /// Return the byte array if succeed. Otherwise, raise an exception. + /// + member ReadBytes: addr: Addr * nBytes: int -> byte [] + + /// + /// Return the byte array of size (nBytes) pointed to by the binary pointer + /// (bp). + /// + /// BInaryPointer. + /// The size of the byte array (in bytes). + /// + /// Return the byte array if succeed. Otherwise, raise an exception. + /// + member ReadBytes: bp: BinaryPointer * nBytes: int -> byte [] + + /// + /// Return the corresponding integer value at the addr of the size from the + /// current binary. + /// + /// The address. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding integer (int64). + /// + member ReadInt: addr: Addr * size: int -> int64 + + /// + /// Return the corresponding integer value of the size from the current + /// binary, which is pointed to by the binary pointer (bp). + /// + /// The binary pointer. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding integer (int64). + /// + member ReadInt: bp: BinaryPointer * size: int -> int64 + + /// + /// Return the corresponding unsigned integer value at the addr of the size + /// from the binary. + /// + /// The address. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding unsigned integer (uint64). + /// + member ReadUInt: addr: Addr * size: int -> uint64 + + /// + /// Return the corresponding unsigned integer value of the size from the + /// binary, which is pointed to by the binary pointer (bp). + /// + /// BinaryPointer. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding unsigned integer (uint64). + /// + member ReadUInt: bp: BinaryPointer * size: int -> uint64 + + /// + /// Return the ASCII string at the addr from the given BinHandle. + /// + /// The address. + /// + /// Return the corresponding ASCII string. + /// + member ReadASCII: addr: Addr -> string + + /// + /// Return the ASCII string pointed to by the binary pointer from the given + /// BinHandle. + /// + /// BinaryPointer. + /// + /// Return the corresponding ASCII string. + /// + member ReadASCII: bp: BinaryPointer -> string + + /// + /// Initialize a BInHnalder from a given binary byte sequence. This function + /// will read the byte sequence and automatically detect its binary format + /// if autoDetect is true. Otherwise, it will consider the given binary + /// sequence as a raw binary (just a series of machine instructions without + /// specific file format). + /// + /// ISA. + /// ArchOperatinoMode. + /// Perform auto format detection or not. + /// Base address for calculating instruction + /// addresses. + /// Raw binary sequence. + /// BinHandle. + static member Init: + isa: ISA + * archMode: ArchOperationMode + * autoDetect: bool + * baseAddr: Addr option + * bytes: byte [] + -> BinHandle + + /// + /// Initialize a BinHandle from a given binary file (fileName). This + /// function will read the file and parse it. It will automatically detect + /// the file format if autoDetect is true. Otherwise, it will cnosider the + /// file as a raw binary. + /// + /// ISA. + /// ArchOperatinoMode. + /// Whether to perform auto format detection. + /// Base address for calculating instruction + /// addresses. + /// Binary file. + /// BinHandle. + static member Init: + isa: ISA + * archMode: ArchOperationMode + * autoDetect: bool + * baseAddr: Addr option + * fileName: string + -> BinHandle + + /// + /// Initialize a BinHandle from an ISA and a binary file path, assuming + /// that the archMode is NoMode. This function behaves the same as the + /// 2-argument constructor Init (isa, fileName), with a difference of using + /// the specified base address when initializing the BinHandle. + /// + /// ISA. + /// Base address. + /// Binary file path. + /// BinHandle. + static member Init: + isa: ISA * baseAddr: Addr option * fileName: string -> BinHandle + + /// + /// Initialize a BinHandle from an ISA and a byte sequence, assuming that + /// the archMode is NoMode. This function behaves the same as the 2-argument + /// constructor Init (isa, bytes), with a difference of using the specified + /// base address when initializing the BinHandle. + /// + /// ISA. + /// Base address. + /// Byte sequence. + /// BinHandle. + static member Init: + isa: ISA * baseAddr: Addr option * bytes: byte [] -> BinHandle + + /// + /// Initialize a BinHandle from an ISA and a binary file path, assuming + /// that the archMode is NoMode. B2R2 will automatically detect the file + /// format of the given binary file, but it will refer to the given ISA + /// parameter either when the binary has multiple architectures, e.g., a fat + /// binary on macOS, or when B2R2 cannot recognize the given file format. If + /// the given binary file does not follow the known formats, then B2R2 + /// consider it as a raw binary with base address at 0. + /// + /// ISA. + /// Binary file path. + /// BinHandle. + static member Init: isa: ISA * fileName: string -> BinHandle + + /// + /// Initialize a BinHandle from an ISA and a byte sequence, assuming that + /// the archMode is NoMode, and the format is RawBinary. + /// + /// ISA. + /// Byte sequence. + /// BinHandle. + static member Init: isa: ISA * bytes: byte [] -> BinHandle + + /// + /// Initialize an empty BinHandle. This function is useful when you want to + /// delay loading the actual body of your binary blob. + /// + /// ISA. + /// ArchOperatinoMode. + /// BinHandle. + static member Init: isa: ISA * archMode: ArchOperationMode -> BinHandle + + /// + /// Initialize an empty BinHandle solely from an ISA, assuming that the + /// archMode is NoMode, and the format is RawBinary. This function is useful + /// when you want to delay loading the actual body of your binary blob. + /// + /// ISA. + /// BinHandle. + static member Init: isa: ISA -> BinHandle + + /// + /// Initialize an empty BinHandle. This function is useful when you want to + /// delay loading the actual body of your binary blob but also want to + /// specify the os. + /// + /// ISA. + /// OS. + /// BinHandle. + static member Init: isa: ISA * os: OS -> BinHandle + + /// + /// Update BinHandle to have new code at a new address (addr). BinHandle + /// is *immutable*. + /// + /// The BinHandle to update. + /// The new address to use. + /// The new code in bytes. + /// New BinHandle. + static member UpdateCode: + hdl: BinHandle -> addr: Addr -> bs: byte [] -> BinHandle + + /// + /// Update BinHandle to patch the code at the address (addr). BinHandle + /// is *immutable*. + /// + /// The BinHandle to update. + /// The new address to use. + /// The new code in bytes. + /// + /// Return (BinHandle) if succeeded, (ErrorCase) otherwise. + /// + static member PatchCode: + hdl: BinHandle -> addr: Addr -> bs: byte [] -> Result + + /// + /// Return the byte array of size (nBytes) at the addr from the given + /// BinHandle (hdl). The return value is an option type. When the given + /// address is invalid, this function returns None. + /// + /// BinHandle. + /// The address. + /// The size of the byte array (in bytes). + /// + /// Return (byte []) if succeeded, (ErrorCase) otherwise. + /// + static member TryReadBytes: + hdl: BinHandle * addr: Addr * nBytes: int -> Result + + /// + /// Return the byte array of size (nBytes) from the BinHandler (hdl), which + /// is pointed to by the BinaryPointer (bp). The return value is an option + /// type. When the given address is invalid, this function returns None. + /// + /// BinHandle. + /// BinaryPointer. + /// The size of the byte array (in bytes). + /// + /// Return (byte []) if succeeded, (ErrorCase) otherwise. + /// + static member TryReadBytes: + hdl: BinHandle * bp: BinaryPointer * nBytes: int + -> Result + + /// + /// Return the byte array of size (nBytes) at the addr from the given + /// BinHandle. + /// + /// BinHandle. + /// The address. + /// The size of the byte array (in bytes). + /// + /// Return the byte array if succeed. Otherwise, raise an exception. + /// + static member ReadBytes: + hdl: BinHandle * addr: Addr * nBytes: int -> byte [] + + /// + /// Return the byte array of size (nBytes) from the given BinHandle, which + /// is pointed to by the BinaryPointer (bp). + /// + /// BinHandle. + /// BinaryPointer. + /// The size of the byte array (in bytes). + /// + /// Return the byte array if succeed. Otherwise, raise an exception. + /// + static member ReadBytes: + hdl: BinHandle * bp: BinaryPointer * nBytes: int -> byte [] + + /// + /// Return the corresponding integer option value at the addr of the size + /// from the given BinHandle. + /// + /// BinHandle. + /// The address. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding value (int64) if the address and the size is + /// valid. Otherwise ErrorCase. + /// + static member TryReadInt: + hdl: BinHandle * addr: Addr * size: int -> Result + + /// + /// Return the corresponding integer option value of the size from the given + /// BinHandle (hdl), which is pointed to by the binary pointer (bp). + /// + /// BinHandle. + /// BinaryPointer. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding value (int64) if the address and the size is + /// valid. Otherwise ErrorCase. + /// + static member TryReadInt: + hdl: BinHandle * bp: BinaryPointer * size: int -> Result + + /// + /// Return the corresponding integer value at the addr of the size from the + /// given BinHandle. + /// + /// BinHandle. + /// The address. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding integer (int64). + /// + static member ReadInt: + hdl: BinHandle * addr: Addr * size: int -> int64 + + /// + /// Return the corresponding integer value of the size from the given + /// BinHandle (hdl), which is pointed to by the binary pointer (bp). + /// + /// BinHandle. + /// BinaryPointer. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding integer (int64). + /// + static member ReadInt: + hdl: BinHandle * bp: BinaryPointer * size: int -> int64 + + /// + /// Return the corresponding unsigned integer option value at the addr of + /// the size from the given BinHandle. + /// + /// BinHandle. + /// The address. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding unsigned integer (uint64) if the address and + /// the size is valid. Otherwise, ErrorCase. + /// + static member TryReadUInt: + hdl: BinHandle * addr: Addr * size: int -> Result + + /// + /// Return the corresponding unsigned integer option value of the size from + /// the given BinHandle (hdl), which is pointed to by the binary pointer + /// (bp). + /// + /// BinHandle. + /// BinaryPointer. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding unsigned integer (uint64) if the address and + /// the size is valid. Otherwise, ErrorCase. + /// + static member TryReadUInt: + hdl: BinHandle * bp: BinaryPointer * size: int -> Result + + /// + /// Return the corresponding unsigned integer value at the addr of the size + /// from the given BinHandle. + /// + /// BinHandle. + /// The address. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding unsigned integer (uint64). + /// + static member ReadUInt: + hdl: BinHandle * addr: Addr * size: int -> uint64 + + /// + /// Return the corresponding unsigned integer value of the size from the + /// given BinHandle (hdl), which is pointed to by the binary pointer (bp). + /// + /// BinHandle. + /// BinaryPointer. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding unsigned integer (uint64). + /// + static member ReadUInt: + hdl: BinHandle * bp: BinaryPointer * size: int -> uint64 + + /// + /// Return the ASCII string at the addr from the given BinHandle. + /// + /// BinHandle. + /// The address. + /// + /// Return the corresponding ASCII string. + /// + static member ReadASCII: + hdl: BinHandle * addr: Addr -> string + + /// + /// Return the ASCII string pointed to by the binary pointer from the given + /// BinHandle. + /// + /// BinHandle. + /// BinaryPointer. + /// + /// Return the corresponding ASCII string. + /// + static member ReadASCII: + hdl: BinHandle * bp: BinaryPointer -> string + + /// + /// Parse one instruction at the given address (addr) from the BinHandle, + /// and return the corresponding instruction. This function raises an + /// exception if the parsing process failed. + /// + /// BinHandle. + /// The address. + /// + /// Parsed instruction. + /// + static member ParseInstr: + hdl: BinHandle * addr: Addr -> Instruction + + /// + /// Parse one instruction pointed to by binary pointer (bp) from the + /// BinHandle, and return the corresponding instruction. This function + /// raises an exception if the parsing process failed. + /// + /// BinHandle. + /// BinaryPointer. + /// + /// Parsed instruction. + /// + static member ParseInstr: + hdl: BinHandle * bp: BinaryPointer -> Instruction + + /// + /// Parse one instruction at the given address (addr) from the BinHandle, + /// and return the corresponding instruction. This function does not raise + /// an exception, but returns an option type. + /// + /// BinHandle. + /// The address. + /// + /// Parsed instruction (option type). + /// + static member TryParseInstr: + hdl: BinHandle * addr: Addr -> Result + + /// + /// Parse one instruction pointed to by the binary pointer (bp) from the + /// BinHandle, and return the corresponding instruction. This function does + /// not raise an exception, but returns an option type. + /// + /// BinHandle. + /// BinaryPointer. + /// + /// Parsed instruction (option type). + /// + static member TryParseInstr: + hdl: BinHandle * bp: BinaryPointer -> Result + + /// Parse a basic block from the given address, and return the sequence of the + /// instructions of the basic block. This function may return an incomplete + /// basic block as an Error type. This function can be safely used for any + /// ISAs, and thus, this should be the main parsing function. + static member ParseBBlock: + BinHandle * addr: Addr + -> Result + + /// Parse a basic block pointed to by the binary pointer (bp), and return the + /// sequence of the instructions of the basic block. This function may return + /// an incomplete basic block as an Error type. This function can be safely + /// used for any ISAs, and thus, this should be the main parsing function. + static member ParseBBlock: + BinHandle * bp: BinaryPointer + -> Result + + /// Lift a parsed instruction (Instruction) to produce an array of IR + /// statements from a given BinHandle. + static member inline LiftInstr: + hdl: BinHandle -> ins: Instruction -> LowUIR.Stmt [] + + /// Lift a parsed instruction (Instruction) to produce an array of optimized + /// IR statements from a given BinHandle. + static member LiftOptimizedInstr: + hdl: BinHandle -> ins: Instruction -> LowUIR.Stmt [] + + /// Return the lifted IR (an array of statements) of a basic block at the + /// given address. This function returns a partial bblock with Error, if the + /// parsing of the bblock was not successful. + static member LiftBBlock: + hdl: BinHandle * addr: Addr + -> Result<(LowUIR.Stmt [] * Addr), + (LowUIR.Stmt [] * Addr)> + + /// Return the lifted IR (an array of statements) of a basic block pointed to + /// by the binary pointer (bp). This function returns a partial bblock with + /// Error, if the parsing of the bblock was not successful. + static member LiftBBlock: + hdl: BinHandle * bp: BinaryPointer + -> Result<(LowUIR.Stmt [] * BinaryPointer), + (LowUIR.Stmt [] * BinaryPointer)> + + /// + /// Return a disassembled string from the parsed instruction. + /// + /// BinHandle. + /// Whether to show the instruction address or + /// not. + /// Whether to resolve symbols while disassembling + /// the instruction. + /// The instruction to disassemble. + /// + /// Disassembled string. + /// + static member inline DisasmInstr: + hdl: BinHandle + -> showAddr: bool + -> resolveSymbol: bool + -> ins: Instruction + -> string + + /// + /// Return a disassembled string from the parsed instruction. This function + /// returns a simplified disassembly, which does not contain the instruction + /// address nor symbols. + /// + /// The instruction to disassemble. + /// + /// Disassembled string. + /// + static member inline DisasmInstrSimple: ins: Instruction -> string + + /// + /// Return the disassembled string for a basic block starting at the given + /// address along with the fall-through address of the block. This function + /// returns a partial disassembly if parsing of the bblock was not + /// successful. + /// + static member DisasmBBlock: + hdl: BinHandle + * showAddr:bool + * resolveSymbol: bool + * addr: Addr + -> Result<(string * Addr), (string * Addr)> + + /// + /// Return the disassembled string for a basic block starting at address + /// pointed to by the binary pointer (bp) along with the fall-through + /// address of the block. This function returns a partial disassembly if + /// parsing of the bblock was not successful. + /// + static member DisasmBBlock: + hdl: BinHandle + * showAddr:bool + * resolveSymbol: bool + * bp: BinaryPointer + -> Result<(string * BinaryPointer), + (string * BinaryPointer)> + + /// + /// Return optimized statements from the given statements. + /// + static member Optimize: stmts: LowUIR.Stmt [] -> LowUIR.Stmt [] + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/Library/CallingConvention.fs b/src/FrontEnd/BinInterface/CallingConvention.fs similarity index 70% rename from src/FrontEnd/Library/CallingConvention.fs rename to src/FrontEnd/BinInterface/CallingConvention.fs index b27ee851..73bfb7fa 100644 --- a/src/FrontEnd/Library/CallingConvention.fs +++ b/src/FrontEnd/BinInterface/CallingConvention.fs @@ -22,13 +22,32 @@ SOFTWARE. *) -module B2R2.FrontEnd.CallingConvention +module B2R2.FrontEnd.BinInterface.CallingConvention open B2R2 +open B2R2.FrontEnd.BinLifter + +[] +let volatileRegisters hdl = + match hdl.ISA.Arch with + | Arch.IntelX86 -> + [ Intel.Register.EAX; Intel.Register.ECX; Intel.Register.EDX ] + |> List.map Intel.Register.toRegID + | Arch.IntelX64 -> + [ Intel.Register.RAX; Intel.Register.RCX; Intel.Register.RDX; + Intel.Register.R8; Intel.Register.R9; Intel.Register.R10; + Intel.Register.R11 ] + |> List.map Intel.Register.toRegID + | Arch.ARMv7 + | Arch.AARCH32 -> + [ ARM32.Register.R0; ARM32.Register.R1; ARM32.Register.R2; + ARM32.Register.R3 ] + |> List.map ARM32.Register.toRegID + | _ -> Utils.futureFeature () [] -let returnRegister handler = - match handler.ISA.Arch with +let returnRegister hdl = + match hdl.ISA.Arch with | Architecture.IntelX86 -> Intel.Register.EAX |> Intel.Register.toRegID | Architecture.IntelX64 -> Intel.Register.RAX |> Intel.Register.toRegID | Architecture.ARMv7 @@ -48,8 +67,8 @@ let returnRegister handler = | _ -> Utils.futureFeature () [] -let syscallNumRegister handler = - match handler.ISA.Arch with +let syscallNumRegister hdl = + match hdl.ISA.Arch with | Architecture.IntelX86 -> Intel.Register.EAX |> Intel.Register.toRegID | Architecture.IntelX64 -> Intel.Register.RAX |> Intel.Register.toRegID | Architecture.ARMv7 @@ -69,9 +88,9 @@ let syscallNumRegister handler = | _ -> Utils.futureFeature () [] -let syscallArgRegister handler num = - match handler.ISA.Arch with - | Architecture.IntelX86 -> +let syscallArgRegister hdl num = + match hdl.OS, hdl.ISA.Arch with + | OS.Linux, Architecture.IntelX86 -> match num with | 1 -> Intel.Register.EBX |> Intel.Register.toRegID | 2 -> Intel.Register.ECX |> Intel.Register.toRegID @@ -80,7 +99,7 @@ let syscallArgRegister handler num = | 5 -> Intel.Register.EDI |> Intel.Register.toRegID | 6 -> Intel.Register.EBP |> Intel.Register.toRegID | _ -> Utils.impossible () - | Architecture.IntelX64 -> + | OS.Linux, Architecture.IntelX64 -> match num with | 1 -> Intel.Register.RDI |> Intel.Register.toRegID | 2 -> Intel.Register.RSI |> Intel.Register.toRegID @@ -89,8 +108,8 @@ let syscallArgRegister handler num = | 5 -> Intel.Register.R8 |> Intel.Register.toRegID | 6 -> Intel.Register.R9 |> Intel.Register.toRegID | _ -> Utils.impossible () - | Architecture.ARMv7 - | Architecture.AARCH32 -> + | OS.Linux, Architecture.ARMv7 + | OS.Linux, Architecture.AARCH32 -> match num with | 1 -> ARM32.Register.R0 |> ARM32.Register.toRegID | 2 -> ARM32.Register.R1 |> ARM32.Register.toRegID @@ -99,7 +118,7 @@ let syscallArgRegister handler num = | 5 -> ARM32.Register.R4 |> ARM32.Register.toRegID | 6 -> ARM32.Register.R5 |> ARM32.Register.toRegID | _ -> Utils.impossible () - | Architecture.AARCH64 -> + | OS.Linux, Architecture.AARCH64 -> match num with | 1 -> ARM64.Register.X0 |> ARM64.Register.toRegID | 2 -> ARM64.Register.X1 |> ARM64.Register.toRegID @@ -108,17 +127,17 @@ let syscallArgRegister handler num = | 5 -> ARM64.Register.X4 |> ARM64.Register.toRegID | 6 -> ARM64.Register.X5 |> ARM64.Register.toRegID | _ -> Utils.impossible () - | Architecture.MIPS1 - | Architecture.MIPS2 - | Architecture.MIPS3 - | Architecture.MIPS4 - | Architecture.MIPS5 - | Architecture.MIPS32 - | Architecture.MIPS32R2 - | Architecture.MIPS32R6 - | Architecture.MIPS64 - | Architecture.MIPS64R2 - | Architecture.MIPS64R6 -> + | OS.Linux, Architecture.MIPS1 + | OS.Linux, Architecture.MIPS2 + | OS.Linux, Architecture.MIPS3 + | OS.Linux, Architecture.MIPS4 + | OS.Linux, Architecture.MIPS5 + | OS.Linux, Architecture.MIPS32 + | OS.Linux, Architecture.MIPS32R2 + | OS.Linux, Architecture.MIPS32R6 + | OS.Linux, Architecture.MIPS64 + | OS.Linux, Architecture.MIPS64R2 + | OS.Linux, Architecture.MIPS64R6 -> match num with | 1 -> MIPS.Register.R4 |> MIPS.Register.toRegID | 2 -> MIPS.Register.R5 |> MIPS.Register.toRegID @@ -129,15 +148,41 @@ let syscallArgRegister handler num = | _ -> Utils.impossible () | _ -> Utils.futureFeature () +[] +let functionArgRegister hdl num = + match hdl.OS, hdl.ISA.Arch with + | OS.Windows, Architecture.IntelX86 -> (* fast call *) + match num with + | 1 -> Intel.Register.ECX |> Intel.Register.toRegID + | 2 -> Intel.Register.EDX |> Intel.Register.toRegID + | _ -> Utils.impossible () + | OS.Linux, Architecture.IntelX64 -> (* System V *) + match num with + | 1 -> Intel.Register.RDI |> Intel.Register.toRegID + | 2 -> Intel.Register.RSI |> Intel.Register.toRegID + | 3 -> Intel.Register.RDX |> Intel.Register.toRegID + | 4 -> Intel.Register.RCX |> Intel.Register.toRegID + | 5 -> Intel.Register.R8 |> Intel.Register.toRegID + | 6 -> Intel.Register.R9 |> Intel.Register.toRegID + | _ -> Utils.impossible () + | OS.Windows, Architecture.IntelX64 -> + match num with + | 1 -> Intel.Register.RCX |> Intel.Register.toRegID + | 2 -> Intel.Register.RDX |> Intel.Register.toRegID + | 3 -> Intel.Register.R8 |> Intel.Register.toRegID + | 4 -> Intel.Register.R9 |> Intel.Register.toRegID + | _ -> Utils.impossible () + | _ -> Utils.futureFeature () + [] -let isNonVolatile handler rid = - match handler.FileInfo.FileFormat, handler.ISA.Arch with - | FileFormat.ELFBinary, Arch.IntelX86 -> (* CDECL *) +let isNonVolatile hdl rid = + match hdl.OS, hdl.ISA.Arch with + | OS.Linux, Arch.IntelX86 -> (* CDECL *) rid = (Intel.Register.EBP |> Intel.Register.toRegID) || rid = (Intel.Register.EBX |> Intel.Register.toRegID) || rid = (Intel.Register.ESI |> Intel.Register.toRegID) || rid = (Intel.Register.EDI |> Intel.Register.toRegID) - | FileFormat.ELFBinary, Arch.IntelX64 -> (* CDECL *) + | OS.Linux, Arch.IntelX64 -> (* CDECL *) rid = (Intel.Register.RBX |> Intel.Register.toRegID) || rid = (Intel.Register.RSP |> Intel.Register.toRegID) || rid = (Intel.Register.RBP |> Intel.Register.toRegID) @@ -145,7 +190,7 @@ let isNonVolatile handler rid = || rid = (Intel.Register.R13 |> Intel.Register.toRegID) || rid = (Intel.Register.R14 |> Intel.Register.toRegID) || rid = (Intel.Register.R15 |> Intel.Register.toRegID) - | FileFormat.ELFBinary, Arch.ARMv7 -> (* EABI *) + | OS.Linux, Arch.ARMv7 -> (* EABI *) rid = (ARM32.Register.R4 |> ARM32.Register.toRegID) || rid = (ARM32.Register.R5 |> ARM32.Register.toRegID) || rid = (ARM32.Register.R6 |> ARM32.Register.toRegID) @@ -153,7 +198,7 @@ let isNonVolatile handler rid = || rid = (ARM32.Register.R8 |> ARM32.Register.toRegID) || rid = (ARM32.Register.SL |> ARM32.Register.toRegID) || rid = (ARM32.Register.FP |> ARM32.Register.toRegID) - | FileFormat.ELFBinary, Arch.AARCH64 -> (* EABI *) + | OS.Linux, Arch.AARCH64 -> (* EABI *) rid = (ARM64.Register.X19 |> ARM64.Register.toRegID) || rid = (ARM64.Register.X20 |> ARM64.Register.toRegID) || rid = (ARM64.Register.X21 |> ARM64.Register.toRegID) @@ -165,17 +210,17 @@ let isNonVolatile handler rid = || rid = (ARM64.Register.X27 |> ARM64.Register.toRegID) || rid = (ARM64.Register.X28 |> ARM64.Register.toRegID) || rid = (ARM64.Register.X29 |> ARM64.Register.toRegID) - | FileFormat.ELFBinary, Arch.MIPS1 - | FileFormat.ELFBinary, Arch.MIPS2 - | FileFormat.ELFBinary, Arch.MIPS3 - | FileFormat.ELFBinary, Arch.MIPS32 - | FileFormat.ELFBinary, Arch.MIPS32R2 - | FileFormat.ELFBinary, Arch.MIPS32R6 - | FileFormat.ELFBinary, Arch.MIPS4 - | FileFormat.ELFBinary, Arch.MIPS5 - | FileFormat.ELFBinary, Arch.MIPS64 - | FileFormat.ELFBinary, Arch.MIPS64R2 - | FileFormat.ELFBinary, Arch.MIPS64R6 -> + | OS.Linux, Arch.MIPS1 + | OS.Linux, Arch.MIPS2 + | OS.Linux, Arch.MIPS3 + | OS.Linux, Arch.MIPS32 + | OS.Linux, Arch.MIPS32R2 + | OS.Linux, Arch.MIPS32R6 + | OS.Linux, Arch.MIPS4 + | OS.Linux, Arch.MIPS5 + | OS.Linux, Arch.MIPS64 + | OS.Linux, Arch.MIPS64R2 + | OS.Linux, Arch.MIPS64R6 -> rid = (MIPS.Register.R16 |> MIPS.Register.toRegID) || rid = (MIPS.Register.R17 |> MIPS.Register.toRegID) || rid = (MIPS.Register.R18 |> MIPS.Register.toRegID) @@ -185,7 +230,7 @@ let isNonVolatile handler rid = || rid = (MIPS.Register.R22 |> MIPS.Register.toRegID) || rid = (MIPS.Register.R23 |> MIPS.Register.toRegID) || rid = (MIPS.Register.R30 |> MIPS.Register.toRegID) - | FileFormat.PEBinary, Arch.IntelX64 -> (* Microsoft x64 *) + | OS.Windows, Arch.IntelX64 -> (* Microsoft x64 *) rid = (Intel.Register.RBX |> Intel.Register.toRegID) || rid = (Intel.Register.RSP |> Intel.Register.toRegID) || rid = (Intel.Register.RBP |> Intel.Register.toRegID) diff --git a/src/FrontEnd/Library/CallingConvention.fsi b/src/FrontEnd/BinInterface/CallingConvention.fsi similarity index 69% rename from src/FrontEnd/Library/CallingConvention.fsi rename to src/FrontEnd/BinInterface/CallingConvention.fsi index c7f374e9..9e1847d8 100644 --- a/src/FrontEnd/Library/CallingConvention.fsi +++ b/src/FrontEnd/BinInterface/CallingConvention.fsi @@ -22,24 +22,35 @@ SOFTWARE. *) -module B2R2.FrontEnd.CallingConvention +module B2R2.FrontEnd.BinInterface.CallingConvention open B2R2 +/// Obtain the list of volatile register IDs +[] +val volatileRegisters: BinHandle -> RegisterID list + /// Obtain the register ID used for storing syscall return values. [] -val returnRegister: BinHandler -> RegisterID +val returnRegister: BinHandle -> RegisterID /// Obtain the register ID used for storing a syscall number. [] -val syscallNumRegister: BinHandler -> RegisterID +val syscallNumRegister: BinHandle -> RegisterID /// Obtain the register ID used for the nth syscall parameter. [] -val syscallArgRegister: BinHandler -> int -> RegisterID +val syscallArgRegister: BinHandle -> int -> RegisterID + +/// Obtain the register ID used for the nth function call parameter. Since +/// actual calling convention may vary depending on the binaries, this function +/// only returns a generally used register for the given architecture and the +/// file format. +[] +val functionArgRegister: BinHandle -> int -> RegisterID /// Check if the given register is non-volatile register in the given binary. /// Non-volatile registers are preserved by callee, i.e., callee-saved /// registers. [] -val isNonVolatile: BinHandler -> RegisterID -> bool +val isNonVolatile: BinHandle -> RegisterID -> bool diff --git a/src/FrontEnd/BinInterface/Helper.fs b/src/FrontEnd/BinInterface/Helper.fs new file mode 100644 index 00000000..c1d3626c --- /dev/null +++ b/src/FrontEnd/BinInterface/Helper.fs @@ -0,0 +1,229 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinInterface.Helper + +open System.Text +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinLifter + +let initBasis isa = + match isa.Arch with + | Arch.IntelX64 + | Arch.IntelX86 -> Intel.Basis.init isa + | Arch.ARMv7 -> ARM32.Basis.init isa + | Arch.AARCH64 -> ARM64.Basis.init isa + | Arch.MIPS1 | Arch.MIPS2 | Arch.MIPS3 | Arch.MIPS4 | Arch.MIPS5 + | Arch.MIPS32 | Arch.MIPS32R2 | Arch.MIPS32R6 + | Arch.MIPS64 | Arch.MIPS64R2 | Arch.MIPS64R6 -> MIPS.Basis.init isa + | Arch.EVM -> EVM.Basis.init isa + | Arch.TMS320C6000 -> TMS320C6000.Basis.init isa + | Arch.CILOnly -> CIL.Basis.init isa + | Arch.AVR -> AVR.Basis.init isa + | _ -> Utils.futureFeature () + +let private appendOSInfo fmt isa = + match fmt with + | FileFormat.ELFBinary -> fmt, isa, OS.Linux + | FileFormat.PEBinary -> fmt, isa, OS.Windows + | FileFormat.MachBinary -> fmt, isa, OS.MacOSX + | _ -> Utils.impossible () + +let identifyFormatAndISAAndOS bytes isa os autoDetect = + if autoDetect then FormatDetector.identify bytes isa ||> appendOSInfo + else FileFormat.RawBinary, isa, Option.defaultValue OS.UnknownOS os + +let newFileInfo bytes (baddr: Addr option) path fmt isa regbay = + match fmt with + | FileFormat.ELFBinary -> + ELFFileInfo (bytes, path, baddr, Some regbay) :> FileInfo + | FileFormat.PEBinary -> + PEFileInfo (bytes, path, baddr) :> FileInfo + | FileFormat.MachBinary -> + MachFileInfo (bytes, path, isa, baddr) :> FileInfo + | _ -> RawFileInfo (bytes, path, isa, baddr) :> FileInfo + +let initParser (isa: ISA) mode (fi: FileInfo) = + match isa.Arch with + | Arch.IntelX64 + | Arch.IntelX86 -> Intel.IntelParser (isa.WordSize) :> Parser + | Arch.ARMv7 -> ARM32.ARM32Parser (isa, mode, fi.EntryPoint) :> Parser + | Arch.AARCH64 -> ARM64.ARM64Parser () :> Parser + | Arch.MIPS1 | Arch.MIPS2 | Arch.MIPS3 | Arch.MIPS4 | Arch.MIPS5 + | Arch.MIPS32 | Arch.MIPS32R2 | Arch.MIPS32R6 + | Arch.MIPS64 | Arch.MIPS64R2 | Arch.MIPS64R6 -> + MIPS.MIPSParser (isa.WordSize, isa.Arch) :> Parser + | Arch.EVM -> EVM.EVMParser (isa.WordSize) :> Parser + | Arch.TMS320C6000 -> TMS320C6000.TMS320C6000Parser () :> Parser + | Arch.CILOnly -> CIL.CILParser () :> Parser + | Arch.AVR -> AVR.AVRParser () :> Parser + | _ -> Utils.futureFeature () + +/// Classify ranges to be either in-file or not-in-file. The second parameter +/// (notinfiles) is a sequence of (exclusive) ranges within the myrange, which +/// represent the not-in-file ranges. This function will simply divide the +/// myrange into subranges where each subrange is labeled with either true or +/// false, where true means in-file, and false means not-in-file. +let classifyRanges myrange notinfiles = + notinfiles + |> Seq.fold (fun (infiles, saddr) r -> + let l = AddrRange.GetMin r + let h = AddrRange.GetMax r + if saddr = l then (r, false) :: infiles, h + else (r, false) :: ((AddrRange (saddr, l), true) :: infiles), h + ) ([], AddrRange.GetMin myrange) + |> (fun (infiles, saddr) -> + if saddr = myrange.Max then infiles + else ((AddrRange (saddr, myrange.Max), true) :: infiles)) + |> List.rev + +let inline readIntBySize (fi: FileInfo) pos size = + match size with + | 1 -> fi.BinReader.PeekInt8 pos |> int64 |> Ok + | 2 -> fi.BinReader.PeekInt16 pos |> int64 |> Ok + | 4 -> fi.BinReader.PeekInt32 pos |> int64 |> Ok + | 8 -> fi.BinReader.PeekInt64 pos |> Ok + | _ -> Error ErrorCase.InvalidMemoryRead + +let inline readUIntBySize (fi: FileInfo) pos size = + match size with + | 1 -> fi.BinReader.PeekUInt8 pos |> uint64 |> Ok + | 2 -> fi.BinReader.PeekUInt16 pos |> uint64 |> Ok + | 4 -> fi.BinReader.PeekUInt32 pos |> uint64 |> Ok + | 8 -> fi.BinReader.PeekUInt64 pos |> Ok + | _ -> Error ErrorCase.InvalidMemoryRead + +let inline readASCII (fi: FileInfo) pos = + let rec loop acc pos = + let b = fi.BinReader.PeekByte pos + if b = 0uy then List.rev (b :: acc) |> List.toArray + else loop (b :: acc) (pos + 1) + loop [] pos + +let inline parseInstrFromAddr (fi: FileInfo) (parser: Parser) addr = + fi.TranslateAddress addr + |> parser.Parse fi.BinReader addr + +let inline tryParseInstrFromAddr (fi: FileInfo) (parser: Parser) addr = + try parseInstrFromAddr fi parser addr |> Ok + with _ -> Error ErrorCase.ParsingFailure + +let inline tryParseInstrFromBinPtr fi (p: Parser) (bp: BinaryPointer) = + try + let ins = p.Parse (fi: FileInfo).BinReader bp.Addr bp.Offset + if BinaryPointer.IsValidAccess bp (int ins.Length) then Ok ins + else Error ErrorCase.ParsingFailure + with _ -> + Error ErrorCase.ParsingFailure + +let inline parseInstrFromBinPtr (fi: FileInfo) parser (bp: BinaryPointer) = + match tryParseInstrFromBinPtr fi parser bp with + | Ok ins -> ins + | Error _ -> raise ParsingFailureException + +let advanceAddr addr len = + addr + uint64 len + +let rec parseLoopByAddr fi parser addr acc = + match tryParseInstrFromAddr fi parser addr with + | Ok ins -> + if ins.IsBBLEnd () then Ok (List.rev (ins :: acc)) + else + let addr = addr + (uint64 ins.Length) + parseLoopByAddr fi parser addr (ins :: acc) + | Error _ -> Error <| List.rev acc + +let inline parseBBLFromAddr (fi: FileInfo) (parser: Parser) addr = + parseLoopByAddr fi parser addr [] + +let rec parseLoopByPtr fi parser bp acc = + match tryParseInstrFromBinPtr fi parser bp with + | Ok (ins: Instruction) -> + if ins.IsBBLEnd () then Ok (List.rev (ins :: acc)) + else + let bp = BinaryPointer.Advance bp (int ins.Length) + parseLoopByPtr fi parser bp (ins :: acc) + | Error _ -> Error <| List.rev acc + +let inline parseBBLFromBinPtr (fi: FileInfo) (parser: Parser) bp = + parseLoopByPtr fi parser bp [] + +let rec liftBBLAux acc advanceFn trctxt pos = function + | (ins: Instruction) :: rest -> + let pos = advanceFn pos (int ins.Length) + liftBBLAux (ins.Translate trctxt :: acc) advanceFn trctxt pos rest + | [] -> struct (List.rev acc |> Array.concat, pos) + +let inline liftBBLFromAddr fi parser trctxt addr = + match parseBBLFromAddr fi parser addr with + | Ok bbl -> + let struct (stmts, addr) = liftBBLAux [] advanceAddr trctxt addr bbl + Ok (stmts, addr) + | Error bbl -> + let struct (stmts, addr) = liftBBLAux [] advanceAddr trctxt addr bbl + Error (stmts, addr) + +let inline liftBBLFromBinPtr fi parser trctxt bp = + match parseBBLFromBinPtr fi parser bp with + | Ok bbl -> + let struct (stmts, bp) = liftBBLAux [] BinaryPointer.Advance trctxt bp bbl + Ok (stmts, bp) + | Error bbl -> + let struct (stmts, bp) = liftBBLAux [] BinaryPointer.Advance trctxt bp bbl + Error (stmts, bp) + +let rec disasmBBLAux sb advanceFn showAddr resolve hlp pos = function + | (ins: Instruction) :: rest -> + let s = ins.Disasm (showAddr, resolve, hlp) + let s = + if (sb: StringBuilder).Length = 0 then s + else System.Environment.NewLine + s + let pos = advanceFn pos (int ins.Length) + disasmBBLAux (sb.Append (s)) advanceFn showAddr resolve hlp pos rest + | [] -> struct (sb.ToString (), pos) + +let disasmBBLFromAddr fi parser hlp showAddr resolve addr = + match parseBBLFromAddr fi parser addr with + | Ok bbl -> + let struct (str, addr) = + disasmBBLAux (StringBuilder ()) advanceAddr showAddr resolve hlp addr bbl + Ok (str, addr) + | Error bbl -> + let struct (str, addr) = + disasmBBLAux (StringBuilder ()) advanceAddr showAddr resolve hlp addr bbl + Error (str, addr) + +let disasmBBLFromBinPtr fi parser hlp showAddr resolve bp = + match parseBBLFromBinPtr fi parser bp with + | Ok bbl -> + let struct (str, addr) = + disasmBBLAux (StringBuilder ()) + BinaryPointer.Advance showAddr resolve hlp bp bbl + Ok (str, addr) + | Error bbl -> + let struct (str, addr) = + disasmBBLAux (StringBuilder ()) + BinaryPointer.Advance showAddr resolve hlp bp bbl + Error (str, addr) diff --git a/src/FrontEnd/BinInterface/README.md b/src/FrontEnd/BinInterface/README.md new file mode 100644 index 00000000..628f7ab3 --- /dev/null +++ b/src/FrontEnd/BinInterface/README.md @@ -0,0 +1,13 @@ +# B2R2.FrontEnd.BinInterface + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.BinInterface Package? + +`B2R2.FrontEnd.BinInterface` is the main interface for B2R2's front-end. In most +cases, it should suffice to import just this package because all the other +front-end packages will be loaded by this one. diff --git a/src/FrontEnd/BinLifter.Tests/AVR.Lifter.Tests.fs b/src/FrontEnd/BinLifter.Tests/AVR.Lifter.Tests.fs new file mode 100644 index 00000000..31b78f99 --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/AVR.Lifter.Tests.fs @@ -0,0 +1,86 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.AVRLifter + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.BinIR.LowUIR +open B2R2.FrontEnd.BinLifter.AVR +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR.LowUIR.AST.InfixOp + +let isa = ISA.Init Architecture.AVR Endian.Little + +let struct (ctxt, _) = AVR.Basis.init isa + +let inline ( !. ) (ctxt: TranslationContext) name = + Register.toRegID name |> ctxt.GetRegVar + +let private test bytes len (actStmts : Stmt []) = + let reader = BinReader.Init (bytes, Endian.Little) + let ins = Parser.parse reader 0UL 0 + let expStmts = Lifter.translate ins.Info len ctxt + Assert.AreEqual (Array.toList expStmts, Array.toList actStmts) + +[] +type AVRUnitTest () = + [] + member __.``[AVR] Instructions with start and end statements lift Test`` () = + test [| 0x00uy; 0x00uy |] 2u [| AST.ismark 2u; AST.iemark 2u |] + + [] + member __.``[AVR] Instructions with Put statements lift Test`` () = + test [| 0x4cuy; 0x2fuy |] 2u + [| AST.ismark 2u + (!.ctxt R.R20 := !.ctxt R.R28) + AST.iemark 2u |] + test [| 0x54uy; 0x01uy |] 2u + [| AST.ismark 2u + (!.ctxt R.R10 := !.ctxt R.R8) + (!.ctxt R.R11 := !.ctxt R.R9) + AST.iemark 2u |] + + [] + member __.``[AVR] Put statements for flag registers lift Test`` () = + test [| 0xf8uy; 0x94uy |] 2u + [| AST.ismark 2u + (!.ctxt R.IF := AST.b0) + AST.iemark 2u |] + test [| 0x11uy; 0x24uy |] 2u + [| AST.ismark 2u + (!.ctxt R.R1 := !.ctxt R.R1 <+> !.ctxt R.R1) + (!.ctxt R.VF := AST.b0) + (!.ctxt R.NF := AST.xthi 1 (!.ctxt R.R1)) + (!.ctxt R.ZF := !. ctxt R.R1 == AST.num0 8) + (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + AST.iemark 2u |] + + [] + member __.``[AVR] Load statements lift Test`` () = + test [| 0x6fuy; 0x92uy |] 2u + [| AST.ismark 2u + (AST.loadLE 8 (!.ctxt R.SP) := !.ctxt R.R6) + (!.ctxt R.SP := !.ctxt R.SP .- AST.num1 16) + AST.iemark 2u |] \ No newline at end of file diff --git a/src/FrontEnd/BinLifter.Tests/AVR.Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/AVR.Parser.Tests.fs new file mode 100644 index 00000000..e543037e --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/AVR.Parser.Tests.fs @@ -0,0 +1,78 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.AVRParser + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.FrontEnd.BinLifter.AVR + +let private test opcode oprs bytes = + let reader = BinReader.Init (bytes, Endian.Little) + let ins = Parser.parse reader 0UL 0 + Assert.AreEqual (ins.Info.Opcode, opcode) + Assert.AreEqual (ins.Info.Operands, oprs) + +[] +type AVRUnitTest () = + [] + member __.``[AVR] No Operand Insturctions Parse Test`` () = + test Opcode.RET + (NoOperand) + [| 0x08uy; 0x95uy |] + + [] + member __.``[AVR] One Operand Insturctions Parse Test`` () = + test Opcode.BREQ + (OneOperand (OprAddr 96)) + [| 0x81uy; 0xf1uy |] + test Opcode.BRGE + (OneOperand (OprAddr 44)) + [| 0xB4uy; 0xf4uy |] + + [] + member __.``[AVR] Two Register Operands Insturctions Parse Test`` () = + test Opcode.ADD + (TwoOperands (OprReg R.R12, OprReg R.R25)) + [| 0xC9uy; 0x0Euy |] + test Opcode.MOV + (TwoOperands (OprReg R.R14, OprReg R.R1)) + [| 0xE1uy; 0x2Cuy |] + + [] + member __.``[AVR] Memory Operands Insturctions Parse Test`` () = + test Opcode.ST + (TwoOperands (OprMemory (PostIdxMode (R.X)), OprReg R.R1)) + [| 0x1Duy; 0x92uy |] + test Opcode.LDD + (TwoOperands (OprReg R.R6, OprMemory (DispMode ((R.Y, 1))))) + [| 0x69uy; 0x80uy |] + + [] + member __.``[AVR] Immediate Operand Insturction Parse Test`` () = + test Opcode.LDI + (TwoOperands (OprReg R.R24, OprImm 0xff)) + [| 0x8Fuy; 0xEFuy |] + + diff --git a/src/FrontEnd/BinLifter.Tests/B2R2.FrontEnd.BinLifter.Tests.fsproj b/src/FrontEnd/BinLifter.Tests/B2R2.FrontEnd.BinLifter.Tests.fsproj new file mode 100644 index 00000000..03bc3281 --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/B2R2.FrontEnd.BinLifter.Tests.fsproj @@ -0,0 +1,26 @@ + + + + net5.0 + false + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FrontEnd.Tests/Lifter.Tests.fs b/src/FrontEnd/BinLifter.Tests/Lifter.Tests.fs similarity index 88% rename from src/FrontEnd.Tests/Lifter.Tests.fs rename to src/FrontEnd/BinLifter.Tests/Lifter.Tests.fs index 6db0d219..17286f99 100644 --- a/src/FrontEnd.Tests/Lifter.Tests.fs +++ b/src/FrontEnd/BinLifter.Tests/Lifter.Tests.fs @@ -37,10 +37,10 @@ module Lifter = [] member __.``PP Test`` () = let e = BitVector.ofUInt32 42ul 32 |> AST.num - Assert.AreEqual (Pp.expToString e, "0x2A:I32") - let e0 = AST.tmpVar 32 + Assert.AreEqual (Pp.expToString e, "0x2a:I32") + let e0 = AST.tmpvar 32 0 Assert.AreEqual (Pp.expToString e0, "T_0:I32") - let e1 = AST.tmpVar 32 + let e1 = AST.tmpvar 32 1 Assert.AreEqual (Pp.expToString e1, "T_1:I32") let e = AST.unop UnOpType.NEG e1 Assert.AreEqual (Pp.expToString e, "(- T_1:I32)") @@ -48,7 +48,7 @@ module Lifter = Assert.AreEqual (Pp.expToString e, "(~ (T_0:I32 + T_1:I32))") let e = AST.load Endian.Little 32 e0 Assert.AreEqual (Pp.expToString e, "[T_0:I32]:I32") - let e = AST.ite (AST.tmpVar 1) e0 e1 - Assert.AreEqual (Pp.expToString e, "(ite (T_2:I1) (T_0:I32) (T_1:I32))") + let e = AST.ite (AST.tmpvar 1 2) e0 e1 + Assert.AreEqual (Pp.expToString e, "((T_2:I1) ? (T_0:I32) : (T_1:I32))") // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd.Tests/Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/Parser.Tests.fs similarity index 99% rename from src/FrontEnd.Tests/Parser.Tests.fs rename to src/FrontEnd/BinLifter.Tests/Parser.Tests.fs index 71e06cfb..5bcd8767 100644 --- a/src/FrontEnd.Tests/Parser.Tests.fs +++ b/src/FrontEnd/BinLifter.Tests/Parser.Tests.fs @@ -26,19 +26,20 @@ namespace B2R2.FrontEnd.Tests open Microsoft.VisualStudio.TestTools.UnitTesting open B2R2 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinInterface module Intel = - open B2R2.FrontEnd.Intel + open B2R2.FrontEnd.BinLifter.Intel let private test prefs segment wordSize opcode oprs length (bytes: byte[]) = let reader = BinReader.Init (bytes) - let ins = Parser.parse reader wordSize 0UL 0 - let pInfo = ins.Info - Assert.AreEqual (pInfo.Prefixes, prefs) - Assert.AreEqual (Helper.getSegment pInfo.Prefixes, segment) - Assert.AreEqual (pInfo.Opcode, opcode) - Assert.AreEqual (pInfo.Operands, oprs) + let parser = IntelParser (wordSize) + let ins = parser.Parse reader 0UL 0 :?> IntelInternalInstruction + Assert.AreEqual (ins.Prefixes, prefs) + Assert.AreEqual (Helper.getSegment ins.Prefixes, segment) + Assert.AreEqual (ins.Opcode, opcode) + Assert.AreEqual (ins.Operands, oprs) Assert.AreEqual (ins.Length, length) let private test32 = test Prefix.PrxNone None WordSize.Bit32 @@ -53,11 +54,11 @@ module Intel = member __.``Intel Data Transfer Parse Test`` () = test32 Opcode.MOV (TwoOperands (OprMem (None, None, Some 2210584L, 32), - OprImm 2L) ) 10ul + OprImm (2L, 32)) ) 10ul [| 0xc7uy; 0x05uy; 0x18uy; 0xbbuy; 0x21uy; 0x00uy; 0x02uy; 0x00uy; 0x00uy; 0x00uy |] - test64 Opcode.PUSH (OneOperand (OprImm 0x44332211L)) 5ul + test64 Opcode.PUSH (OneOperand (OprImm (0x44332211L, 32))) 5ul [| 0x68uy; 0x11uy; 0x22uy; 0x33uy; 0x44uy |] test32 Opcode.MOVSX @@ -75,7 +76,8 @@ module Intel = [| 0x48uy; 0x03uy; 0xc8uy |] test32 Opcode.IMUL - (ThreeOperands (OprReg R.EDI, OprReg R.EDX, OprImm 10L)) 3ul + (ThreeOperands (OprReg R.EDI, OprReg R.EDX, OprImm (10L, 8))) + 3ul [| 0x6buy; 0xfauy; 0x0auy |] test32 Opcode.MUL @@ -110,12 +112,12 @@ module Intel = member __.``Intel Shift And Rotate Parse Test`` () = test32 Opcode.ROL (TwoOperands (OprMem (Some R.EAX, None, None, 32), - OprImm 10L) ) 3ul + OprImm (10L, 8))) 3ul [| 0xc1uy; 0x00uy; 0x0auy |] test32 Opcode.ROL (TwoOperands (OprMem (Some R.EAX, None, None, 8), - OprImm 10L)) 3ul + OprImm (10L, 8))) 3ul [| 0xc0uy; 0x00uy; 0x0auy |] /// 5.1.6 Bit and Byte Instructions @@ -123,7 +125,7 @@ module Intel = member __.``Intel Bit And Byte Parse Test`` () = test32 Opcode.TEST (TwoOperands (OprMem (Some R.EAX, None, None, 8), - OprImm 10L)) 3ul + OprImm (10L, 8))) 3ul [| 0xf6uy; 0x00uy; 0x0auy |] /// 5.1.7 Control Transfer Instructions @@ -146,7 +148,8 @@ module Intel = 7ul [| 0x9auy; 0x98uy; 0x76uy; 0x54uy; 0x32uy; 0x10uy; 0x00uy |] - test32 Opcode.INT (OneOperand (OprImm 1L)) 2ul [| 0xcduy; 0x01uy |] + test32 Opcode.INT (OneOperand (OprImm (1L, 8))) + 2ul [| 0xcduy; 0x01uy |] /// 5.1.9 I/O Instructions [] @@ -525,7 +528,8 @@ module Intel = [] member __.``Intel Packed Align Right Parse Test`` () = test64 Opcode.PALIGNR - (ThreeOperands (OprReg R.XMM2, OprReg R.XMM1, OprImm 1L)) 6ul + (ThreeOperands (OprReg R.XMM2, OprReg R.XMM1, OprImm (1L, 8))) + 6ul [| 0x66uy; 0x0fuy; 0x3auy; 0x0fuy; 0xd1uy; 0x01uy |] /// 5.10 SSE4.1 INSTRUCTIONS @@ -1454,7 +1458,11 @@ module Intel = [] type ExceptionTestClass () = [] +#if !EMULATION [)>] +#else + [)>] +#endif member __.``Size cond ParsingFailure Test`` () = test64 Opcode.AAA NoOperand 1ul [| 0x37uy |] @@ -1486,16 +1494,17 @@ module Intel = [] member __.``Intel IL Test`` () = let isa = ISA.Init Arch.IntelX86 Endian.Little - let hdl = BinHandler.Init (isa) + let hdl = BinHandle.Init (isa) Assert.AreEqual (0, hdl.FileInfo.BinReader.Length ()) module ARMv7 = - open B2R2.FrontEnd.ARM32 + open B2R2.FrontEnd.BinLifter.ARM32 let private test arch endian cond op w (q: Qualifier option) simd oprs bytes = let reader = BinReader.Init (bytes, endian) - let ctxt = ParsingContext.Init (ArchOperationMode.ARMMode) - let ins = Parser.parse reader ctxt arch 0UL 0 + let mode = ArchOperationMode.ARMMode + let mutable itstate = [] + let ins = Parser.parse reader mode &itstate arch 0UL 0 let cond' = ins.Info.Condition let opcode' = ins.Info.Opcode let wback' = ins.Info.WriteBack @@ -2153,8 +2162,8 @@ module ARMv7 = [| 0xf3uy; 0xd2uy; 0xc4uy; 0x60uy |] module ARM64 = - open B2R2.FrontEnd.ARM64 - open B2R2.FrontEnd.ARM64.OperandHelper + open B2R2.FrontEnd.BinLifter.ARM64 + open B2R2.FrontEnd.BinLifter.ARM64.OperandHelper let private test endian opcode oprs bytes = let reader = BinReader.Init (bytes, endian) @@ -5307,12 +5316,13 @@ module ARM64 = [| 0x9euy; 0x79uy; 0x02uy; 0x62uy |] module ARMThumb = - open B2R2.FrontEnd.ARM32 + open B2R2.FrontEnd.BinLifter.ARM32 let private test arch endian cond op w q (simd: SIMDDataType option) oprs bs = let reader = BinReader.Init (bs, endian) - let ctxt = ParsingContext.Init (ArchOperationMode.ThumbMode) - let ins = Parser.parse reader ctxt arch 0UL 0 + let mode = ArchOperationMode.ThumbMode + let mutable itstate = [] + let ins = Parser.parse reader mode &itstate arch 0UL 0 let cond' = ins.Info.Condition let opcode' = ins.Info.Opcode let wback' = ins.Info.WriteBack @@ -6085,7 +6095,7 @@ module ARMThumb = [| 0xf3uy; 0xbfuy; 0x8fuy; 0x1fuy |] module MIPS64 = - open B2R2.FrontEnd.MIPS + open B2R2.FrontEnd.BinLifter.MIPS let private test arch endian opcode oprs bytes = let reader = BinReader.Init (bytes, endian) @@ -6207,7 +6217,7 @@ module MIPS64 = [| 0xb4uy; 0xcbuy; 0x87uy; 0x15uy |] module MIPS32 = - open B2R2.FrontEnd.MIPS + open B2R2.FrontEnd.BinLifter.MIPS let private test arch endian opcode cond fmt oprs bytes = let reader = BinReader.Init (bytes, endian) @@ -6543,12 +6553,11 @@ module MIPS32 = [| 0x45uy; 0x00uy; 0x00uy; 0x1auy |] module EVM = - open B2R2.FrontEnd.EVM + open B2R2.FrontEnd.BinLifter.EVM let private test opcode bytes = let reader = BinReader.Init (bytes, Endian.Little) - let ctxt = ParsingContext.Init (ArchOperationMode.NoMode) - let ins = Parser.parse reader ctxt WordSize.Bit64 0UL 0 + let ins = Parser.parse reader 0UL WordSize.Bit64 0UL 0 let opcode' = ins.Info.Opcode Assert.AreEqual (opcode', opcode) @@ -6557,7 +6566,7 @@ module EVM = type PUSHClass () = [] member __.``[EVM] Push Parse Test`` () = - test (Opcode.PUSH10 <| (BitVector.ofUBInt 316059037807746189465I 80)) + test (Opcode.PUSH10 <| (BitVector.ofBInt 316059037807746189465I 80)) [| 0x69uy; 0x00uy; 0x11uy; 0x22uy; 0x33uy; 0x44uy; 0x55uy; 0x66uy; 0x77uy; 0x88uy; 0x99uy |] diff --git a/src/FrontEnd.Tests/TMS320.Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/TMS320.Parser.Tests.fs similarity index 96% rename from src/FrontEnd.Tests/TMS320.Parser.Tests.fs rename to src/FrontEnd/BinLifter.Tests/TMS320.Parser.Tests.fs index e81a66f9..e7adeb77 100644 --- a/src/FrontEnd.Tests/TMS320.Parser.Tests.fs +++ b/src/FrontEnd/BinLifter.Tests/TMS320.Parser.Tests.fs @@ -26,13 +26,13 @@ module B2R2.FrontEnd.Tests.TMS320 open Microsoft.VisualStudio.TestTools.UnitTesting open B2R2 -open B2R2.FrontEnd -open B2R2.FrontEnd.TMS320C6000 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.TMS320C6000 let private test opcode unit oprs bytes = let reader = BinReader.Init (bytes, Endian.Little) - let ctxt = ParsingContext.Init (ArchOperationMode.NoMode) - let ins = Parser.parse reader ctxt 0UL 0 + let mutable inpar = false + let ins = Parser.parse reader &inpar 0UL 0 Assert.AreEqual (ins.Info.Opcode, opcode) Assert.AreEqual (ins.Info.FunctionalUnit, unit) Assert.AreEqual (ins.Info.Operands, oprs) diff --git a/src/FrontEnd/BinLifter/ARM32/ARM32.fs b/src/FrontEnd/BinLifter/ARM32/ARM32.fs new file mode 100644 index 00000000..0b586502 --- /dev/null +++ b/src/FrontEnd/BinLifter/ARM32/ARM32.fs @@ -0,0 +1,66 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.ARM32 + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for 32-bit ARM instructions. +type ARM32TranslationContext internal (isa, regexprs) = + inherit TranslationContext (isa) + member val private RegExprs: RegExprs = regexprs + override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar + override __.GetPseudoRegVar _id _pos = failwith "Implement" // XXX + +module Basis = + let init isa = + let regexprs = RegExprs () + struct ( + ARM32TranslationContext (isa, regexprs) :> TranslationContext, + ARM32RegisterBay (regexprs) :> RegisterBay + ) + + let detectThumb entryPoint (isa: ISA) = + match entryPoint, isa.Arch with + | Some entry, Arch.ARMv7 when entry % 2UL <> 0UL -> (* XXX: LIbraries? *) + ArchOperationMode.ThumbMode + | _ -> ArchOperationMode.ARMMode + +/// Parser for 32-bit ARM instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type ARM32Parser (isa: ISA, mode, entryPoint: Addr option) = + inherit Parser () + let mutable mode: ArchOperationMode = + if mode = ArchOperationMode.NoMode then Basis.detectThumb entryPoint isa + else mode + let mutable itstate: byte list = [] + + override __.OperationMode with get() = mode and set(m) = mode <- m + + override __.Parse reader addr pos = + Parser.parse reader mode &itstate isa.Arch addr pos + :> Instruction + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/ARM32/ARM32Disasm.fs b/src/FrontEnd/BinLifter/ARM32/ARM32Disasm.fs similarity index 65% rename from src/FrontEnd/ARM32/ARM32Disasm.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32Disasm.fs index 79d3ff3e..60ef3d35 100644 --- a/src/FrontEnd/ARM32/ARM32Disasm.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32Disasm.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.ARM32.Disasm +module internal B2R2.FrontEnd.BinLifter.ARM32.Disasm -open B2R2 -open B2R2.FrontEnd open System.Text +open B2R2 +open B2R2.FrontEnd.BinLifter let opCodeToString = function | Op.MOV -> "mov" @@ -72,7 +72,7 @@ let opCodeToString = function | Op.ADR -> "adr" | Op.MRS -> "mrs" | Op.MSR -> "msr" - | Op.BX -> "bx" + | Op.BX -> "bx" | Op.CLZ -> "clz" | Op.BXJ -> "bxj" | Op.BLX -> "blx" @@ -492,7 +492,7 @@ let opCodeToString = function | Op.VCVTP -> "vcvtp" | Op.VCVTM -> "vcvtm" | Op.InvalidOP -> "(illegal)" - | _ -> failwith "Unknown opcode encountered." + | _ -> Utils.impossible () let condToString = function | Some Condition.EQ -> "eq" @@ -513,8 +513,9 @@ let condToString = function | Some Condition.LE -> "le" | Some Condition.AL -> "" | Some Condition.NV -> "nv" - | Some Condition.UN | None -> "" - | _ -> failwith "Unknown condition encountered." + | Some Condition.UN + | None -> "" + | _ -> Utils.impossible () let SIMDTypToStr = function | SIMDTyp8 -> ".8" @@ -554,13 +555,13 @@ let inline appendSIMDDataTypes ins (sb: StringBuilder) = | Some (TwoDT (dt1, dt2)) -> (sb.Append (SIMDTypToStr dt1)).Append (SIMDTypToStr dt2) -let inline buildOpcode ins builder acc = +let inline buildOpcode ins (builder: DisasmBuilder<_>) = let sb = StringBuilder () let sb = sb.Append (opCodeToString ins.Opcode) let sb = sb.Append (condToString ins.Condition) let sb = appendQualifier ins sb let sb = appendSIMDDataTypes ins sb - builder AsmWordKind.Mnemonic (sb.ToString ()) acc + builder.Accumulate AsmWordKind.Mnemonic (sb.ToString ()) let existRegList = function | TwoOperands (_, OprRegList _) -> true @@ -571,15 +572,17 @@ let isRFEorSRS = function | Op.SRS | Op.SRSDA | Op.SRSDB | Op.SRSIA | Op.SRSIB -> true | _ -> false -let buildReg ins isRegList reg builder acc = +let buildReg ins isRegList reg (builder: DisasmBuilder<_>) = let reg = Register.toString reg match ins.WriteBack with | Some true when existRegList ins.Operands && not isRegList -> - builder AsmWordKind.Variable reg acc |> builder AsmWordKind.String "!" + builder.Accumulate AsmWordKind.Variable reg + builder.Accumulate AsmWordKind.String "!" | Some true when isRFEorSRS ins.Opcode -> - builder AsmWordKind.Variable reg acc |> builder AsmWordKind.String "!" + builder.Accumulate AsmWordKind.Variable reg + builder.Accumulate AsmWordKind.String "!" | _ -> - builder AsmWordKind.Variable reg acc + builder.Accumulate AsmWordKind.Variable reg /// See A8-499 the description of . let flagToString = function @@ -603,84 +606,83 @@ let flagToString = function | PSRg -> "_g" | PSRnzcvqg -> "_nzcvqg" -let specRegToString ins reg pFlag builder acc = +let specRegToString ins reg pFlag builder = match pFlag with - | None -> buildReg ins false reg builder acc + | None -> buildReg ins false reg builder | Some f -> - buildReg ins false reg builder acc - |> builder AsmWordKind.String (flagToString f) + buildReg ins false reg builder + builder.Accumulate AsmWordKind.String (flagToString f) -let regListToString ins list builder acc = - let acc = builder AsmWordKind.String "{" acc +let regListToString ins list (builder: DisasmBuilder<_>) = + builder.Accumulate AsmWordKind.String "{" let len = List.length list list - |> List.fold (fun (acc, idx) r -> - let acc = buildReg ins true r builder acc - if idx + 1 = len then (acc, idx + 1) - else builder AsmWordKind.String ", " acc, idx + 1) (acc, 0) - |> fst - |> builder AsmWordKind.String "}" - -let simdToString ins s builder acc = + |> List.iteri (fun idx r -> + buildReg ins true r builder + if idx + 1 = len then () + else builder.Accumulate AsmWordKind.String ", ") + builder.Accumulate AsmWordKind.String "}" + +let simdToString ins s builder = match s with - | Vector v -> buildReg ins false v builder acc + | Vector v -> buildReg ins false v builder | Scalar (v, None) -> - buildReg ins false v builder acc - |> builder AsmWordKind.String "[]" + buildReg ins false v builder + builder.Accumulate AsmWordKind.String "[]" | Scalar (v, Some i) -> - buildReg ins false v builder acc - |> builder AsmWordKind.String "[" - |> builder AsmWordKind.String (string i) - |> builder AsmWordKind.String "]" + buildReg ins false v builder + builder.Accumulate AsmWordKind.String "[" + builder.Accumulate AsmWordKind.String (string i) + builder.Accumulate AsmWordKind.String "]" -let simdOprToString ins simd builder acc = +let simdOprToString ins simd builder = match simd with - | SFReg s -> simdToString ins s builder acc + | SFReg s -> simdToString ins s builder | OneReg s -> - builder AsmWordKind.String "{" acc - |> simdToString ins s builder - |> builder AsmWordKind.String "}" + builder.Accumulate AsmWordKind.String "{" + simdToString ins s builder + builder.Accumulate AsmWordKind.String "}" | TwoRegs (s1, s2) -> - builder AsmWordKind.String "{" acc - |> simdToString ins s1 builder - |> builder AsmWordKind.String ", " - |> simdToString ins s2 builder - |> builder AsmWordKind.String "}" + builder.Accumulate AsmWordKind.String "{" + simdToString ins s1 builder + builder.Accumulate AsmWordKind.String ", " + simdToString ins s2 builder + builder.Accumulate AsmWordKind.String "}" | ThreeRegs (s1, s2, s3) -> - builder AsmWordKind.String "{" acc - |> simdToString ins s1 builder - |> builder AsmWordKind.String ", " - |> simdToString ins s2 builder - |> builder AsmWordKind.String ", " - |> simdToString ins s3 builder - |> builder AsmWordKind.String "}" + builder.Accumulate AsmWordKind.String "{" + simdToString ins s1 builder + builder.Accumulate AsmWordKind.String ", " + simdToString ins s2 builder + builder.Accumulate AsmWordKind.String ", " + simdToString ins s3 builder + builder.Accumulate AsmWordKind.String "}" | FourRegs (s1, s2, s3, s4) -> - builder AsmWordKind.String "{" acc - |> simdToString ins s1 builder - |> builder AsmWordKind.String ", " - |> simdToString ins s2 builder - |> builder AsmWordKind.String ", " - |> simdToString ins s3 builder - |> builder AsmWordKind.String ", " - |> simdToString ins s4 builder - |> builder AsmWordKind.String "}" + builder.Accumulate AsmWordKind.String "{" + simdToString ins s1 builder + builder.Accumulate AsmWordKind.String ", " + simdToString ins s2 builder + builder.Accumulate AsmWordKind.String ", " + simdToString ins s3 builder + builder.Accumulate AsmWordKind.String ", " + simdToString ins s4 builder + builder.Accumulate AsmWordKind.String "}" let signToString = function | None -> "" | Some Plus -> "" | Some Minus -> "-" -let immToString (imm: int64) sign builder acc = - builder AsmWordKind.String "#" acc - |> builder AsmWordKind.String (signToString sign) - |> builder AsmWordKind.Value ("0x" + imm.ToString ("X")) +let immToString imm sign (builder: DisasmBuilder<_>) = + builder.Accumulate AsmWordKind.String "#" + builder.Accumulate AsmWordKind.String (signToString sign) + builder.Accumulate AsmWordKind.Value (String.i64ToHex imm) -let fpImmToString (fp: float) builder acc = - builder AsmWordKind.String "#" acc - |> builder AsmWordKind.Value (fp.ToString ("N8")) +let fpImmToString (fp: float) (builder: DisasmBuilder<_>) = + builder.Accumulate AsmWordKind.String "#" + builder.Accumulate AsmWordKind.Value (fp.ToString ("N8")) -let optionToString (opt: int64) builder acc = - builder AsmWordKind.Value ("0x" + opt.ToString ("X")) acc +let optionToString (opt: int64) (builder: DisasmBuilder<_>) = + builder.Accumulate AsmWordKind.Value (String.i64ToHex opt) let srTypeToString = function | SRTypeLSL -> "lsl" @@ -689,78 +691,77 @@ let srTypeToString = function | SRTypeROR -> "ror" | SRTypeRRX -> "rrx" -let prependDelimiter delimiter builder acc = +let prependDelimiter delimiter (builder: DisasmBuilder<_>) = match delimiter with - | None -> acc - | Some delim -> - builder AsmWordKind.String delim acc + | None -> () + | Some delim -> builder.Accumulate AsmWordKind.String delim -let shiftToString shift delim builder acc = +let shiftToString shift delim builder = match shift with - | _, Imm 0u -> acc + | _, Imm 0u -> () | s, Imm i -> - prependDelimiter delim builder acc - |> builder AsmWordKind.String (srTypeToString s) - |> builder AsmWordKind.String " " - |> immToString (int64 i) None builder + prependDelimiter delim builder + builder.Accumulate AsmWordKind.String (srTypeToString s) + builder.Accumulate AsmWordKind.String " " + immToString (int64 i) None builder -let regShiftToString ins shift reg builder acc = - builder AsmWordKind.String (srTypeToString shift) acc - |> builder AsmWordKind.String " " - |> buildReg ins false reg builder +let regShiftToString ins shift reg (builder: DisasmBuilder<_>) = + builder.Accumulate AsmWordKind.String (srTypeToString shift) + builder.Accumulate AsmWordKind.String " " + buildReg ins false reg builder let delimPostIdx = function | PostIdxMode _ -> "], " | _ -> ", " -let immOffsetToString ins addrMode offset builder acc = +let immOffsetToString ins addrMode offset builder = match offset with - | reg, _, None | reg, _, Some 0L -> buildReg ins false reg builder acc + | reg, _, None | reg, _, Some 0L -> buildReg ins false reg builder | reg, s, Some imm -> - buildReg ins false reg builder acc - |> builder AsmWordKind.String (delimPostIdx addrMode) - |> immToString imm s builder + buildReg ins false reg builder + builder.Accumulate AsmWordKind.String (delimPostIdx addrMode) + immToString imm s builder -let regOffsetToString ins addrMode offset builder acc = +let regOffsetToString ins addrMode offset builder = match offset with | bReg, s, reg, None -> - buildReg ins false bReg builder acc - |> builder AsmWordKind.String (delimPostIdx addrMode) - |> builder AsmWordKind.String (signToString s) - |> buildReg ins false reg builder + buildReg ins false bReg builder + builder.Accumulate AsmWordKind.String (delimPostIdx addrMode) + builder.Accumulate AsmWordKind.String (signToString s) + buildReg ins false reg builder | bReg, s, reg, Some shift -> - buildReg ins false bReg builder acc - |> builder AsmWordKind.String (delimPostIdx addrMode) - |> builder AsmWordKind.String (signToString s) - |> buildReg ins false reg builder - |> shiftToString shift (Some ", ") builder + buildReg ins false bReg builder + builder.Accumulate AsmWordKind.String (delimPostIdx addrMode) + builder.Accumulate AsmWordKind.String (signToString s) + buildReg ins false reg builder + shiftToString shift (Some ", ") builder -let alignOffsetToString ins offset builder acc = +let alignOffsetToString ins offset builder = match offset with | bReg, Some align, None -> - buildReg ins false bReg builder acc - |> builder AsmWordKind.String ":" - |> builder AsmWordKind.String (string align) + buildReg ins false bReg builder + builder.Accumulate AsmWordKind.String ":" + builder.Accumulate AsmWordKind.String (string align) | bReg, Some align, Some reg -> - buildReg ins false bReg builder acc - |> builder AsmWordKind.String ":" - |> builder AsmWordKind.String (string align) - |> builder AsmWordKind.String "], " - |> buildReg ins false reg builder + buildReg ins false bReg builder + builder.Accumulate AsmWordKind.String ":" + builder.Accumulate AsmWordKind.String (string align) + builder.Accumulate AsmWordKind.String "], " + buildReg ins false reg builder | bReg, None, Some reg -> - buildReg ins false bReg builder acc - |> builder AsmWordKind.String "], " - |> buildReg ins false reg builder - | bReg, None, None -> buildReg ins false bReg builder acc + buildReg ins false bReg builder + builder.Accumulate AsmWordKind.String "], " + buildReg ins false reg builder + | bReg, None, None -> buildReg ins false bReg builder -let offsetToString ins addrMode offset builder acc = +let offsetToString ins addrMode offset builder = match offset with | ImmOffset (reg, s, imm) -> - immOffsetToString ins addrMode (reg, s, imm) builder acc + immOffsetToString ins addrMode (reg, s, imm) builder | RegOffset (bReg, s, reg, shf) -> - regOffsetToString ins addrMode (bReg, s, reg, shf) builder acc + regOffsetToString ins addrMode (bReg, s, reg, shf) builder | AlignOffset (bReg, align, reg) -> - alignOffsetToString ins (bReg, align, reg) builder acc + alignOffsetToString ins (bReg, align, reg) builder let processAddrExn32 ins addr = let pc = @@ -772,32 +773,48 @@ let processAddrExn32 ins addr = | Op.ADR -> ParseUtils.align pc 4UL | _ -> addr -let memHead ins addr addrMode builder acc = +let calculateRelativePC lbl addr = int32 addr + int32 lbl |> uint64 + +let commentWithSymbol helper addr addrStr (builder: DisasmBuilder<_>) = + if builder.ResolveSymbol then + match (helper: DisasmHelper).FindFunctionSymbol (addr) with + | Error _ -> + builder.Accumulate AsmWordKind.String addrStr + | Ok "" -> () + | Ok name -> + builder.Accumulate AsmWordKind.String (addrStr + " ; <") + builder.Accumulate AsmWordKind.Value name + builder.Accumulate AsmWordKind.String ">" + else () + +let memHead hlp ins addr addrMode (builder: DisasmBuilder<_>) = match addrMode with | OffsetMode offset | PreIdxMode offset | PostIdxMode offset -> - builder AsmWordKind.String "[" acc - |> offsetToString ins addrMode offset builder + builder.Accumulate AsmWordKind.String "[" + offsetToString ins addrMode offset builder | UnIdxMode (reg, opt) -> - builder AsmWordKind.String "[" acc - |> buildReg ins false reg builder - |> builder AsmWordKind.String "], {" - |> optionToString opt builder + builder.Accumulate AsmWordKind.String "[" + buildReg ins false reg builder + builder.Accumulate AsmWordKind.String "], {" + optionToString opt builder | LiteralMode lbl -> - let addr = processAddrExn32 ins addr - let str = "0x" + ((int32 addr) + (int32 lbl)).ToString ("x") - builder AsmWordKind.String str acc + let addr = processAddrExn32 ins addr |> calculateRelativePC lbl + let addrStr = "0x" + addr.ToString ("x") + match ins.Opcode with + | Op.BL | Op.BLX -> commentWithSymbol hlp addr addrStr builder + | _ -> builder.Accumulate AsmWordKind.String addrStr -let memTail addrMode builder acc = +let memTail addrMode (builder: DisasmBuilder<_>) = match addrMode with - | OffsetMode _ -> builder AsmWordKind.String "]" acc - | PreIdxMode _ -> builder AsmWordKind.String "]!" acc - | PostIdxMode _ -> acc - | UnIdxMode _ -> builder AsmWordKind.String "}" acc - | LiteralMode _ -> acc + | OffsetMode _ -> builder.Accumulate AsmWordKind.String "]" + | PreIdxMode _ -> builder.Accumulate AsmWordKind.String "]!" + | PostIdxMode _ -> () + | UnIdxMode _ -> builder.Accumulate AsmWordKind.String "}" + | LiteralMode _ -> () -let memToString ins addr addrMode builder acc = - memHead ins addr addrMode builder acc - |> memTail addrMode builder +let memToString hlp ins addr addrMode builder = + memHead hlp ins addr addrMode builder + memTail addrMode builder let optToString = function | SY -> "sy" @@ -822,78 +839,87 @@ let iFlagToString = function | IF -> "if" | AIF -> "aif" -let endToString = function +let endToString endian = + match endian with | Endian.Little -> "le" | Endian.Big -> "be" - | _ -> invalidArg "Endian" "Invalid endian is given." + | _ -> invalidArg (nameof endian) "Invalid endian is given." -let oprToString i addr operand delim builder acc = +let oprToString hlp ins addr operand delim builder = match operand with | OprReg reg -> - prependDelimiter delim builder acc |> buildReg i false reg builder + prependDelimiter delim builder + buildReg ins false reg builder | OprSpecReg (reg, pFlag) -> - prependDelimiter delim builder acc |> specRegToString i reg pFlag builder + prependDelimiter delim builder + specRegToString ins reg pFlag builder | OprRegList regList -> - prependDelimiter delim builder acc |> regListToString i regList builder + prependDelimiter delim builder + regListToString ins regList builder | OprSIMD simd -> - prependDelimiter delim builder acc |> simdOprToString i simd builder + prependDelimiter delim builder + simdOprToString ins simd builder | OprImm imm -> - prependDelimiter delim builder acc |> immToString imm None builder + prependDelimiter delim builder + immToString imm None builder | OprFPImm fp -> - prependDelimiter delim builder acc |> fpImmToString fp builder + prependDelimiter delim builder + fpImmToString fp builder | OprShift s -> - shiftToString s delim builder acc + shiftToString s delim builder | OprRegShift (s, r) -> - prependDelimiter delim builder acc |> regShiftToString i s r builder + prependDelimiter delim builder + regShiftToString ins s r builder | OprMemory addrMode -> - prependDelimiter delim builder acc |> memToString i addr addrMode builder + prependDelimiter delim builder + memToString hlp ins addr addrMode builder | OprOption opt -> - prependDelimiter delim builder acc - |> builder AsmWordKind.String (optToString opt) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.String (optToString opt) | OprIflag flag -> - prependDelimiter delim builder acc - |> builder AsmWordKind.String (iFlagToString flag) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.String (iFlagToString flag) | OprEndian e -> - prependDelimiter delim builder acc - |> builder AsmWordKind.String (endToString e) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.String (endToString e) | OprCond c -> - prependDelimiter delim builder acc - |> builder AsmWordKind.String (condToString (Some c)) - | GoToLabel _ -> acc + prependDelimiter delim builder + builder.Accumulate AsmWordKind.String (condToString (Some c)) + | GoToLabel _ -> () -let buildOprs ins pc builder acc = +let buildOprs hlp ins pc builder = match ins.Operands with - | NoOperand -> acc + | NoOperand -> () | OneOperand opr -> - oprToString ins pc opr (Some " ") builder acc + oprToString hlp ins pc opr (Some " ") builder | TwoOperands (opr1, opr2) -> - oprToString ins pc opr1 (Some " ") builder acc - |> oprToString ins pc opr2 (Some ", ") builder + oprToString hlp ins pc opr1 (Some " ") builder + oprToString hlp ins pc opr2 (Some ", ") builder | ThreeOperands (opr1, opr2, opr3) -> - oprToString ins pc opr1 (Some " ") builder acc - |> oprToString ins pc opr2 (Some ", ") builder - |> oprToString ins pc opr3 (Some ", ") builder + oprToString hlp ins pc opr1 (Some " ") builder + oprToString hlp ins pc opr2 (Some ", ") builder + oprToString hlp ins pc opr3 (Some ", ") builder | FourOperands (opr1, opr2, opr3, opr4) -> - oprToString ins pc opr1 (Some " ") builder acc - |> oprToString ins pc opr2 (Some ", ") builder - |> oprToString ins pc opr3 (Some ", ") builder - |> oprToString ins pc opr4 (Some ", ") builder + oprToString hlp ins pc opr1 (Some " ") builder + oprToString hlp ins pc opr2 (Some ", ") builder + oprToString hlp ins pc opr3 (Some ", ") builder + oprToString hlp ins pc opr4 (Some ", ") builder | FiveOperands (opr1, opr2, opr3, opr4, opr5) -> - oprToString ins pc opr1 (Some " ") builder acc - |> oprToString ins pc opr2 (Some ", ") builder - |> oprToString ins pc opr3 (Some ", ") builder - |> oprToString ins pc opr4 (Some ", ") builder - |> oprToString ins pc opr5 (Some ", ") builder + oprToString hlp ins pc opr1 (Some " ") builder + oprToString hlp ins pc opr2 (Some ", ") builder + oprToString hlp ins pc opr3 (Some ", ") builder + oprToString hlp ins pc opr4 (Some ", ") builder + oprToString hlp ins pc opr5 (Some ", ") builder | SixOperands (opr1, opr2, opr3, opr4, opr5, opr6) -> - oprToString ins pc opr1 (Some " ") builder acc - |> oprToString ins pc opr2 (Some ", ") builder - |> oprToString ins pc opr3 (Some ", ") builder - |> oprToString ins pc opr4 (Some ", ") builder - |> oprToString ins pc opr5 (Some ", ") builder - |> oprToString ins pc opr6 (Some ", ") builder - -let disasm showAddr ins builder acc = + oprToString hlp ins pc opr1 (Some " ") builder + oprToString hlp ins pc opr2 (Some ", ") builder + oprToString hlp ins pc opr3 (Some ", ") builder + oprToString hlp ins pc opr4 (Some ", ") builder + oprToString hlp ins pc opr5 (Some ", ") builder + oprToString hlp ins pc opr6 (Some ", ") builder + +let disasm hlp ins (builder: DisasmBuilder<_>) = let pc = ins.Address - DisasmBuilder.addr pc WordSize.Bit32 showAddr builder acc - |> buildOpcode ins builder - |> buildOprs ins pc builder + if builder.ShowAddr then builder.AccumulateAddr () else () + buildOpcode ins builder + buildOprs hlp ins pc builder diff --git a/src/FrontEnd/ARM32/ARM32Exceptions.fs b/src/FrontEnd/BinLifter/ARM32/ARM32Exceptions.fs similarity index 97% rename from src/FrontEnd/ARM32/ARM32Exceptions.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32Exceptions.fs index 348586bb..e8ba340f 100644 --- a/src/FrontEnd/ARM32/ARM32Exceptions.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32Exceptions.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM32 +namespace B2R2.FrontEnd.BinLifter.ARM32 /// This is a fatal error that happens when B2R2 tries to access non-existing /// register symbol. This exception should not happen in general. diff --git a/src/FrontEnd/ARM32/ARM32IRHelper.fs b/src/FrontEnd/BinLifter/ARM32/ARM32IRHelper.fs similarity index 63% rename from src/FrontEnd/ARM32/ARM32IRHelper.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32IRHelper.fs index c6ecde50..b1ecb7c5 100644 --- a/src/FrontEnd/ARM32/ARM32IRHelper.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32IRHelper.fs @@ -22,87 +22,87 @@ SOFTWARE. *) -module B2R2.FrontEnd.ARM32.IRHelper +module B2R2.FrontEnd.BinLifter.ARM32.IRHelper open B2R2 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -open B2R2.BinIR.LowUIR.AST +open B2R2.BinIR.LowUIR.AST.InfixOp let getRegVar (ctxt: TranslationContext) name = Register.toRegID name |> ctxt.GetRegVar /// Returns TRUE if the implementation includes the Security Extensions, /// on page B1-1157. function : HaveSecurityExt() -let haveSecurityExt () = b0 +let haveSecurityExt () = AST.b0 /// Returns TRUE if the implementation includes the Virtualization Extensions, /// on page AppxP-2660. function : HaveVirtExt() -let haveVirtExt () = b0 +let haveVirtExt () = AST.b0 /// Gets the mask bits for fetching the condition flag bits from the PSR. /// PSR bit[31:28] -let maskPSRForCondbits = num <| BitVector.ofUBInt 4026531840I 32 +let maskPSRForCondbits = AST.num <| BitVector.ofBInt 4026531840I 32 /// Gets the mask bits for fetching the N condition flag from the PSR. /// PSR bit[31] -let maskPSRForNbit = num <| BitVector.ofUBInt 2147483648I 32 +let maskPSRForNbit = AST.num <| BitVector.ofBInt 2147483648I 32 /// Gets the mask bits for fetching the Z condition flag from the PSR. /// PSR bits[30] -let maskPSRForZbit = num <| BitVector.ofUBInt 1073741824I 32 +let maskPSRForZbit = AST.num <| BitVector.ofBInt 1073741824I 32 /// Gets the mask bits for fetching the C condition flag from the PSR. /// PSR bit[29] -let maskPSRForCbit = num <| BitVector.ofUBInt 536870912I 32 +let maskPSRForCbit = AST.num <| BitVector.ofBInt 536870912I 32 /// Gets the mask bits for fetching the V condition flag from the PSR. /// PSR bit[28] -let maskPSRForVbit = num <| BitVector.ofUBInt 268435456I 32 +let maskPSRForVbit = AST.num <| BitVector.ofBInt 268435456I 32 /// Gets the mask bits for fetching the Q bit from the PSR. /// PSR bit[27] -let maskPSRForQbit = num <| BitVector.ofUBInt 134217728I 32 +let maskPSRForQbit = AST.num <| BitVector.ofBInt 134217728I 32 /// Gets the mask bits for fetching the IT[1:0] bits from the PSR. /// PSR bits[26:25] -let maskPSRForIT10bits = num <| BitVector.ofUBInt 100663296I 32 +let maskPSRForIT10bits = AST.num <| BitVector.ofBInt 100663296I 32 /// Gets the mask bits for fetching the J bit from the PSR. /// PSR bit[24] -let maskPSRForJbit = num <| BitVector.ofUBInt 16777216I 32 +let maskPSRForJbit = AST.num <| BitVector.ofBInt 16777216I 32 /// Gets the mask bits for fetching the GE[3:0] bits from the PSR. /// PSR bits[19:16] -let maskPSRForGEbits = num <| BitVector.ofUBInt 983040I 32 +let maskPSRForGEbits = AST.num <| BitVector.ofBInt 983040I 32 /// Gets the mask bits for fetching the IT[7:2] bits from the PSR. /// PSR bits[15:10] -let maskPSRForIT72bits = num <| BitVector.ofUBInt 64512I 32 +let maskPSRForIT72bits = AST.num <| BitVector.ofBInt 64512I 32 /// Gets the mask bits for fetching the E bit from the PSR. /// PSR bit[9] -let maskPSRForEbit = num <| BitVector.ofUBInt 512I 32 +let maskPSRForEbit = AST.num <| BitVector.ofBInt 512I 32 /// Gets the mask bits for fetching the A bit from the PSR. /// PSR bit[8] -let maskPSRForAbit = num <| BitVector.ofUBInt 256I 32 +let maskPSRForAbit = AST.num <| BitVector.ofBInt 256I 32 /// Gets the mask bits for fetching the I bit from the PSR. /// PSR bit[7] -let maskPSRForIbit = num <| BitVector.ofUBInt 128I 32 +let maskPSRForIbit = AST.num <| BitVector.ofBInt 128I 32 /// Gets the mask bits for fetching the F bit from the PSR. /// PSR bit[6] -let maskPSRForFbit = num <| BitVector.ofUBInt 64I 32 +let maskPSRForFbit = AST.num <| BitVector.ofBInt 64I 32 /// Gets the mask bits for fetching the T bit from the PSR. /// PSR bit[5] -let maskPSRForTbit = num <| BitVector.ofUBInt 32I 32 +let maskPSRForTbit = AST.num <| BitVector.ofBInt 32I 32 /// Gets the mask bits for fetching the M[4:0] bits from the PSR. /// PSR bits[4:0] -let maskPSRForMbits = num <| BitVector.ofUBInt 31I 32 +let maskPSRForMbits = AST.num <| BitVector.ofBInt 31I 32 /// Get PSR bits without shifting it. let internal getPSR ctxt reg psrType = @@ -136,47 +136,49 @@ let isSetCPSR_M ctxt = getPSR ctxt R.CPSR PSR_M == maskPSRForMbits /// Test whether mode number is valid, on page B1-1142. /// function : BadMode() let isBadMode modeM = - let cond1 = modeM == (num <| BitVector.ofInt32 0b10000 32) - let cond2 = modeM == (num <| BitVector.ofInt32 0b10001 32) - let cond3 = modeM == (num <| BitVector.ofInt32 0b10010 32) - let cond4 = modeM == (num <| BitVector.ofInt32 0b10011 32) - let cond5 = modeM == (num <| BitVector.ofInt32 0b10110 32) - let cond6 = modeM == (num <| BitVector.ofInt32 0b10111 32) - let cond7 = modeM == (num <| BitVector.ofInt32 0b11010 32) - let cond8 = modeM == (num <| BitVector.ofInt32 0b11011 32) - let cond9 = modeM == (num <| BitVector.ofInt32 0b11111 32) - let ite1 = ite cond9 b0 b1 - let ite2 = ite cond8 b0 ite1 - let ite3 = ite cond7 (haveVirtExt () |> not) ite2 - let ite4 = ite cond6 b0 ite3 - let ite5 = ite cond5 (haveSecurityExt () |> not) ite4 - let ite6 = ite cond4 b0 ite5 - let ite7 = ite cond3 b0 ite6 - let ite8 = ite cond2 b0 ite7 - ite cond1 b0 ite8 + let cond1 = modeM == (AST.num <| BitVector.ofInt32 0b10000 32) + let cond2 = modeM == (AST.num <| BitVector.ofInt32 0b10001 32) + let cond3 = modeM == (AST.num <| BitVector.ofInt32 0b10010 32) + let cond4 = modeM == (AST.num <| BitVector.ofInt32 0b10011 32) + let cond5 = modeM == (AST.num <| BitVector.ofInt32 0b10110 32) + let cond6 = modeM == (AST.num <| BitVector.ofInt32 0b10111 32) + let cond7 = modeM == (AST.num <| BitVector.ofInt32 0b11010 32) + let cond8 = modeM == (AST.num <| BitVector.ofInt32 0b11011 32) + let cond9 = modeM == (AST.num <| BitVector.ofInt32 0b11111 32) + let ite1 = AST.ite cond9 AST.b0 AST.b1 + let ite2 = AST.ite cond8 AST.b0 ite1 + let ite3 = AST.ite cond7 (haveVirtExt () |> AST.not) ite2 + let ite4 = AST.ite cond6 AST.b0 ite3 + let ite5 = AST.ite cond5 (haveSecurityExt () |> AST.not) ite4 + let ite6 = AST.ite cond4 AST.b0 ite5 + let ite7 = AST.ite cond3 AST.b0 ite6 + let ite8 = AST.ite cond2 AST.b0 ite7 + AST.ite cond1 AST.b0 ite8 /// Returns TRUE if current mode is User or System mode, on page B1-1142. /// function : CurrentModeIsUserOrSystem() let currentModeIsUserOrSystem ctxt = let modeM = getPSR ctxt R.CPSR PSR_M let modeCond = isBadMode modeM - let ite1 = modeM == (num <| BitVector.ofInt32 0b11111 32) - let ite2 = ite (modeM == (num <| BitVector.ofInt32 0b10000 32)) b1 ite1 - ite modeCond (Expr.Undefined (1, "UNPREDICTABLE")) ite2 + let ite1 = modeM == (AST.num <| BitVector.ofInt32 0b11111 32) + let ite2 = + AST.ite (modeM == (AST.num <| BitVector.ofInt32 0b10000 32)) AST.b1 ite1 + AST.ite modeCond (AST.undef 1 "UNPREDICTABLE") ite2 /// Returns TRUE if current mode is Hyp mode, on page B1-1142. /// function : CurrentModeIsHyp() let currentModeIsHyp ctxt = let modeM = getPSR ctxt R.CPSR PSR_M let modeCond = isBadMode modeM - let ite1 = modeM == (num <| BitVector.ofInt32 0b11010 32) - ite modeCond (Expr.Undefined (1, "UNPREDICTABLE")) ite1 + let ite1 = modeM == (AST.num <| BitVector.ofInt32 0b11010 32) + AST.ite modeCond (AST.undef 1 "UNPREDICTABLE") ite1 /// Is this ARM instruction set, on page A2-51. -let isInstrSetARM ctxt = not (isSetCPSR_J ctxt) .& not (isSetCPSR_T ctxt) +let isInstrSetARM ctxt = + AST.not (isSetCPSR_J ctxt) .& AST.not (isSetCPSR_T ctxt) /// Is this Thumb instruction set, on page A2-51. -let isInstrSetThumb ctxt = not (isSetCPSR_J ctxt) .& (isSetCPSR_T ctxt) +let isInstrSetThumb ctxt = AST.not (isSetCPSR_J ctxt) .& (isSetCPSR_T ctxt) /// Is this ThumbEE instruction set, on page A2-51. let isInstrSetThumbEE ctxt = (isSetCPSR_J ctxt) .& (isSetCPSR_T ctxt) diff --git a/src/FrontEnd/ARM32/ARM32Instruction.fs b/src/FrontEnd/BinLifter/ARM32/ARM32Instruction.fs similarity index 67% rename from src/FrontEnd/ARM32/ARM32Instruction.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32Instruction.fs index 9699e191..4f7097d0 100644 --- a/src/FrontEnd/ARM32/ARM32Instruction.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32Instruction.fs @@ -22,22 +22,19 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM32 +namespace B2R2.FrontEnd.BinLifter.ARM32 open B2R2 -open B2R2.FrontEnd -open System.Text +open B2R2.FrontEnd.BinLifter /// The internal representation for an ARM32 instruction used by our /// disassembler and lifter. -type ARM32Instruction (addr, numBytes, insInfo, ctxt, auxctxt) = +type ARM32Instruction (addr, numBytes, insInfo) = inherit Instruction (addr, numBytes, WordSize.Bit32) - member val Info: InsInfo = insInfo - - override __.NextParsingContext = ctxt + let dummyHelper = DisasmHelper () - override __.AuxParsingContext = auxctxt + member val Info: InsInfo = insInfo override __.IsBranch () = match __.Info.Opcode with @@ -54,6 +51,11 @@ type ARM32Instruction (addr, numBytes, insInfo, ctxt, auxctxt) = | _ -> false | _ -> false + override __.IsModeChanging () = + match __.Info.Opcode with + | Op.BLX -> true + | _ -> false + member __.HasConcJmpTarget () = match __.Info.Operands with | OneOperand (OprMemory (LiteralMode _)) -> true @@ -94,15 +96,24 @@ type ARM32Instruction (addr, numBytes, insInfo, ctxt, auxctxt) = | _ -> false override __.IsRET () = - Utils.futureFeature () + match __.Info with + | { Opcode = Op.LDR; Operands = TwoOperands (OprReg R.PC, _)} -> true + | { Opcode = Op.POP; Operands = OneOperand (OprRegList regs) } + when List.contains R.PC regs -> true + | _ -> false override __.IsInterrupt () = - __.Info.Opcode = Op.SVC + match __.Info.Opcode with + | Op.SVC | Op.HVC | Op.SMC -> true + | _ -> false override __.IsExit () = + Utils.futureFeature () + + override __.IsBBLEnd () = __.IsDirectBranch () || __.IsIndirectBranch () || - __.Info.Opcode = Op.SVC + __.IsInterrupt () override __.DirectBranchTarget (addr: byref) = if __.IsBranch () then @@ -120,6 +131,31 @@ type ARM32Instruction (addr, numBytes, insInfo, ctxt, auxctxt) = override __.IndirectTrampolineAddr (_: byref) = false + override __.Immediate (v: byref) = + match __.Info.Operands with + | OneOperand (OprImm c) + | TwoOperands (OprImm c, _) + | TwoOperands (_, OprImm c) + | ThreeOperands (OprImm c, _, _) + | ThreeOperands (_, OprImm c, _) + | ThreeOperands (_, _, OprImm c) + | FourOperands (OprImm c, _, _, _) + | FourOperands (_, OprImm c, _, _) + | FourOperands (_, _, OprImm c, _) + | FourOperands (_, _, _, OprImm c) + | FiveOperands (OprImm c, _, _, _, _) + | FiveOperands (_, OprImm c, _, _, _) + | FiveOperands (_, _, OprImm c, _, _) + | FiveOperands (_, _, _, OprImm c, _) + | FiveOperands (_, _, _, _, OprImm c) + | SixOperands (OprImm c, _, _, _, _, _) + | SixOperands (_, OprImm c, _, _, _, _) + | SixOperands (_, _, OprImm c, _, _, _) + | SixOperands (_, _, _, OprImm c, _, _) + | SixOperands (_, _, _, _, OprImm c, _) + | SixOperands (_, _, _, _, _, OprImm c) -> v <- c; true + | _ -> false + member private __.GetNextMode () = match __.Info.Opcode with | Opcode.BLX @@ -144,7 +180,7 @@ type ARM32Instruction (addr, numBytes, insInfo, ctxt, auxctxt) = elif __.Info.Opcode = Opcode.HLT then Seq.empty else acc - override __.InterruptNum (num: byref) = Utils.futureFeature () + override __.InterruptNum (_num: byref) = Utils.futureFeature () override __.IsNop () = __.Info.Opcode = Op.NOP @@ -152,25 +188,27 @@ type ARM32Instruction (addr, numBytes, insInfo, ctxt, auxctxt) = override __.Translate ctxt = Lifter.translate __.Info ctxt - member private __.StrBuilder _ (str: string) (acc: StringBuilder) = - acc.Append (str) - - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = - let acc = StringBuilder () - let acc = Disasm.disasm showAddr __.Info __.StrBuilder acc - acc.ToString () + override __.Disasm (showAddr, resolveSym, disasmHelper) = + let builder = + DisasmStringBuilder (showAddr, resolveSym, WordSize.Bit32, addr, numBytes) + Disasm.disasm disasmHelper __.Info builder + builder.Finalize () override __.Disasm () = - let acc = StringBuilder () - let acc = Disasm.disasm false __.Info __.StrBuilder acc - acc.ToString () + let builder = + DisasmStringBuilder (false, false, WordSize.Bit32, addr, numBytes) + Disasm.disasm dummyHelper __.Info builder + builder.Finalize () + + override __.Decompose (showAddr) = + let builder = + DisasmWordBuilder (showAddr, false, WordSize.Bit32, addr, numBytes, 8) + Disasm.disasm dummyHelper __.Info builder + builder.Finalize () - member private __.WordBuilder kind str (acc: AsmWordBuilder) = - acc.Append ({ AsmWordKind = kind; AsmWordValue = str }) + override __.IsInlinedAssembly () = false - override __.Decompose () = - AsmWordBuilder (8) - |> Disasm.disasm true __.Info __.WordBuilder - |> fun b -> b.Finish () + override __.Equals (_) = Utils.futureFeature () + override __.GetHashCode () = Utils.futureFeature () // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/ARM32/ARM32Lifter.fs b/src/FrontEnd/BinLifter/ARM32/ARM32Lifter.fs similarity index 72% rename from src/FrontEnd/ARM32/ARM32Lifter.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32Lifter.fs index 37e81f13..3cfefe6e 100644 --- a/src/FrontEnd/ARM32/ARM32Lifter.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32Lifter.fs @@ -22,18 +22,18 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.ARM32.Lifter +module internal B2R2.FrontEnd.BinLifter.ARM32.Lifter open System open B2R2 open B2R2.BinIR open B2R2.BinIR.LowUIR -open B2R2.BinIR.LowUIR.AST -open B2R2.FrontEnd -open B2R2.FrontEnd.ARM32 -open B2R2.FrontEnd.ARM32.IRHelper +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.ARM32 +open B2R2.FrontEnd.BinLifter.ARM32.IRHelper -let inline private ( acc + getRegNum reg) 0u regs -let regsToExpr regs = num <| BitVector.ofUInt32 (regsToUInt32 regs) 16 +let regsToExpr regs = AST.num <| BitVector.ofUInt32 (regsToUInt32 regs) 16 let sfRegToExpr ctxt = function | Vector reg -> getRegVar ctxt reg @@ -81,7 +81,7 @@ let transOprToExpr ctxt = function | OprReg reg -> getRegVar ctxt reg | OprRegList regs -> regsToExpr regs | OprSIMD simd -> simdToExpr ctxt simd - | OprImm imm -> num <| BitVector.ofInt64 imm 32 // FIXME + | OprImm imm -> AST.num <| BitVector.ofInt64 imm 32 // FIXME | _ -> raise InvalidOperandException let transOneOpr insInfo ctxt = @@ -110,11 +110,11 @@ let transFourOprs insInfo ctxt = transOprToExpr ctxt o4 | _ -> raise InvalidOperandException -let bvOfBaseAddr addr = num <| BitVector.ofUInt64 addr 32 +let bvOfBaseAddr addr = AST.num <| BitVector.ofUInt64 addr 32 /// Gets the mask bits for fetching the RFR bit from the NSACR. /// NSACR bit[19] -let maskNSACRForRFRbit = num <| BitVector.ofInt32 524288 32 +let maskNSACRForRFRbit = AST.num <| BitVector.ofInt32 524288 32 let getNSACR ctxt nsacrType = let nsacr = getRegVar ctxt R.NSACR @@ -125,15 +125,15 @@ let isSetNSACR_RFR ctxt = getNSACR ctxt NSACR_RFR == maskNSACRForRFRbit /// Gets the mask bits for fetching the AW bit from the SCR. /// SCR bit[5] -let maskSCRForAWbit = num <| BitVector.ofInt32 32 32 +let maskSCRForAWbit = AST.num <| BitVector.ofInt32 32 32 /// Gets the mask bits for fetching the FW bit from the SCR. /// SCR bit[4] -let maskSCRForFWbit = num <| BitVector.ofInt32 16 32 +let maskSCRForFWbit = AST.num <| BitVector.ofInt32 16 32 /// Gets the mask bits for fetching the NS bit from the SCR. /// SCR bit[0] -let maskSCRForNSbit = num1 32 +let maskSCRForNSbit = AST.num1 32 let getSCR ctxt scrType = let scr = getRegVar ctxt R.SCR @@ -148,7 +148,7 @@ let isSetSCR_NS ctxt = getSCR ctxt SCR_NS == maskSCRForNSbit /// Gets the mask bits for fetching the NMFI bit from the SCTLR. /// SCTLR bit[27] -let maskSCTLRForNMFIbit = num <| BitVector.ofUBInt 134217728I 32 +let maskSCTLRForNMFIbit = AST.num <| BitVector.ofBInt 134217728I 32 let getSCTLR ctxt sctlrType = let sctlr = getRegVar ctxt R.SCTLR @@ -180,50 +180,50 @@ let enablePSRBits ctxt reg psrType = let disablePSRBits ctxt reg psrType = let psr = getRegVar ctxt reg match psrType with - | PSR_Cond -> psr .& not maskPSRForCondbits - | PSR_N -> psr .& not maskPSRForNbit - | PSR_Z -> psr .& not maskPSRForZbit - | PSR_C -> psr .& not maskPSRForCbit - | PSR_V -> psr .& not maskPSRForVbit - | PSR_Q -> psr .& not maskPSRForQbit - | PSR_IT10 -> psr .& not maskPSRForIT10bits - | PSR_J -> psr .& not maskPSRForJbit - | PSR_GE -> psr .& not maskPSRForGEbits - | PSR_IT72 -> psr .& not maskPSRForIT72bits - | PSR_E -> psr .& not maskPSRForEbit - | PSR_A -> psr .& not maskPSRForAbit - | PSR_I -> psr .& not maskPSRForIbit - | PSR_F -> psr .& not maskPSRForFbit - | PSR_T -> psr .& not maskPSRForTbit - | PSR_M -> psr .& not maskPSRForMbits + | PSR_Cond -> psr .& AST.not maskPSRForCondbits + | PSR_N -> psr .& AST.not maskPSRForNbit + | PSR_Z -> psr .& AST.not maskPSRForZbit + | PSR_C -> psr .& AST.not maskPSRForCbit + | PSR_V -> psr .& AST.not maskPSRForVbit + | PSR_Q -> psr .& AST.not maskPSRForQbit + | PSR_IT10 -> psr .& AST.not maskPSRForIT10bits + | PSR_J -> psr .& AST.not maskPSRForJbit + | PSR_GE -> psr .& AST.not maskPSRForGEbits + | PSR_IT72 -> psr .& AST.not maskPSRForIT72bits + | PSR_E -> psr .& AST.not maskPSRForEbit + | PSR_A -> psr .& AST.not maskPSRForAbit + | PSR_I -> psr .& AST.not maskPSRForIbit + | PSR_F -> psr .& AST.not maskPSRForFbit + | PSR_T -> psr .& AST.not maskPSRForTbit + | PSR_M -> psr .& AST.not maskPSRForMbits let setPSR ctxt reg psrType expr = let shift expr = match psrType with - | PSR_Cond -> expr << (num <| BitVector.ofInt32 28 32) - | PSR_N -> expr << (num <| BitVector.ofInt32 31 32) - | PSR_Z -> expr << (num <| BitVector.ofInt32 30 32) - | PSR_C -> expr << (num <| BitVector.ofInt32 29 32) - | PSR_V -> expr << (num <| BitVector.ofInt32 28 32) - | PSR_Q -> expr << (num <| BitVector.ofInt32 27 32) - | PSR_IT10 -> expr << (num <| BitVector.ofInt32 25 32) - | PSR_J -> expr << (num <| BitVector.ofInt32 24 32) - | PSR_GE -> expr << (num <| BitVector.ofInt32 16 32) - | PSR_IT72 -> expr << (num <| BitVector.ofInt32 10 32) - | PSR_E -> expr << (num <| BitVector.ofInt32 9 32) - | PSR_A -> expr << (num <| BitVector.ofInt32 8 32) - | PSR_I -> expr << (num <| BitVector.ofInt32 7 32) - | PSR_F -> expr << (num <| BitVector.ofInt32 6 32) - | PSR_T -> expr << (num <| BitVector.ofInt32 5 32) + | PSR_Cond -> expr << (AST.num <| BitVector.ofInt32 28 32) + | PSR_N -> expr << (AST.num <| BitVector.ofInt32 31 32) + | PSR_Z -> expr << (AST.num <| BitVector.ofInt32 30 32) + | PSR_C -> expr << (AST.num <| BitVector.ofInt32 29 32) + | PSR_V -> expr << (AST.num <| BitVector.ofInt32 28 32) + | PSR_Q -> expr << (AST.num <| BitVector.ofInt32 27 32) + | PSR_IT10 -> expr << (AST.num <| BitVector.ofInt32 25 32) + | PSR_J -> expr << (AST.num <| BitVector.ofInt32 24 32) + | PSR_GE -> expr << (AST.num <| BitVector.ofInt32 16 32) + | PSR_IT72 -> expr << (AST.num <| BitVector.ofInt32 10 32) + | PSR_E -> expr << (AST.num <| BitVector.ofInt32 9 32) + | PSR_A -> expr << (AST.num <| BitVector.ofInt32 8 32) + | PSR_I -> expr << (AST.num <| BitVector.ofInt32 7 32) + | PSR_F -> expr << (AST.num <| BitVector.ofInt32 6 32) + | PSR_T -> expr << (AST.num <| BitVector.ofInt32 5 32) | PSR_M -> expr - disablePSRBits ctxt reg psrType .| (zExt 32 expr |> shift) + disablePSRBits ctxt reg psrType .| (AST.zext 32 expr |> shift) let getCarryFlag ctxt = - getPSR ctxt R.CPSR PSR_C >> (num <| BitVector.ofInt32 29 32) + getPSR ctxt R.CPSR PSR_C >> (AST.num <| BitVector.ofInt32 29 32) let getZeroMask maskSize regType = - BitVector.ofUBInt (BigInteger.getMask maskSize) regType - |> BitVector.bnot |> num + BitVector.ofBInt (BigInteger.getMask maskSize) regType + |> BitVector.bnot |> AST.num let zMaskAnd e regType maskSize = e .& (getZeroMask maskSize regType) @@ -234,9 +234,9 @@ let maskAndOR e1 e2 regType maskSize = expr .| e2 let getOverflowFlagOnAdd e1 e2 r = - let e1High = extractHigh 1 e1 - let e2High = extractHigh 1 e2 - let rHigh = extractHigh 1 r + let e1High = AST.xthi 1 e1 + let e2High = AST.xthi 1 e2 + let rHigh = AST.xthi 1 r (e1High == e2High) .& (e1High <+> rHigh) let parseCond = function @@ -268,20 +268,20 @@ let conditionPassed ctxt cond = | 0b001 -> isSetCPSR_C ctxt | 0b010 -> isSetCPSR_N ctxt | 0b011 -> isSetCPSR_V ctxt - | 0b100 -> isSetCPSR_C ctxt .& not (isSetCPSR_Z ctxt) + | 0b100 -> isSetCPSR_C ctxt .& AST.not (isSetCPSR_Z ctxt) | 0b101 -> isSetCPSR_N ctxt == isSetCPSR_V ctxt - | 0b110 -> isSetCPSR_N ctxt == isSetCPSR_V ctxt .& not (isSetCPSR_Z ctxt) - | 0b111 -> b1 + | 0b110 -> isSetCPSR_N ctxt == isSetCPSR_V ctxt .& AST.not (isSetCPSR_Z ctxt) + | 0b111 -> AST.b1 | _ -> failwith "Invalid condition" - if cond1 <> 0b111 && cond2 = 1 then not result else result + if cond1 <> 0b111 && cond2 = 1 then AST.not result else result /// Logical shift left of a bitstring, with carry output, on page A2-41. /// for Register amount. function : LSL_C() let shiftLSLCForRegAmount value regType amount carryIn = - let chkZero = relop RelOpType.EQ amount (num (BitVector.ofUInt32 0u regType)) + let chkZero = AST.relop RelOpType.EQ amount (AST.num (BitVector.ofUInt32 0u regType)) let result = value << amount - let carryOut = value << (amount .- num1 regType) |> extractHigh 1 - ite chkZero value result, ite chkZero carryIn carryOut + let carryOut = value << (amount .- AST.num1 regType) |> AST.xthi 1 + AST.ite chkZero value result, AST.ite chkZero carryIn carryOut /// Logical shift left of a bitstring, on page A2-41. for Register amount. /// function : LSL() @@ -291,10 +291,10 @@ let shiftLSLForRegAmount value regType amount carryIn = /// Logical shift right of a bitstring, with carry output, on page A2-41. /// for Register amount. function : LSR_C() let shiftLSRCForRegAmount value regType amount carryIn = - let chkZero = relop RelOpType.EQ amount (num (BitVector.ofUInt32 0u regType)) + let chkZero = AST.relop RelOpType.EQ amount (AST.num (BitVector.ofUInt32 0u regType)) let result = value >> amount - let carryOut = value >> (amount .- num1 regType ) |> extractLow 1 - ite chkZero value result, ite chkZero carryIn carryOut + let carryOut = value >> (amount .- AST.num1 regType ) |> AST.xtlo 1 + AST.ite chkZero value result, AST.ite chkZero carryIn carryOut /// Logical shift right of a bitstring, on page A2-41. for Register amount. /// function : LSR() @@ -304,10 +304,10 @@ let shiftLSRForRegAmount value regType amount carryIn = /// Arithmetic shift right of a bitstring, with carry output, on page A2-41. /// for Register amount. function : ASR_C() let shiftASRCForRegAmount value regType amount carryIn = - let chkZero = relop RelOpType.EQ amount (num (BitVector.ofUInt32 0u regType)) + let chkZero = AST.relop RelOpType.EQ amount (AST.num (BitVector.ofUInt32 0u regType)) let result = value ?>> amount - let carryOut = value ?>> (amount .- num1 regType ) |> extractLow 1 - ite chkZero value result, ite chkZero carryIn carryOut + let carryOut = value ?>> (amount .- AST.num1 regType ) |> AST.xtlo 1 + AST.ite chkZero value result, AST.ite chkZero carryIn carryOut /// Logical shift right of a bitstring, on page A2-41. for Register amount. /// function : ASR() @@ -317,13 +317,13 @@ let shiftASRForRegAmount value regType amount carryIn = /// Rotate right of a bitstring, with carry output, on page A2-41. /// for Register amount. function : ROR_C() let shiftRORCForRegAmount value regType amount carryIn = - let chkZero = relop RelOpType.EQ amount (num (BitVector.ofUInt32 0u regType)) - let m = amount .% num (BitVector.ofInt32 (RegType.toBitWidth regType) regType) - let nm = (num <| BitVector.ofInt32 32 32) .- m + let chkZero = AST.relop RelOpType.EQ amount (AST.num (BitVector.ofUInt32 0u regType)) + let m = amount .% AST.num (BitVector.ofInt32 (RegType.toBitWidth regType) regType) + let nm = (AST.num <| BitVector.ofInt32 32 32) .- m let result = shiftLSRForRegAmount value regType m carryIn .| shiftLSLForRegAmount value regType nm carryIn - let carryOut = extractHigh 1 result - ite chkZero value result, ite chkZero carryIn carryOut + let carryOut = AST.xthi 1 result + AST.ite chkZero value result, AST.ite chkZero carryIn carryOut /// Rotate right of a bitstring, on page A2-41. for Register amount. /// function : ROR() @@ -333,12 +333,12 @@ let shiftRORForRegAmount value regType amount carryIn = /// Rotate right with extend of a bitstring, with carry output, on page A2-41. /// for Register amount. function : RRX_C() let shiftRRXCForRegAmount value regType amount carryIn = - let chkZero = relop RelOpType.EQ amount (num (BitVector.ofUInt32 0u regType)) - let amount1 = num (BitVector.ofInt32 (RegType.toBitWidth regType) regType) - let e1 = shiftLSLForRegAmount (zExt 32 carryIn) regType - (amount1 .- num1 regType) carryIn - let e2 = shiftLSRForRegAmount value regType (num1 regType) carryIn - ite chkZero value (e1 .| e2), ite chkZero carryIn (extractLow 1 value) + let chkZero = AST.relop RelOpType.EQ amount (AST.num (BitVector.ofUInt32 0u regType)) + let amount1 = AST.num (BitVector.ofInt32 (RegType.toBitWidth regType) regType) + let e1 = shiftLSLForRegAmount (AST.zext 32 carryIn) regType + (amount1 .- AST.num1 regType) carryIn + let e2 = shiftLSRForRegAmount value regType (AST.num1 regType) carryIn + AST.ite chkZero value (e1 .| e2), AST.ite chkZero carryIn (AST.xtlo 1 value) /// Rotate right with extend of a bitstring, on page A2-41. for Register amount. /// function : RRX() @@ -348,7 +348,7 @@ let shiftRRXForRegAmount value regType amount carryIn = /// Perform a specified shift by a specified amount on a bitstring, /// with carry output, on page A8-292. let shiftCForRegAmount value regType shiftType amount carryIn = - let carryIn = extractLow 1 carryIn + let carryIn = AST.xtlo 1 carryIn match shiftType with | SRTypeLSL -> shiftLSLCForRegAmount value regType amount carryIn | SRTypeLSR -> shiftLSRCForRegAmount value regType amount carryIn @@ -360,8 +360,8 @@ let shiftCForRegAmount value regType shiftType amount carryIn = /// function : LSL_C() let shiftLSLC value regType amount = Utils.assertByCond (amount > 0u) InvalidShiftAmountException - let amount = num (BitVector.ofUInt32 amount regType) - value << amount, value << (amount .- num1 regType ) |> extractHigh 1 + let amount = AST.num (BitVector.ofUInt32 amount regType) + value << amount, value << (amount .- AST.num1 regType ) |> AST.xthi 1 /// Logical shift left of a bitstring, on page A2-41. function : LSL() let shiftLSL value regType amount = @@ -372,8 +372,8 @@ let shiftLSL value regType amount = /// function : LSR_C() let shiftLSRC value regType amount = Utils.assertByCond (amount > 0u) InvalidShiftAmountException - let amount' = num (BitVector.ofUInt32 amount regType) - value >> amount', extract value 1 (amount - 1u |> Convert.ToInt32) + let amount' = AST.num (BitVector.ofUInt32 amount regType) + value >> amount', AST.extract value 1 (amount - 1u |> Convert.ToInt32) /// Logical shift right of a bitstring, on page A2-41. function : LSR() let shiftLSR value regType amount = @@ -384,8 +384,8 @@ let shiftLSR value regType amount = /// function : ASR_C() let shiftASRC value regType amount = Utils.assertByCond (amount > 0u) InvalidShiftAmountException - let amount = num (BitVector.ofUInt32 amount regType) - value ?>> amount, value ?>> (amount .- num1 regType ) |> extractLow 1 + let amount = AST.num (BitVector.ofUInt32 amount regType) + value ?>> amount, value ?>> (amount .- AST.num1 regType ) |> AST.xtlo 1 /// Logical shift right of a bitstring, on page A2-41. function : ASR() let shiftASR value regType amount = @@ -398,7 +398,7 @@ let shiftRORC value regType amount = Utils.assertByCond (amount <> 0u) InvalidShiftAmountException let m = amount % uint32 (RegType.toBitWidth regType) let result = shiftLSR value regType m .| shiftLSL value regType (32u - m) - result, extractHigh 1 result + result, AST.xthi 1 result /// Rotate right of a bitstring, on page A2-41. function : ROR() let shiftROR value regType amount = @@ -409,7 +409,7 @@ let shiftROR value regType amount = let shiftRRXC value regType amount = let e1 = uint32 (RegType.toBitWidth regType) - 1u |> shiftLSL amount regType let e2 = shiftLSR value regType 1u - e1 .| e2, extractLow 1 value + e1 .| e2, AST.xtlo 1 value /// Rotate right with extend of a bitstring, on page A2-41. /// function : RRX() @@ -442,19 +442,19 @@ let shift value regType shiftType amount carryIn = let addWithCarry src1 src2 carryIn = let result = src1 .+ src2 .+ carryIn let carryOut = - ite (carryIn == (BitVector.ofUInt32 1u 32 |> num)) - (ge src1 (not src2)) (gt src1 (not src2)) + AST.ite (carryIn == (BitVector.ofUInt32 1u 32 |> AST.num)) + (AST.ge src1 (AST.not src2)) (AST.gt src1 (AST.not src2)) let overflow = getOverflowFlagOnAdd src1 src2 result result, carryOut, overflow /// Sets the ARM instruction set, on page A2-51. -let selectARMInstrSet ctxt (builder: StmtBuilder) = +let selectARMInstrSet ctxt (builder: IRBuilder) = let cpsr = getRegVar ctxt R.CPSR builder 1 match insInfo.Mode with - | ArchOperationMode.ARMMode -> InterJmp (getPC ctxt, addr, jmpInfo) - | _ -> InterJmp (getPC ctxt, addr, jmpInfo) + | ArchOperationMode.ARMMode -> AST.interjmp addr jmpInfo + | _ -> AST.interjmp addr jmpInfo -let disableITStateForCondBranches ctxt isUnconditional (builder: StmtBuilder) = +let disableITStateForCondBranches ctxt isUnconditional (builder: IRBuilder) = if isUnconditional then () else let cpsr = getRegVar ctxt R.CPSR @@ -482,26 +482,25 @@ let disableITStateForCondBranches ctxt isUnconditional (builder: StmtBuilder) = /// Write value to R.PC, with interworking, on page A2-47. /// function : BXWritePC() -let bxWritePC ctxt isUnconditional addr (builder: StmtBuilder) = - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let cond1 = extractLow 1 addr == b1 - let pc = getPC ctxt +let bxWritePC ctxt isUnconditional addr (builder: IRBuilder) = + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let cond1 = AST.xtlo 1 addr == AST.b1 disableITStateForCondBranches ctxt isUnconditional builder - builder 1, InterJmpInfo.SwitchToThumb)) - builder 1) InterJmpKind.SwitchToThumb) + builder bxWritePC ctxt isUnconditional addr builder - | _ -> builder builder |> num - let n0 = num0 16 - let n1 = num1 16 - let res0 = ite (expr .& n1 == n1) n1 n0 - let res1 = ite ((expr >> n1) .& n1 == n1) n1 n0 - let res2 = ite ((expr >> (numI16 2)) .& n1 == n1) n1 n0 - let res3 = ite ((expr >> (numI16 3)) .& n1 == n1) n1 n0 - let res4 = ite ((expr >> (numI16 4)) .& n1 == n1) n1 n0 - let res5 = ite ((expr >> (numI16 5)) .& n1 == n1) n1 n0 - let res6 = ite ((expr >> (numI16 6)) .& n1 == n1) n1 n0 - let res7 = ite ((expr >> (numI16 7)) .& n1 == n1) n1 n0 - let res8 = ite ((expr >> (numI16 8)) .& n1 == n1) n1 n0 - let res9 = ite ((expr >> (numI16 9)) .& n1 == n1) n1 n0 - let res10 = ite ((expr >> (numI16 10)) .& n1 == n1) n1 n0 - let res11 = ite ((expr >> (numI16 11)) .& n1 == n1) n1 n0 - let res12 = ite ((expr >> (numI16 12)) .& n1 == n1) n1 n0 - let res13 = ite ((expr >> (numI16 13)) .& n1 == n1) n1 n0 - let res14 = ite ((expr >> (numI16 14)) .& n1 == n1) n1 n0 - let res15 = ite ((expr >> (numI16 15)) .& n1 == n1) n1 n0 + let numI16 n = BitVector.ofInt32 n 16 |> AST.num + let n0 = AST.num0 16 + let n1 = AST.num1 16 + let res0 = AST.ite (expr .& n1 == n1) n1 n0 + let res1 = AST.ite ((expr >> n1) .& n1 == n1) n1 n0 + let res2 = AST.ite ((expr >> (numI16 2)) .& n1 == n1) n1 n0 + let res3 = AST.ite ((expr >> (numI16 3)) .& n1 == n1) n1 n0 + let res4 = AST.ite ((expr >> (numI16 4)) .& n1 == n1) n1 n0 + let res5 = AST.ite ((expr >> (numI16 5)) .& n1 == n1) n1 n0 + let res6 = AST.ite ((expr >> (numI16 6)) .& n1 == n1) n1 n0 + let res7 = AST.ite ((expr >> (numI16 7)) .& n1 == n1) n1 n0 + let res8 = AST.ite ((expr >> (numI16 8)) .& n1 == n1) n1 n0 + let res9 = AST.ite ((expr >> (numI16 9)) .& n1 == n1) n1 n0 + let res10 = AST.ite ((expr >> (numI16 10)) .& n1 == n1) n1 n0 + let res11 = AST.ite ((expr >> (numI16 11)) .& n1 == n1) n1 n0 + let res12 = AST.ite ((expr >> (numI16 12)) .& n1 == n1) n1 n0 + let res13 = AST.ite ((expr >> (numI16 13)) .& n1 == n1) n1 n0 + let res14 = AST.ite ((expr >> (numI16 14)) .& n1 == n1) n1 n0 + let res15 = AST.ite ((expr >> (numI16 15)) .& n1 == n1) n1 n0 res0 .+ res1 .+ res2 .+ res3 .+ res4 .+ res5 .+ res6 .+ res7 .+ res8 .+ res9 .+ res10 .+ res11 .+ res12 .+ res13 .+ res14 .+ res15 @@ -566,7 +565,7 @@ let countLeadingZeroBits b size = size - 1 - highestSetBit b size /// OprMemory access that must be aligned, at specified privilege level, /// on page B2-1294. function : MemA[] -let memAWithPriv addr size value = b0 // FIXME +let memAWithPriv addr size value = AST.b0 // FIXME /// OprMemory access that must be aligned, at current privilege level, /// on page B2-1294. function : MemA_with_priv[] @@ -574,7 +573,7 @@ let memA addr size value = memAWithPriv addr size value /// OprMemory access that must be aligned, at specified privilege level, /// on page B2-1294. function : MemU_with_priv[] -let memUWithPriv addr size value = b0 // FIXME +let memUWithPriv addr size value = AST.b0 // FIXME /// OprMemory access without alignment requirement, at current privilege level, /// on page B2-1295. function : MemU[] @@ -587,76 +586,78 @@ let pcStoreValue ctxt = getPC ctxt /// Returns TRUE in Secure state or if no Security Extensions, on page B1-1157. /// function : IsSecure() let isSecure ctxt = - not (haveSecurityExt ()) .| not (isSetSCR_NS ctxt) .| - (getPSR ctxt R.CPSR PSR_M == (num <| BitVector.ofInt32 0b10110 32)) + AST.not (haveSecurityExt ()) .| AST.not (isSetSCR_NS ctxt) .| + (getPSR ctxt R.CPSR PSR_M == (AST.num <| BitVector.ofInt32 0b10110 32)) /// Return TRUE if current mode is executes at PL1 or higher, on page B1-1142. /// function : CurrentModeIsNotUser() let currentModeIsNotUser ctxt = let modeM = getPSR ctxt R.CPSR PSR_M let modeCond = isBadMode modeM - let ite1 = ite (modeM == (num <| BitVector.ofInt32 0b10000 32)) b0 b1 - ite modeCond (Expr.Undefined (1, "UNPREDICTABLE")) ite1 + let ite1 = + AST.ite (modeM == (AST.num <| BitVector.ofInt32 0b10000 32)) + AST.b0 AST.b1 + AST.ite modeCond (AST.undef 1 "UNPREDICTABLE") ite1 /// Bitstring replication, on page AppxP-2652. /// function : Replicate() let replicate expr regType lsb width value = - let v = BitVector.ofUBInt (BigInteger.getMask width <<< lsb) regType - if value = 0 then expr .& (v |> BitVector.bnot |> num) else expr .| (v |> num) + let v = BitVector.ofBInt (BigInteger.getMask width <<< lsb) regType + if value = 0 then expr .& (v |> BitVector.bnot |> AST.num) else expr .| (v |> AST.num) /// All-ones bitstring, on page AppxP-2652. -let ones rt = BitVector.ofUBInt (RegType.getMask rt) rt |> num - -let writeModeBits ctxt value isExcptReturn (builder: StmtBuilder) = - let lblL8 = lblSymbol "L8" - let lblL9 = lblSymbol "L9" - let lblL10 = lblSymbol "L10" - let lblL11 = lblSymbol "L11" - let lblL12 = lblSymbol "L12" - let lblL13 = lblSymbol "L13" - let lblL14 = lblSymbol "L14" - let lblL15 = lblSymbol "L15" - let lblL16 = lblSymbol "L16" - let lblL17 = lblSymbol "L17" +let ones rt = BitVector.ofBInt (RegType.getMask rt) rt |> AST.num + +let writeModeBits ctxt value isExcptReturn (builder: IRBuilder) = + let lblL8 = builder.NewSymbol "L8" + let lblL9 = builder.NewSymbol "L9" + let lblL10 = builder.NewSymbol "L10" + let lblL11 = builder.NewSymbol "L11" + let lblL12 = builder.NewSymbol "L12" + let lblL13 = builder.NewSymbol "L13" + let lblL14 = builder.NewSymbol "L14" + let lblL15 = builder.NewSymbol "L15" + let lblL16 = builder.NewSymbol "L16" + let lblL17 = builder.NewSymbol "L17" let valueM = value .& maskPSRForMbits let cpsrM = getPSR ctxt R.CPSR PSR_M - let num11010 = (num <| BitVector.ofInt32 0b11010 32) - let chkSecure = not (isSecure ctxt) - let cond1 = chkSecure .& (valueM == (num <| BitVector.ofInt32 0b10110 32)) + let num11010 = (AST.num <| BitVector.ofInt32 0b11010 32) + let chkSecure = AST.not (isSecure ctxt) + let cond1 = chkSecure .& (valueM == (AST.num <| BitVector.ofInt32 0b10110 32)) let cond2 = chkSecure .& isSetNSACR_RFR ctxt .& - (valueM == (num <| BitVector.ofInt32 0b10001 32)) + (valueM == (AST.num <| BitVector.ofInt32 0b10001 32)) let cond3 = chkSecure .& (valueM == num11010) let cond4 = chkSecure .& (cpsrM != num11010) .& (valueM == num11010) let cond5 = (cpsrM == num11010) .& (valueM != num11010) - builder - let cond = privileged .& (not nmfi .| chkValueF) .& + let chkValueF = (value .& maskPSRForFbit) == AST.num0 32 + let cond = privileged .& (AST.not nmfi .| chkValueF) .& (isSecure ctxt .| isSetSCR_FW ctxt .| haveVirtExt ()) - builder (getRegVar ctxt reg) |> zExt 32 + let amount = AST.xtlo 8 (getRegVar ctxt reg) |> AST.zext 32 e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt) | _ -> raise InvalidOperandException @@ -786,90 +787,90 @@ let parseOprOfADC insInfo ctxt = | _ -> raise InvalidOperandException let startMark insInfo builder = - builder - let cond = tmpVar 1 - let nextstate = tmpVar 32 - let lblThen = lblSymbol "LThen" - let lblElse = lblSymbol "LElse" - let lblEnd = lblSymbol "LEnd" +let itAdvance ctxt (builder: IRBuilder) = + let itstate = builder.NewTempVar 32 + let cond = builder.NewTempVar 1 + let nextstate = builder.NewTempVar 32 + let lblThen = builder.NewSymbol "LThen" + let lblElse = builder.NewSymbol "LElse" + let lblEnd = builder.NewSymbol "LEnd" let cpsr = getRegVar ctxt R.CPSR let cpsrIT10 = - getPSR ctxt R.CPSR PSR_IT10 >> (num <| BitVector.ofInt32 25 32) + getPSR ctxt R.CPSR PSR_IT10 >> (AST.num <| BitVector.ofInt32 25 32) let cpsrIT72 = - getPSR ctxt R.CPSR PSR_IT72 >> (num <| BitVector.ofInt32 8 32) - let mask10 = num <| BitVector.ofInt32 0x3 32 (* For ITSTATE[1:0] *) - let mask20 = num <| BitVector.ofInt32 0x7 32 (* For ITSTATE[2:0] *) - let mask40 = num <| BitVector.ofInt32 0x1f 32 (* For ITSTATE[4:0] *) - let mask42 = num <| BitVector.ofInt32 0x1c 32 (* For ITSTATE[4:2] *) - let cpsrIT42 = cpsr .& (num <| BitVector.ofInt32 0xffffe3ff 32) - let num8 = num <| BitVector.ofInt32 8 32 + getPSR ctxt R.CPSR PSR_IT72 >> (AST.num <| BitVector.ofInt32 8 32) + let mask10 = AST.num <| BitVector.ofInt32 0x3 32 (* For ITSTATE[1:0] *) + let mask20 = AST.num <| BitVector.ofInt32 0x7 32 (* For ITSTATE[2:0] *) + let mask40 = AST.num <| BitVector.ofInt32 0x1f 32 (* For ITSTATE[4:0] *) + let mask42 = AST.num <| BitVector.ofInt32 0x1c 32 (* For ITSTATE[4:2] *) + let cpsrIT42 = cpsr .& (AST.num <| BitVector.ofInt32 0xffffe3ff 32) + let num8 = AST.num <| BitVector.ofInt32 8 32 builder )) - builder )) + builder )) + builder )) builder setPSR ctxt R.CPSR PSR_IT10) builder () | Some (i: InsInfo) -> let target = BitVector.ofUInt64 (i.Address + uint64 i.NumBytes) 32 - builder ) + opr .+ (AST.num <| BitVector.ofInt32 rel 32) else opr let adc isSetFlags insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let dst, src1, src2 = parseOprOfADC insInfo ctxt let src1 = convertPCOpr insInfo ctxt src1 let src2 = convertPCOpr insInfo ctxt src2 - let t1, t2 = tmpVar 32, tmpVar 32 - let result = tmpVar 32 + let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 + let result = builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder @@ -882,8 +883,8 @@ let adc isSetFlags insInfo ctxt = builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) builder setPSR ctxt R.CPSR PSR_V) else () @@ -918,7 +919,7 @@ let transFourOprsOfADD insInfo ctxt = let e1 = transOprToExpr ctxt opr1 let e2 = transOprToExpr ctxt opr2 let e3 = transOprToExpr ctxt opr3 - let amount = extractLow 8 (getRegVar ctxt reg) |> zExt 32 + let amount = AST.xtlo 8 (getRegVar ctxt reg) |> AST.zext 32 e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt) | _ -> raise InvalidOperandException @@ -930,24 +931,24 @@ let parseOprOfADD insInfo ctxt = | _ -> raise InvalidOperandException let add isSetFlags insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let dst, src1, src2 = parseOprOfADD insInfo ctxt let src1 = convertPCOpr insInfo ctxt src1 let src2 = convertPCOpr insInfo ctxt src2 - let t1, t2 = tmpVar 32, tmpVar 32 + let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder builder ) + let result, carryOut, overflow = addWithCarry t1 t2 (AST.num0 32) if dst = getPC ctxt then aluWritePC ctxt insInfo isUnconditional result builder else builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) builder setPSR ctxt R.CPSR PSR_V) else () @@ -967,10 +968,10 @@ let transLableOprsOfBL insInfo targetMode imm = match targetMode with | ArchOperationMode.ARMMode -> let addr = bvOfBaseAddr (insInfo.Address + offset) - align addr (num (BitVector.ofInt32 4 32)) + align addr (AST.num (BitVector.ofInt32 4 32)) | ArchOperationMode.ThumbMode -> bvOfBaseAddr (insInfo.Address + offset) | _ -> raise InvalidTargetArchModeException - pc .+ (num <| BitVector.ofInt64 imm 32) + pc .+ (AST.num <| BitVector.ofInt64 imm 32) let targetModeOfBL insInfo = match insInfo.Opcode, insInfo.Mode with @@ -987,32 +988,32 @@ let parseOprOfBL insInfo = | _ -> raise InvalidOperandException let bl insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let alignedAddr, targetMode = parseOprOfBL insInfo let lr = getRegVar ctxt R.LR - let retAddr = bvOfBaseAddr insInfo.Address .+ (num <| BitVector.ofInt32 4 32) + let retAddr = bvOfBaseAddr insInfo.Address .+ (AST.num <| BitVector.ofInt32 4 32) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder if insInfo.Mode = ArchOperationMode.ARMMode then builder ) 32 1) + else builder ) 32 1) selectInstrSet ctxt builder targetMode - builder )) + builder )) else - let addr = addr .+ (num <| BitVector.ofInt32 2 32) - builder ) 32 1) + let addr = addr .+ (AST.num <| BitVector.ofInt32 2 32) + builder ) 32 1) bxWritePC ctxt isUnconditional (getRegVar ctxt reg) builder putEndLabel ctxt lblIgnore isUnconditional (Some insInfo) builder endMark insInfo builder @@ -1028,58 +1029,58 @@ let parseOprOfPUSHPOP insInfo = | OneOperand (OprRegList regs) -> regsToUInt32 regs //, false (unAlignedAllowed) | _ -> raise InvalidOperandException -let pushLoop ctxt numOfReg addr (builder: StmtBuilder) = +let pushLoop ctxt numOfReg addr (builder: IRBuilder) = let loop addr count = if (numOfReg >>> count) &&& 1u = 1u then if count = 13 && count <> lowestSetBit numOfReg 32 then - builder addr := (Expr.Undefined (32, "UNKNOWN"))) + builder addr := (AST.undef 32 "UNKNOWN")) else let reg = count |> byte |> OperandHelper.getRegister - builder addr := getRegVar ctxt reg) - addr .+ (num <| BitVector.ofInt32 4 32) + builder addr := getRegVar ctxt reg) + addr .+ (AST.num <| BitVector.ofInt32 4 32) else addr List.fold loop addr [ 0 .. 14 ] let push insInfo ctxt = - let builder = new StmtBuilder (32) - let t0 = tmpVar 32 + let builder = IRBuilder (32) + let t0 = builder.NewTempVar 32 let sp = getRegVar ctxt R.SP let numOfReg = parseOprOfPUSHPOP insInfo let stackWidth = 4 * bitCount numOfReg 16 - let addr = sp .- (num <| BitVector.ofInt32 stackWidth 32) + let addr = sp .- (AST.num <| BitVector.ofInt32 stackWidth 32) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder builder >> 15 &&& 1u) = 1u then - builder addr := pcStoreValue ctxt) + builder addr := pcStoreValue ctxt) else () builder , tmpVar 32 - let result = tmpVar 32 + let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 + let result = builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder builder ) + let res, carryOut, overflow = addWithCarry t1 (AST.not t2) (AST.num1 32) builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) builder setPSR ctxt R.CPSR PSR_V) else () @@ -1088,15 +1089,15 @@ let sub isSetFlags insInfo ctxt = /// B9.3.19 SUBS R.PC, R.LR (Thumb), on page B9-2008 let subsPCLRThumb insInfo ctxt = - let builder = new StmtBuilder (64) + let builder = IRBuilder (64) let _, _, src2 = parseOprOfADD insInfo ctxt let pc = getPC ctxt - let result, _, _ = addWithCarry pc (not src2) (num1 32) + let result, _, _ = addWithCarry pc (AST.not src2) (AST.num1 32) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder cpsrWriteByInstr ctxt (getRegVar ctxt R.SPSR) 0b1111 true builder - builder let _, src1, src2 = parseOprOfADC insInfo ctxt in src1.& src2 | Op.EORS -> let _, src1, src2 = parseOprOfADC insInfo ctxt in src1 <+> src2 | Op.SUBS -> let _, src1, src2 = parseOprOfADC insInfo ctxt - let r, _, _ = addWithCarry src1 (not src2) (num1 32) in r + let r, _, _ = addWithCarry src1 (AST.not src2) (AST.num1 32) in r | Op.RSBS -> let _, src1, src2 = parseOprOfADC insInfo ctxt - let r, _, _ = addWithCarry (not src1) src2 (num1 32) in r + let r, _, _ = addWithCarry (AST.not src1) src2 (AST.num1 32) in r | Op.ADDS -> let _, src1, src2 = parseOprOfADC insInfo ctxt - let r, _, _ = addWithCarry src1 src2 (num0 32) in r + let r, _, _ = addWithCarry src1 src2 (AST.num0 32) in r | Op.ADCS -> let _, src1, src2 = parseOprOfADC insInfo ctxt let r, _, _ = addWithCarry src1 src2 (getCarryFlag ctxt) in r | Op.SBCS -> let _, src1, src2 = parseOprOfADC insInfo ctxt - let r, _, _ = addWithCarry src1 (not src2) (getCarryFlag ctxt) + let r, _, _ = addWithCarry src1 (AST.not src2) (getCarryFlag ctxt) r | Op.RSCS -> let _, src1, src2 = parseOprOfADC insInfo ctxt - let r, _, _ = addWithCarry (not src1) src2 (getCarryFlag ctxt) + let r, _, _ = addWithCarry (AST.not src1) src2 (getCarryFlag ctxt) r | Op.ORRS -> let _, src1, src2 = parseOprOfADC insInfo ctxt in src1 .| src2 | Op.MOVS -> let _, src = transTwoOprs insInfo ctxt in src @@ -1130,36 +1131,36 @@ let parseResultOfSUBAndRela insInfo ctxt = shiftForRegAmount src1 32 SRTypeROR src2 (getCarryFlag ctxt) | Op.RRXS -> let _, src = transTwoOprs insInfo ctxt - shiftForRegAmount src 32 SRTypeRRX (num1 32) (getCarryFlag ctxt) + shiftForRegAmount src 32 SRTypeRRX (AST.num1 32) (getCarryFlag ctxt) | Op.BICS -> let _, src1, src2 = parseOprOfADC insInfo ctxt - src1 .& (not src2) - | Op.MVNS -> let _, src = parseOprOfMVNS insInfo ctxt in not src + src1 .& (AST.not src2) + | Op.MVNS -> let _, src = parseOprOfMVNS insInfo ctxt in AST.not src | _ -> raise InvalidOperandException /// B9.3.20 SUBS R.PC, R.LR and related instruction (ARM), on page B9-2010 let subsAndRelatedInstr insInfo ctxt = - let builder = new StmtBuilder (64) - let result = tmpVar 32 + let builder = IRBuilder (64) + let result = builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder cpsrWriteByInstr ctxt (getRegVar ctxt R.SPSR) 0b1111 true builder builder - if v then BitVector.one 1 |> Num - else BitVector.zero 1 |> Num + if v then BitVector.one 1 |> AST.num + else BitVector.zero 1 |> AST.num | None -> getCarryFlag ctxt -let translateLogicOp insInfo ctxt (builder: StmtBuilder) = +let translateLogicOp insInfo ctxt (builder: IRBuilder) = match insInfo.Operands with | TwoOperands (OprReg _, OprReg _) -> - let t = tmpVar 32 + let t = builder.NewTempVar 32 let e1, e2 = transTwoOprs insInfo ctxt builder SRTypeLSL 0u (getCarryFlag ctxt) @@ -1169,7 +1170,7 @@ let translateLogicOp insInfo ctxt (builder: StmtBuilder) = let carryOut = computeCarryOutFromImmCflag insInfo ctxt e1, e2, e3, carryOut | FourOperands (opr1, opr2, opr3 , OprShift (typ, Imm imm)) -> - let t = tmpVar 32 + let t = builder.NewTempVar 32 let carryIn = getCarryFlag ctxt let dst = transOprToExpr ctxt opr1 let src1 = transOprToExpr ctxt opr2 @@ -1178,41 +1179,41 @@ let translateLogicOp insInfo ctxt (builder: StmtBuilder) = let shifted, carryOut = shiftC t 32 typ imm carryIn dst, src1, shifted, carryOut | FourOperands (opr1, opr2, opr3 , OprRegShift (typ, reg)) -> - let t = tmpVar 32 + let t = builder.NewTempVar 32 let carryIn = getCarryFlag ctxt let dst = transOprToExpr ctxt opr1 let src1 = transOprToExpr ctxt opr2 let rm = transOprToExpr ctxt opr3 builder (getRegVar ctxt reg) |> zExt 32 + let amount = AST.xtlo 8 (getRegVar ctxt reg) |> AST.zext 32 let shifted, carryOut = shiftCForRegAmount t 32 typ amount carryIn dst, src1, shifted, carryOut | _ -> raise InvalidOperandException let logicalAnd isSetFlags insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let dst, src1, src2, carryOut = translateLogicOp insInfo ctxt builder - let result = tmpVar 32 + let result = builder.NewTempVar 32 builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) else () putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let mov isSetFlags insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let dst, res = transTwoOprs insInfo ctxt - let result = tmpVar 32 + let result = builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder @@ -1222,27 +1223,27 @@ let mov isSetFlags insInfo ctxt = builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) else () putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let eor isSetFlags insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let dst, src1, src2, carryOut = translateLogicOp insInfo ctxt builder - let result = tmpVar 32 + let result = builder.NewTempVar 32 builder src2) if dst = getPC ctxt then aluWritePC ctxt insInfo isUnconditional result builder else builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) else () putEndLabel ctxt lblIgnore isUnconditional None builder @@ -1258,7 +1259,7 @@ let transFourOprsOfRSB insInfo ctxt = let e1 = transOprToExpr ctxt opr1 let e2 = transOprToExpr ctxt opr2 let e3 = transOprToExpr ctxt opr3 - let amount = extractLow 8 (getRegVar ctxt reg) |> zExt 32 + let amount = AST.xtlo 8 (getRegVar ctxt reg) |> AST.zext 32 e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt) | _ -> raise InvalidOperandException @@ -1269,24 +1270,24 @@ let parseOprOfRSB insInfo ctxt = | _ -> raise InvalidOperandException let rsb isSetFlags insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let dst, src1, src2 = parseOprOfRSB insInfo ctxt - let result = tmpVar 32 - let t1, t2 = tmpVar 32, tmpVar 32 + let result = builder.NewTempVar 32 + let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder builder ) + let res, carryOut, overflow = addWithCarry (AST.not t1) t2 (AST.num1 32) builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) builder setPSR ctxt R.CPSR PSR_V) else () @@ -1310,7 +1311,7 @@ let transFourOprsOfSBC insInfo ctxt = let e1 = transOprToExpr ctxt opr1 let e2 = transOprToExpr ctxt opr2 let e3 = transOprToExpr ctxt opr3 - let amount = extractLow 8 (getRegVar ctxt reg) |> zExt 32 + let amount = AST.xtlo 8 (getRegVar ctxt reg) |> AST.zext 32 e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt) | _ -> raise InvalidOperandException @@ -1322,24 +1323,24 @@ let parseOprOfSBC insInfo ctxt = | _ -> raise InvalidOperandException let sbc isSetFlags insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let dst, src1, src2 = parseOprOfSBC insInfo ctxt - let t1, t2 = tmpVar 32, tmpVar 32 - let result = tmpVar 32 + let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 + let result = builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) builder setPSR ctxt R.CPSR PSR_V) else () @@ -1356,7 +1357,7 @@ let transFourOprsOfRSC insInfo ctxt = let e1 = transOprToExpr ctxt opr1 let e2 = transOprToExpr ctxt opr2 let e3 = transOprToExpr ctxt opr3 - let amount = extractLow 8 (getRegVar ctxt reg) |> zExt 32 + let amount = AST.xtlo 8 (getRegVar ctxt reg) |> AST.zext 32 e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt) | _ -> raise InvalidOperandException @@ -1367,24 +1368,24 @@ let parseOprOfRSC insInfo ctxt = | _ -> raise InvalidOperandException let rsc isSetFlags insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let dst, src1, src2 = parseOprOfRSC insInfo ctxt - let t1, t2 = tmpVar 32, tmpVar 32 - let result = tmpVar 32 + let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 + let result = builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) builder setPSR ctxt R.CPSR PSR_V) else () @@ -1392,60 +1393,60 @@ let rsc isSetFlags insInfo ctxt = endMark insInfo builder let orr isSetFlags insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let dst, src1, src2, carryOut = translateLogicOp insInfo ctxt builder - let result = tmpVar 32 + let result = builder.NewTempVar 32 builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) else () putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let orn isSetFlags insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let dst, src1, src2, carryOut = translateLogicOp insInfo ctxt builder - let result = tmpVar 32 - builder + builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) else () putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let bic isSetFlags insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let dst, src1, src2, carryOut = translateLogicOp insInfo ctxt builder - let result = tmpVar 32 - builder + builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) else () putEndLabel ctxt lblIgnore isUnconditional None builder @@ -1474,7 +1475,7 @@ let transThreeOprsOfMVN insInfo ctxt = let carryIn = getCarryFlag ctxt let dst = transOprToExpr ctxt opr1 let src = transOprToExpr ctxt opr2 - let amount = extractLow 8 (getRegVar ctxt rs) |> zExt 32 + let amount = AST.xtlo 8 (getRegVar ctxt rs) |> AST.zext 32 let shifted, carryOut = shiftCForRegAmount src 32 typ amount carryIn dst, shifted, carryOut | _ -> raise InvalidOperandException @@ -1486,20 +1487,20 @@ let parseOprOfMVN insInfo ctxt = | _ -> raise InvalidOperandException let mvn isSetFlags insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let dst, src, carryOut = parseOprOfMVN insInfo ctxt - let result = tmpVar 32 + let result = builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) else () putEndLabel ctxt lblIgnore isUnconditional None builder @@ -1526,7 +1527,7 @@ let transTwoOprsOfShiftInstr insInfo shiftTyp ctxt tmp = | TwoOperands (OprReg _, OprReg _) -> let carryIn = getCarryFlag ctxt let e1, e2 = transTwoOprs insInfo ctxt - let shiftN = extractLow 8 e2 |> zExt 32 + let shiftN = AST.xtlo 8 e2 |> AST.zext 32 let result, carryOut = shiftCForRegAmount tmp 32 shiftTyp shiftN carryIn e1, e1, result, carryOut | _ -> raise InvalidOperandException @@ -1543,7 +1544,7 @@ let transThreeOprsOfShiftInstr insInfo shiftTyp ctxt tmp = | ThreeOperands (_, _, OprReg _) -> let carryIn = getCarryFlag ctxt let e1, e2, e3 = transThreeOprs insInfo ctxt - let amount = extractLow 8 e3 |> zExt 32 + let amount = AST.xtlo 8 e3 |> AST.zext 32 let shifted, carryOut = shiftCForRegAmount tmp 32 shiftTyp amount carryIn e1, e2, shifted, carryOut @@ -1556,9 +1557,9 @@ let parseOprOfShiftInstr insInfo shiftTyp ctxt tmp = | _ -> raise InvalidOperandException let shiftInstr isSetFlags insInfo typ ctxt = - let builder = new StmtBuilder (32) - let srcTmp = tmpVar 32 - let result = tmpVar 32 + let builder = IRBuilder (32) + let srcTmp = builder.NewTempVar 32 + let result = builder.NewTempVar 32 let dst, src, res, carryOut = parseOprOfShiftInstr insInfo typ ctxt srcTmp let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder @@ -1570,8 +1571,8 @@ let shiftInstr isSetFlags insInfo typ ctxt = builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) else () putEndLabel ctxt lblIgnore isUnconditional None builder @@ -1683,28 +1684,28 @@ let rrxs isSetFlags insInfo ctxt = | _ -> shiftInstr isSetFlags insInfo SRTypeRRX ctxt let clz insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let dst, src = transTwoOprs insInfo ctxt - let lblBoundCheck = lblSymbol "LBoundCheck" - let lblZeroCheck = lblSymbol "LZeroCheck" - let lblCount = lblSymbol "LCount" - let lblEnd = lblSymbol "LEnd" - let numSize = (num <| BitVector.ofInt32 32 32) - let t1 = tmpVar 32 - let cond1 = t1 == (num0 32) - let cond2 = src .& ((num1 32) << (t1 .- num1 32)) != (num0 32) + let lblBoundCheck = builder.NewSymbol "LBoundCheck" + let lblZeroCheck = builder.NewSymbol "LZeroCheck" + let lblCount = builder.NewSymbol "LCount" + let lblEnd = builder.NewSymbol "LEnd" + let numSize = (AST.num <| BitVector.ofInt32 32 32) + let t1 = builder.NewTempVar 32 + let cond1 = t1 == (AST.num0 32) + let cond2 = src .& ((AST.num1 32) << (t1 .- AST.num1 32)) != (AST.num0 32) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder builder )) - builder )) + builder (getRegVar ctxt rs) |> zExt 32 + let amount = AST.xtlo 8 (getRegVar ctxt rs) |> AST.zext 32 let shifted = shiftForRegAmount src 32 typ amount carryIn dst, shifted | _ -> raise InvalidOperandException @@ -1742,39 +1743,39 @@ let parseOprOfCMN insInfo ctxt = | _ -> raise InvalidOperandException let cmn insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let dst, src = parseOprOfCMN insInfo ctxt - let result = tmpVar 32 - let t1, t2 = tmpVar 32, tmpVar 32 + let result = builder.NewTempVar 32 + let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 let cpsr = getRegVar ctxt R.CPSR let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder builder ) + let res, carryOut, overflow = addWithCarry t1 t2 (AST.num0 32) builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) builder setPSR ctxt R.CPSR PSR_V) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let mla isSetFlags insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rd, rn, rm, ra = transFourOprs insInfo ctxt - let r = tmpVar 32 + let r = builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder (zExt 64 rn .* zExt 64 rm .+ - zExt 64 ra)) + builder (AST.zext 64 rn .* AST.zext 64 rm .+ + AST.zext 64 ra)) builder r |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder r |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) else () putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder @@ -1798,7 +1799,7 @@ let transThreeOprsOfCMP insInfo ctxt = let carryIn = getCarryFlag ctxt let dst = transOprToExpr ctxt opr1 let src = transOprToExpr ctxt opr2 - let amount = extractLow 8 (getRegVar ctxt rs) |> zExt 32 + let amount = AST.xtlo 8 (getRegVar ctxt rs) |> AST.zext 32 dst, shiftForRegAmount src 32 typ amount carryIn | _ -> raise InvalidOperandException @@ -1809,57 +1810,57 @@ let parseOprOfCMP insInfo ctxt = | _ -> raise InvalidOperandException let cmp insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rn, rm = parseOprOfCMP insInfo ctxt - let result = tmpVar 32 - let t1, t2 = tmpVar 32, tmpVar 32 + let result = builder.NewTempVar 32 + let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 let cpsr = getRegVar ctxt R.CPSR let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder builder ) + let res, carryOut, overflow = addWithCarry t1 (AST.not t2) (AST.num1 32) builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) builder setPSR ctxt R.CPSR PSR_V) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let umlal isSetFlags insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rdLo, rdHi, rn, rm = transFourOprs insInfo ctxt - let result = tmpVar 64 + let result = builder.NewTempVar 64 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder rn .* zExt 64 rm .+ concat rdLo rdHi) - builder result) - builder result) + builder rn .* AST.zext 64 rm .+ AST.concat rdLo rdHi) + builder result) + builder result) if isSetFlags then let cpsr = getRegVar ctxt R.CPSR - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) else () putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let umull isSetFlags insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rdLo, rdHi, rn, rm = transFourOprs insInfo ctxt - let result = tmpVar 64 + let result = builder.NewTempVar 64 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder rn .* zExt 64 rm) - builder result) - builder result) + builder rn .* AST.zext 64 rm) + builder result) + builder result) if isSetFlags then let cpsr = getRegVar ctxt R.CPSR - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) else () putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder @@ -1879,39 +1880,39 @@ let transOprsOfTEQ insInfo ctxt = let carryIn = getCarryFlag ctxt let rn = transOprToExpr ctxt opr1 let rm = transOprToExpr ctxt opr2 - let amount = extractLow 8 (getRegVar ctxt rs) |> zExt 32 + let amount = AST.xtlo 8 (getRegVar ctxt rs) |> AST.zext 32 let shifted, carryOut = shiftCForRegAmount rm 32 typ amount carryIn rn, shifted, carryOut | _ -> raise InvalidOperandException let teq insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let src1, src2, carryOut = transOprsOfTEQ insInfo ctxt - let result = tmpVar 32 + let result = builder.NewTempVar 32 let cpsr = getRegVar ctxt R.CPSR let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder builder src2) - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let mul isSetFlags insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rd, rn, rm = transThreeOprs insInfo ctxt - let result = tmpVar 32 + let result = builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder (zExt 64 rn .* zExt 64 rm)) + builder (AST.zext 64 rn .* AST.zext 64 rm)) builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) else () putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder @@ -1936,77 +1937,77 @@ let transOprsOfTST insInfo ctxt = let carryIn = getCarryFlag ctxt let rn = transOprToExpr ctxt opr1 let rm = transOprToExpr ctxt opr2 - let amount = extractLow 8 (getRegVar ctxt rs) |> zExt 32 + let amount = AST.xtlo 8 (getRegVar ctxt rs) |> AST.zext 32 let shifted, carryOut = shiftCForRegAmount rm 32 typ amount carryIn rn, shifted, carryOut | _ -> raise InvalidOperandException let tst insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let src1, src2, carryOut = transOprsOfTST insInfo ctxt - let result = tmpVar 32 + let result = builder.NewTempVar 32 let cpsr = getRegVar ctxt R.CPSR let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) builder setPSR ctxt R.CPSR PSR_C) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let smulhalf insInfo ctxt s1top s2top = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let rd, rn, rm = transThreeOprs insInfo ctxt - let t1 = tmpVar 32 - let t2 = tmpVar 32 + let t1 = builder.NewTempVar 32 + let t2 = builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - if s1top then builder rn |> zExt 32) - else builder rn |> sExt 32) - if s2top then builder rm |> zExt 32) - else builder rm |> sExt 32) + if s1top then builder rn |> AST.zext 32) + else builder rn |> AST.sext 32) + if s2top then builder rm |> AST.zext 32) + else builder rm |> AST.sext 32) builder - let result = tmpVar 64 + let tmpresult = builder.NewTempVar 64 + let result = builder.NewTempVar 64 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder rn .* sExt 64 rm) - if doAcc then builder rn .* AST.sext 64 rm) + if doAcc then builder result) - builder result) + builder result) + builder result) if isSetFlags then let cpsr = getRegVar ctxt R.CPSR - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + builder result |> setPSR ctxt R.CPSR PSR_N) + builder |> setPSR ctxt R.CPSR PSR_Z) else () putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let smulacchalf insInfo ctxt s1top s2top = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let rd, rn, rm, ra = transFourOprs insInfo ctxt - let t1 = tmpVar 32 - let t2 = tmpVar 32 + let t1 = builder.NewTempVar 32 + let t2 = builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - if s1top then builder rn |> zExt 32) - else builder rn |> sExt 32) - if s2top then builder rm |> zExt 32) - else builder rm |> sExt 32) - builder ra) + if s1top then builder rn |> AST.zext 32) + else builder rn |> AST.sext 32) + if s2top then builder rm |> AST.zext 32) + else builder rm |> AST.sext 32) + builder ra) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder @@ -2014,21 +2015,21 @@ let parseOprOfB insInfo = let addr = bvOfBaseAddr (insInfo.Address + pcOffset insInfo) match insInfo.Operands with | OneOperand (OprMemory (LiteralMode imm)) -> - addr .+ (num <| BitVector.ofInt64 imm 32) + addr .+ (AST.num <| BitVector.ofInt64 imm 32) | _ -> raise InvalidOperandException let b insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let e = parseOprOfB insInfo let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder - let clearHigh16In32 expr = expr .& not maskHigh16In32 + let maskHigh16In32 = AST.num <| BitVector.ofBInt 4294901760I 32 + let clearHigh16In32 expr = expr .& AST.not maskHigh16In32 dst := clearHigh16In32 dst .| - (src << (num <| BitVector.ofInt32 16 32)) + (src << (AST.num <| BitVector.ofInt32 16 32)) let movt insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let dst, res = transTwoOprs insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder @@ -2053,18 +2054,18 @@ let movt insInfo ctxt = putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder -let popLoop ctxt numOfReg addr (builder: StmtBuilder) = +let popLoop ctxt numOfReg addr (builder: IRBuilder) = let loop addr count = if (numOfReg >>> count) &&& 1u = 1u then let reg = count |> byte |> OperandHelper.getRegister - builder addr) - (addr .+ (num <| BitVector.ofInt32 4 32)) + builder addr) + (addr .+ (AST.num <| BitVector.ofInt32 4 32)) else addr List.fold loop addr [ 0 .. 14 ] let pop insInfo ctxt = - let builder = new StmtBuilder (32) - let t0 = tmpVar 32 + let builder = IRBuilder (32) + let t0 = builder.NewTempVar 32 let sp = getRegVar ctxt R.SP let numOfReg = parseOprOfPUSHPOP insInfo let stackWidth = 4 * bitCount numOfReg 16 @@ -2075,10 +2076,10 @@ let pop insInfo ctxt = builder >> 13 &&& 1u) = 0u then - builder )) - else builder , "UNKNOWN"))) + builder )) + else builder "UNKNOWN")) if (numOfReg >>> 15 &&& 1u) = 1u then - loadLE 32 addr |> loadWritePC ctxt isUnconditional builder + AST.loadLE 32 addr |> loadWritePC ctxt isUnconditional builder else () putEndLabel ctxt lblIgnore isUnconditional (Some insInfo) builder endMark insInfo builder @@ -2091,15 +2092,15 @@ let parseOprOfLDM insInfo ctxt = let getLDMStartAddr rn stackWidth = function | Op.LDM | Op.LDMIA -> rn - | Op.LDMDA -> rn .- (num <| BitVector.ofInt32 (stackWidth + 4) 32) - | Op.LDMDB -> rn .- (num <| BitVector.ofInt32 stackWidth 32) - | Op.LDMIB -> rn .+ (num <| BitVector.ofInt32 4 32) + | Op.LDMDA -> rn .- (AST.num <| BitVector.ofInt32 (stackWidth + 4) 32) + | Op.LDMDB -> rn .- (AST.num <| BitVector.ofInt32 stackWidth 32) + | Op.LDMIB -> rn .+ (AST.num <| BitVector.ofInt32 4 32) | _ -> raise InvalidOpcodeException let ldm opcode insInfo ctxt wbackop = - let builder = new StmtBuilder (32) - let t0 = tmpVar 32 - let t1 = tmpVar 32 + let builder = IRBuilder (32) + let t0 = builder.NewTempVar 32 + let t1 = builder.NewTempVar 32 let rn, numOfRn, numOfReg = parseOprOfLDM insInfo ctxt let wback = Option.get insInfo.WriteBack let stackWidth = 4 * bitCount numOfReg 16 @@ -2111,13 +2112,13 @@ let ldm opcode insInfo ctxt wbackop = builder >> 15 &&& 1u) = 1u then - loadLE 32 addr |> loadWritePC ctxt isUnconditional builder + AST.loadLE 32 addr |> loadWritePC ctxt isUnconditional builder else () if wback && (numOfReg &&& numOfRn) = 0u then - builder )) + builder )) else () if wback && (numOfReg &&& numOfRn) = numOfRn then - builder , "UNKNOWN"))) + builder "UNKNOWN")) else () putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder @@ -2126,8 +2127,8 @@ let getOffAddrWithExpr s r e = if s = Some Plus then r .+ e else r .- e let getOffAddrWithImm s r imm = match s, imm with - | Some Plus, Some i -> r .+ (num <| BitVector.ofInt64 i 32) - | Some Minus, Some i -> r .- (num <| BitVector.ofInt64 i 32) + | Some Plus, Some i -> r .+ (AST.num <| BitVector.ofInt64 i 32) + | Some Minus, Some i -> r .- (AST.num <| BitVector.ofInt64 i 32) | _, _ -> r let parseMemOfLDR insInfo ctxt = function @@ -2143,10 +2144,10 @@ let parseMemOfLDR insInfo ctxt = function rn, Some (rn, getOffAddrWithImm s rn imm) | OprMemory (LiteralMode imm) -> let addr = bvOfBaseAddr insInfo.Address - let pc = align addr (num <| BitVector.ofInt32 4 32) + let pc = align addr (AST.num <| BitVector.ofInt32 4 32) let rel = if insInfo.Mode = ArchOperationMode.ARMMode then 8u else 4u - pc .+ (num <| BitVector.ofUInt32 rel 32) - .+ (num <| BitVector.ofInt64 imm 32), None + pc .+ (AST.num <| BitVector.ofUInt32 rel 32) + .+ (AST.num <| BitVector.ofInt64 imm 32), None | OprMemory (OffsetMode (RegOffset (n, _, m, None))) -> let m = getRegVar ctxt m |> convertPCOpr insInfo ctxt let n = getRegVar ctxt n |> convertPCOpr insInfo ctxt @@ -2188,22 +2189,22 @@ let parseOprOfLDR insInfo ctxt = /// Load register let ldr insInfo ctxt size ext = - let builder = new StmtBuilder (16) - let data = tmpVar 32 + let builder = IRBuilder (16) + let data = builder.NewTempVar 32 let rt, addr, writeback = parseOprOfLDR insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder match writeback with | Some (basereg, newoffset) -> - let taddr = tmpVar 32 - let twriteback = tmpVar 32 + let taddr = builder.NewTempVar 32 + let twriteback = builder.NewTempVar 32 builder ext 32) + builder ext 32) builder - builder ext 32) + builder ext 32) if rt = getPC ctxt then loadWritePC ctxt isUnconditional builder data else builder raise InvalidOperandException let ldrd insInfo ctxt = - let builder = new StmtBuilder (8) - let taddr = tmpVar 32 + let builder = IRBuilder (8) + let taddr = builder.NewTempVar 32 let rt, rt2, addr, writeback = parseOprOfLDRD insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - let n4 = num (BitVector.ofInt32 4 32) + let n4 = AST.num (BitVector.ofInt32 4 32) match writeback with | Some (basereg, newoffset) -> - let twriteback = tmpVar 32 + let twriteback = builder.NewTempVar 32 builder taddr) - builder (taddr .+ n4)) + builder taddr) + builder (taddr .+ n4)) builder builder taddr) - builder (taddr .+ n4)) + builder taddr) + builder (taddr .+ n4)) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let sel8Bits r offset = - extract r 8 offset |> zExt 32 + AST.extract r 8 offset |> AST.zext 32 let combine8bitResults t1 t2 t3 t4 = - let mask = num <| BitVector.ofInt32 0xff 32 - let n8 = num <| BitVector.ofInt32 8 32 - let n16 = num <| BitVector.ofInt32 16 32 - let n24 = num <| BitVector.ofInt32 24 32 + let mask = AST.num <| BitVector.ofInt32 0xff 32 + let n8 = AST.num <| BitVector.ofInt32 8 32 + let n16 = AST.num <| BitVector.ofInt32 16 32 + let n24 = AST.num <| BitVector.ofInt32 24 32 ((t4 .& mask) << n24) .| ((t3 .& mask) << n16) .| ((t2 .& mask) << n8) .| (t1 .& mask) let combineGEs ge0 ge1 ge2 ge3 = - let n1 = num1 32 - let n2 = num <| BitVector.ofInt32 2 32 - let n3 = num <| BitVector.ofInt32 3 32 + let n1 = AST.num1 32 + let n2 = AST.num <| BitVector.ofInt32 2 32 + let n3 = AST.num <| BitVector.ofInt32 3 32 ge0 .| (ge1 << n1) .| (ge2 << n2) .| (ge3 << n3) let uadd8 insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let rd, rn, rm = transThreeOprs insInfo ctxt - let sum1 = tmpVar 32 - let sum2 = tmpVar 32 - let sum3 = tmpVar 32 - let sum4 = tmpVar 32 - let ge0 = tmpVar 32 - let ge1 = tmpVar 32 - let ge2 = tmpVar 32 - let ge3 = tmpVar 32 + let sum1 = builder.NewTempVar 32 + let sum2 = builder.NewTempVar 32 + let sum3 = builder.NewTempVar 32 + let sum4 = builder.NewTempVar 32 + let ge0 = builder.NewTempVar 32 + let ge1 = builder.NewTempVar 32 + let ge2 = builder.NewTempVar 32 + let ge3 = builder.NewTempVar 32 let cpsr = getRegVar ctxt R.CPSR - let n100 = num <| BitVector.ofInt32 0x100 32 + let n100 = AST.num <| BitVector.ofInt32 0x100 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder @@ -2291,41 +2292,41 @@ let uadd8 insInfo ctxt = builder ) (num0 32)) - builder ) (num0 32)) - builder ) (num0 32)) - builder ) (num0 32)) + builder ) (AST.num0 32)) + builder ) (AST.num0 32)) + builder ) (AST.num0 32)) + builder ) (AST.num0 32)) builder setPSR ctxt R.CPSR PSR_GE) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let sel insInfo ctxt = - let builder = new StmtBuilder (16) - let t1 = tmpVar 32 - let t2 = tmpVar 32 - let t3 = tmpVar 32 - let t4 = tmpVar 32 + let builder = IRBuilder (16) + let t1 = builder.NewTempVar 32 + let t2 = builder.NewTempVar 32 + let t3 = builder.NewTempVar 32 + let t4 = builder.NewTempVar 32 let rd, rn, rm = transThreeOprs insInfo ctxt - let n1 = num1 32 - let n2 = num <| BitVector.ofInt32 2 32 - let n4 = num <| BitVector.ofInt32 4 32 - let n8 = num <| BitVector.ofInt32 8 32 - let ge = getPSR ctxt R.CPSR PSR_GE >> (num <| BitVector.ofInt32 16 32) + let n1 = AST.num1 32 + let n2 = AST.num <| BitVector.ofInt32 2 32 + let n4 = AST.num <| BitVector.ofInt32 4 32 + let n8 = AST.num <| BitVector.ofInt32 8 32 + let ge = getPSR ctxt R.CPSR PSR_GE >> (AST.num <| BitVector.ofInt32 16 32) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder - let t2 = tmpVar 32 + let builder = IRBuilder (16) + let t1 = builder.NewTempVar 32 + let t2 = builder.NewTempVar 32 let rd, rm = transTwoOprs insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder @@ -2333,17 +2334,17 @@ let rbit insInfo ctxt = builder rd) for i = 0 to 31 do - builder i) |> zExt 32) - builder ))) + builder i) |> AST.zext 32) + builder ))) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let rev insInfo ctxt = - let builder = new StmtBuilder (16) - let t1 = tmpVar 32 - let t2 = tmpVar 32 - let t3 = tmpVar 32 - let t4 = tmpVar 32 + let builder = IRBuilder (16) + let t1 = builder.NewTempVar 32 + let t2 = builder.NewTempVar 32 + let t3 = builder.NewTempVar 32 + let t4 = builder.NewTempVar 32 let rd, rm = transTwoOprs insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder @@ -2358,14 +2359,14 @@ let rev insInfo ctxt = /// Store register. let str insInfo ctxt size = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rt, addr, writeback = parseOprOfLDR insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - if rt = getPC ctxt then builder addr := pcStoreValue ctxt) - elif size = 32 then builder addr := rt) - else builder addr := pcStoreValue ctxt) + elif size = 32 then builder addr := rt) + else builder builder () @@ -2373,28 +2374,28 @@ let str insInfo ctxt size = endMark insInfo builder let strex insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rd, rt, addr, writeback = parseOprOfLDRD insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - if rt = getPC ctxt then builder addr := pcStoreValue ctxt) - else builder addr := rt) + if rt = getPC ctxt then builder addr := pcStoreValue ctxt) + else builder addr := rt) match writeback with | Some (basereg, newoffset) -> builder () - builder ) (* XXX: always succeeds for now *) + builder ) (* XXX: always succeeds for now *) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let strd insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let rt, rt2, addr, writeback = parseOprOfLDRD insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder addr := rt) - builder (addr .+ (num <| BitVector.ofInt32 4 32)) := rt2) + builder addr := rt) + builder (addr .+ (AST.num <| BitVector.ofInt32 4 32)) := rt2) match writeback with | Some (basereg, newoffset) -> builder () @@ -2409,29 +2410,29 @@ let parseOprOfSTM insInfo ctxt = let getSTMStartAddr rn msize = function | Op.STM | Op.STMIA | Op.STMEA -> rn - | Op.STMDA -> rn .- msize .+ (num <| BitVector.ofInt32 4 32) + | Op.STMDA -> rn .- msize .+ (AST.num <| BitVector.ofInt32 4 32) | Op.STMDB -> rn .- msize - | Op.STMIB -> rn .+ (num <| BitVector.ofInt32 4 32) + | Op.STMIB -> rn .+ (AST.num <| BitVector.ofInt32 4 32) | _ -> raise InvalidOpcodeException -let stmLoop ctxt regs wback rn addr (builder: StmtBuilder) = +let stmLoop ctxt regs wback rn addr (builder: IRBuilder) = let loop addr count = if (regs >>> count) &&& 1u = 1u then let ri = count |> byte |> OperandHelper.getRegister |> getRegVar ctxt if ri = rn && wback && count <> lowestSetBit regs 32 then - builder addr := (Expr.Undefined (32, "UNKNOWN"))) + builder addr := (AST.undef 32 "UNKNOWN")) else - builder addr := ri) - addr .+ (num <| BitVector.ofInt32 4 32) + builder addr := ri) + addr .+ (AST.num <| BitVector.ofInt32 4 32) else addr List.fold loop addr [ 0 .. 14 ] let stm opcode insInfo ctxt wbop = - let builder = new StmtBuilder (32) - let taddr = tmpVar 32 + let builder = IRBuilder (32) + let taddr = builder.NewTempVar 32 let rn, regs = parseOprOfSTM insInfo ctxt let wback = Option.get insInfo.WriteBack - let msize = BitVector.ofInt32 (4 * bitCount regs 16) 32 |> num + let msize = BitVector.ofInt32 (4 * bitCount regs 16) 32 |> AST.num let addr = getSTMStartAddr rn msize opcode let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder @@ -2439,7 +2440,7 @@ let stm opcode insInfo ctxt wbop = builder >> 15 &&& 1u) = 1u then - builder addr := pcStoreValue ctxt) + builder addr := pcStoreValue ctxt) else () if wback then builder int64 match insInfo.Operands with | TwoOperands (OprReg rn, (OprMemory (LiteralMode imm))) -> - getRegVar ctxt rn, pc .+ (num <| BitVector.ofInt64 (imm + offset) 32) + getRegVar ctxt rn, pc .+ (AST.num <| BitVector.ofInt64 (imm + offset) 32) | _ -> raise InvalidOperandException let cbz nonZero insInfo ctxt = - let builder = new StmtBuilder (16) - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let n = if nonZero then num1 1 else num0 1 + let builder = IRBuilder (16) + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let n = if nonZero then AST.num1 1 else AST.num0 1 let rn, pc = parseOprOfCBZ insInfo ctxt - let cond = n <+> (rn == num0 32) + let cond = n <+> (rn == AST.num0 32) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder |> num - builder |> AST.num + builder convertPCOpr insInfo ctxt let rm = getRegVar ctxt rm |> convertPCOpr insInfo ctxt let addr = rn .+ rm - loadLE 8 addr |> zExt 32 + AST.loadLE 8 addr |> AST.zext 32 | OneOperand (OprMemory (OffsetMode (RegOffset (rn, None, rm, Some (_, Imm i))))) -> let rn = getRegVar ctxt rn |> convertPCOpr insInfo ctxt let rm = getRegVar ctxt rm |> convertPCOpr insInfo ctxt let addr = rn .+ (shiftLSL rm 32 i) - loadLE 16 addr |> zExt 32 + AST.loadLE 16 addr |> AST.zext 32 | _ -> raise InvalidOperandException let tableBranch insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let pc = bvOfBaseAddr insInfo.Address let halfwords = parseOprOfTableBranch insInfo ctxt - let numTwo = num <| BitVector.ofInt32 2 32 + let numTwo = AST.num <| BitVector.ofInt32 2 32 let result = pc .+ (numTwo .* halfwords) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder raise InvalidOperandException let bfc insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let rd, lsb, width = parseOprOfBFC insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder @@ -2526,38 +2527,38 @@ let parseOprOfRdRnLsbWidth insInfo ctxt = | _ -> raise InvalidOperandException let bfi insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let rd, rn, lsb, width = parseOprOfRdRnLsbWidth insInfo ctxt - let t0 = tmpVar 32 - let t1 = tmpVar 32 + let t0 = builder.NewTempVar 32 + let t1 = builder.NewTempVar 32 let n = rn .& - (BitVector.ofUBInt (BigInteger.getMask width) 32 |> num) + (BitVector.ofBInt (BigInteger.getMask width) 32 |> AST.num) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder )) + builder )) builder lsb width 0) builder 31 || width < 0 then raise InvalidOperandException else () - let v = BitVector.ofUBInt (BigInteger.getMask width) 32 |> num - builder > (num <| BitVector.ofInt32 lsb 32)) .& v) + let v = BitVector.ofBInt (BigInteger.getMask width) 32 |> AST.num + builder > (AST.num <| BitVector.ofInt32 lsb 32)) .& v) if signExtend && width > 1 then - let msb = tmpVar 32 - let mask = tmpVar 32 - let msboffset = num <| BitVector.ofInt32 (lsb + width - 1) 32 - let shift = num <| BitVector.ofInt32 width 32 - builder > msboffset) .& num1 32) - builder )) << shift) + let msb = builder.NewTempVar 32 + let mask = builder.NewTempVar 32 + let msboffset = AST.num <| BitVector.ofInt32 (lsb + width - 1) 32 + let shift = AST.num <| BitVector.ofInt32 width 32 + builder > msboffset) .& AST.num1 32) + builder )) << shift) builder raise InvalidOperandException -let createTemporaries cnt regtype = - Array.init cnt (fun _ -> tmpVar regtype) +let createTemporaries (builder: IRBuilder) cnt regtype = + Array.init cnt (fun _ -> builder.NewTempVar regtype) let extractUQOps r width = let typ = RegType.fromBitWidth width - [| for w in 0 .. width .. 31 do yield extract r typ w |> zExt 32 done |] + [| for w in 0 .. width .. 31 do yield AST.extract r typ w |> AST.zext 32 done |] let saturate e width = - let max32 = num <| BitVector.ofInt32 (pown 2 width - 1) 32 - let zero = num0 32 + let max32 = AST.num <| BitVector.ofInt32 (pown 2 width - 1) 32 + let zero = AST.num0 32 let resultType = RegType.fromBitWidth width - ite (sgt e max32) (extractLow resultType max32) - (ite (slt e zero) (num0 resultType) (extractLow resultType e)) + AST.ite (AST.sgt e max32) (AST.xtlo resultType max32) + (AST.ite (AST.slt e zero) (AST.num0 resultType) (AST.xtlo resultType e)) let getUQAssignment tmps width = tmps |> Array.mapi (fun idx t -> - (zExt 32 t) << (num <| BitVector.ofInt32 (idx * width) 32)) + (AST.zext 32 t) << (AST.num <| BitVector.ofInt32 (idx * width) 32)) |> Array.reduce (.|) let uqopr insInfo ctxt width opr = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rd, rn, rm = parseOprOfUqOpr ctxt insInfo.Operands - let tmps = createTemporaries (32 / width) 32 - let sats = createTemporaries (32 / width) (RegType.fromBitWidth width) + let tmps = createTemporaries builder (32 / width) 32 + let sats = createTemporaries builder (32 / width) (RegType.fromBitWidth width) let rns = extractUQOps rn width let rms = extractUQOps rm width let diffs = Array.map2 opr rns rms @@ -2610,26 +2611,26 @@ let parseOprOfADR insInfo ctxt = match insInfo.Operands with | TwoOperands (OprReg rd, OprMemory (LiteralMode imm)) -> let addr = bvOfBaseAddr insInfo.Address - let addr = addr .+ (num <| BitVector.ofInt32 4 32) - let pc = align addr (num <| BitVector.ofInt32 4 32) - getRegVar ctxt rd, pc .+ (num <| BitVector.ofInt64 imm 32) + let addr = addr .+ (AST.num <| BitVector.ofInt32 4 32) + let pc = align addr (AST.num <| BitVector.ofInt32 4 32) + getRegVar ctxt rd, pc .+ (AST.num <| BitVector.ofInt64 imm 32) | _ -> raise InvalidOperandException let it insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let cpsr = getRegVar ctxt R.CPSR - let itState = num <| BitVector.ofInt32 (int insInfo.ITState) 32 - let mask10 = num <| BitVector.ofInt32 0b11 32 - let mask72 = (num <| BitVector.ofInt32 0b11111100 32) + let itState = AST.num <| BitVector.ofInt32 (int insInfo.ITState) 32 + let mask10 = AST.num <| BitVector.ofInt32 0b11 32 + let mask72 = (AST.num <| BitVector.ofInt32 0b11111100 32) let itState10 = itState .& mask10 - let itState72 = (itState .& mask72) >> (num <| BitVector.ofInt32 2 32) + let itState72 = (itState .& mask72) >> (AST.num <| BitVector.ofInt32 2 32) startMark insInfo builder builder setPSR ctxt R.CPSR PSR_IT10) builder setPSR ctxt R.CPSR PSR_IT72) endMark insInfo builder let adr insInfo ctxt = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let rd, result = parseOprOfADR insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder @@ -2640,14 +2641,14 @@ let adr insInfo ctxt = endMark insInfo builder let mls insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let rd, rn, rm, ra = transFourOprs insInfo ctxt - let r = tmpVar 32 + let r = builder.NewTempVar 32 let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder (zExt 64 ra .- zExt 64 rn .* - zExt 64 rm)) + builder (AST.zext 64 ra .- AST.zext 64 rn .* + AST.zext 64 rm)) builder raise InvalidOperandException let extend insInfo ctxt extractfn amount = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let rd, rm, rotation = parseOprOfExtend insInfo ctxt let rotated = shiftROR rm 32 rotation let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder (extractLow amount rotated)) + builder (AST.xtlo amount rotated)) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder @@ -2678,13 +2679,13 @@ let parseOprOfXTA insInfo ctxt = | _ -> raise InvalidOperandException let extendAndAdd insInfo ctxt amount = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let rd, rn, rm, rotation = parseOprOfXTA insInfo ctxt let rotated = shiftROR rm 32 rotation let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder (extractLow amount rotated)) + builder (AST.xtlo amount rotated)) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder @@ -2700,27 +2701,27 @@ let parseOprOfVLDR insInfo ctxt = | TwoOperands (OprSIMD (SFReg (Vector d)), OprMemory (OffsetMode (ImmOffset (rn , s, imm)))) -> let pc = getRegVar ctxt rn |> convertPCOpr insInfo ctxt - let baseAddr = align pc (num <| BitVector.ofInt32 4 32) + let baseAddr = align pc (AST.num <| BitVector.ofInt32 4 32) getRegVar ctxt d, getOffAddrWithImm s baseAddr imm, checkSingleReg d | _ -> raise InvalidOperandException let vldr insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let rd, addr, isSReg = parseOprOfVLDR insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder if isSReg then - let data = tmpVar 32 - builder addr) + let data = builder.NewTempVar 32 + builder addr) builder - let d2 = tmpVar 32 - builder addr) - builder (addr .+ (num (BitVector.ofInt32 4 32)))) - builder + let d2 = builder.NewTempVar 32 + builder addr) + builder (addr .+ (AST.num (BitVector.ofInt32 4 32)))) + builder raise InvalidOperandException let vstr insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let rd, addr, isSReg = parseOprOfVSTR insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - if isSReg then builder addr := rd) + if isSReg then builder addr := rd) else - let mem1 = loadLE 32 addr - let mem2 = loadLE 32 (addr .+ (num <| BitVector.ofInt32 4 32)) + let mem1 = AST.loadLE 32 addr + let mem2 = AST.loadLE 32 (addr .+ (AST.num <| BitVector.ofInt32 4 32)) let isbig = ctxt.Endianness = Endian.Big builder rd else extractLow 32 rd) + (mem1 := if isbig then AST.xthi 32 rd else AST.xtlo 32 rd) builder rd else extractHigh 32 rd) + (mem2 := if isbig then AST.xtlo 32 rd else AST.xthi 32 rd) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder @@ -2836,31 +2837,31 @@ let parsePUSHPOPsubValue insInfo = else getVFPDRegisterToInt regs.Head d, imm, isSReg -let vpopLoop ctxt d imm isSReg addr (builder: StmtBuilder) = +let vpopLoop ctxt d imm isSReg addr (builder: IRBuilder) = let rec singleRegLoop r addr = if r < imm then let reg = d + r |> byte |> OperandHelper.getVFPSRegister - let nextAddr = (addr .+ (num <| BitVector.ofInt32 4 32)) - builder addr) + let nextAddr = (addr .+ (AST.num <| BitVector.ofInt32 4 32)) + builder addr) singleRegLoop (r + 1) nextAddr else () let rec nonSingleRegLoop r addr = if r < imm / 2 then let reg = d + r |> byte |> OperandHelper.getVFPDRegister - let word1 = loadLE 32 addr - let word2 = loadLE 32 (addr .+ (num <| BitVector.ofInt32 4 32)) - let nextAddr = addr .+ (num <| BitVector.ofInt32 8 32) + let word1 = AST.loadLE 32 addr + let word2 = AST.loadLE 32 (addr .+ (AST.num <| BitVector.ofInt32 4 32)) + let nextAddr = addr .+ (AST.num <| BitVector.ofInt32 8 32) let isbig = ctxt.Endianness = Endian.Big - builder + let builder = IRBuilder (64) // FIXME + let t0 = builder.NewTempVar 32 let sp = getRegVar ctxt R.SP let d, imm, isSReg = parsePUSHPOPsubValue insInfo let addr = sp @@ -2868,28 +2869,28 @@ let vpop insInfo ctxt = startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder builder )) + builder )) vpopLoop ctxt d imm isSReg t0 builder putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder -let vpushLoop ctxt d imm isSReg addr (builder: StmtBuilder) = +let vpushLoop ctxt d imm isSReg addr (builder: IRBuilder) = let rec singleRegLoop r addr = if r < imm then let reg = d + r |> byte |> OperandHelper.getVFPSRegister - let nextAddr = (addr .+ (num <| BitVector.ofInt32 4 32)) - builder addr := getRegVar ctxt reg) + let nextAddr = (addr .+ (AST.num <| BitVector.ofInt32 4 32)) + builder addr := getRegVar ctxt reg) singleRegLoop (r + 1) nextAddr else () let rec nonSingleRegLoop r addr = if r < imm / 2 then let reg = d + r |> byte |> OperandHelper.getVFPDRegister - let mem1 = loadLE 32 addr - let mem2 = loadLE 32 (addr .+ (num <| BitVector.ofInt32 4 32)) - let nextAddr = addr .+ (num <| BitVector.ofInt32 8 32) + let mem1 = AST.loadLE 32 addr + let mem2 = AST.loadLE 32 (addr .+ (AST.num <| BitVector.ofInt32 4 32)) + let nextAddr = addr .+ (AST.num <| BitVector.ofInt32 8 32) let isbig = ctxt.Endianness = Endian.Big - let data1 = extractHigh 32 (getRegVar ctxt reg) - let data2 = extractLow 32 (getRegVar ctxt reg) + let data1 = AST.xthi 32 (getRegVar ctxt reg) + let data2 = AST.xtlo 32 (getRegVar ctxt reg) builder + let builder = IRBuilder (64) // FIXME + let t0 = builder.NewTempVar 32 let sp = getRegVar ctxt R.SP let d, imm, isSReg = parsePUSHPOPsubValue insInfo let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder - builder )) + builder )) builder raise InvalidOperandException let vand insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let dst, src1, src2 = parseOprOfVAND insInfo ctxt let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder @@ -2930,7 +2931,7 @@ let vand insInfo ctxt = endMark insInfo builder let vmrs insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let rt, fpscr = transTwoOprs insInfo ctxt let cpsr = getRegVar ctxt R.CPSR let isUnconditional = ParseUtils.isUnconditional insInfo.Condition @@ -2989,15 +2990,15 @@ let getParsingInfo insInfo = RegIndex = regIndex } -let inline numI32 n t = BitVector.ofInt32 n t |> num +let inline numI32 n t = BitVector.ofInt32 n t |> AST.num -let elem vector e size = extract vector (RegType.fromBitWidth size) (e * size) +let elem vector e size = AST.extract vector (RegType.fromBitWidth size) (e * size) let elemForIR vector vSize index size = - let index = zExt vSize index - let mask = num <| BitVector.ofUBInt (BigInteger.getMask size) vSize - let eSize = num <| BitVector.ofInt32 size vSize - (vector >> (index .* eSize)) .& mask |> extractLow (RegType.fromBitWidth size) + let index = AST.zext vSize index + let mask = AST.num <| BitVector.ofBInt (BigInteger.getMask size) vSize + let eSize = AST.num <| BitVector.ofInt32 size vSize + (vector >> (index .* eSize)) .& mask |> AST.xtlo (RegType.fromBitWidth size) let getESzieOfVMOV = function | Some (OneDT SIMDTyp8) -> 8 @@ -3022,12 +3023,12 @@ let parseOprOfVMOV insInfo ctxt builder = | TwoOperands (OprSIMD (SFReg (Vector reg)), OprImm _) -> if isQwordReg reg then let dst, imm = transTwoOprs insInfo ctxt - let imm64 = concat imm imm // FIXME - builder dst := imm64) - builder dst := imm64) + let imm64 = AST.concat imm imm // FIXME + builder dst := imm64) + builder dst := imm64) else let dst, imm = transTwoOprs insInfo ctxt - let imm64 = concat imm imm // FIXME + let imm64 = AST.concat imm imm // FIXME builder let dst, src = transTwoOprs insInfo ctxt @@ -3037,7 +3038,7 @@ let parseOprOfVMOV insInfo ctxt builder = | _ -> raise InvalidOperandException let vmov insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder @@ -3062,7 +3063,7 @@ let isAdvSIMDByDT = function let isAdvancedSIMD insInfo = match insInfo.Operands with | TwoOperands (OprSIMD _, OprImm _) | TwoOperands (OprSIMD _, OprSIMD _) -> - isF32orF64 insInfo.SIMDTyp |> Operators.not + isF32orF64 insInfo.SIMDTyp |> not | TwoOperands (OprSIMD _, OprReg _) | TwoOperands (OprReg _, OprSIMD _) | FourOperands (OprSIMD _, OprSIMD _, OprReg _, OprReg _) | FourOperands (OprReg _, OprReg _, OprSIMD _, OprSIMD _) -> @@ -3072,36 +3073,36 @@ let isAdvancedSIMD insInfo = | ThreeOperands (OprReg _, OprReg _, OprSIMD _) -> false | _ -> false -let absExpr expr size = ite (slt expr (num0 size)) (AST.neg expr) (expr) +let absExpr expr size = AST.ite (AST.slt expr (AST.num0 size)) (AST.neg expr) (expr) let vabs insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rd, rm = transTwoOprs insInfo ctxt let p = getParsingInfo insInfo - let regs = if typeOf rd = 64 then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rm = extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) for e in 0 .. p.Elements - 1 do builder then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rn = extract rn 64 (r * 64) - let rm = extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rn = AST.extract rn 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) for e in 0 .. p.Elements - 1 do builder getRegVar ctxt rd, - extractLow (RegType.fromBitWidth esize) (getRegVar ctxt rm) + AST.xtlo (RegType.fromBitWidth esize) (getRegVar ctxt rm) | _ -> raise InvalidOperandException let vdup insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let esize = 8 * getEBytes insInfo.SIMDTyp let rd, scalar = parseOprOfVDUP insInfo ctxt esize let elements = 64 / esize - let regs = if typeOf rd = 64 then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) for e in 0 .. elements - 1 do builder > t == num1 oprSz, Name lblEnd, Name lblLoopCont)) - builder > t == AST.num1 oprSz) + (AST.name lblEnd) (AST.name lblLoopCont)) + builder then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rm = extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) for e in 0 .. pInfo.Elements - 1 do countLeadingZeroBitsForIR (elem rd e pInfo.ESize) (elem rm e pInfo.ESize) pInfo.RtESize builder @@ -3171,10 +3174,10 @@ let vclz insInfo ctxt = endMark insInfo builder let maxExpr isUnsigned expr1 expr2 = - let op = if isUnsigned then gt else sgt in ite (op expr1 expr2) expr1 expr2 + let op = if isUnsigned then AST.gt else AST.sgt in AST.ite (op expr1 expr2) expr1 expr2 let minExpr isUnsigned expr1 expr2 = - let op = if isUnsigned then lt else slt in ite (op expr1 expr2) expr1 expr2 + let op = if isUnsigned then AST.lt else AST.slt in AST.ite (op expr1 expr2) expr1 expr2 let isUnsigned = function | Some (OneDT SIMDTypU8) | Some (OneDT SIMDTypU16) @@ -3185,39 +3188,39 @@ let isUnsigned = function | _ -> raise InvalidOperandException let vmaxmin insInfo ctxt maximum = - let builder = new StmtBuilder (32) + let builder = IRBuilder (32) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rd, rn, rm = transThreeOprs insInfo ctxt let pInfo = getParsingInfo insInfo - let regs = if typeOf rd = 64 then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 let unsigned = isUnsigned insInfo.SIMDTyp for r in 0 .. regs - 1 do - let rn = extract rn 64 (r * 64) - let rm = extract rm 64 (r * 64) - let rd = extract rd 64 (r * 64) + let rn = AST.extract rn 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) for e in 0 .. pInfo.Elements - 1 do let op1 = elem rn e pInfo.ESize let op2 = elem rm e pInfo.ESize let result = if maximum then maxExpr unsigned op1 op2 else minExpr unsigned op1 op2 - builder then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rn = extract rn 64 (r * 64) - let rm = extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rn = AST.extract rn 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) for e in 0 .. p.Elements - 1 do builder raise InvalidOperandException let vstm insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder @@ -3241,8 +3244,8 @@ let vstm insInfo ctxt = | Op.VSTMDB -> false | _ -> raise InvalidOpcodeException let regs = List.length regList - let imm32 = num <| BitVector.ofInt32 ((regs * 2) <<< 2) 32 - let addr = tmpVar 32 + let imm32 = AST.num <| BitVector.ofInt32 ((regs * 2) <<< 2) 32 + let addr = builder.NewTempVar 32 let updateRn rn = if insInfo.WriteBack.Value then if add then rn .+ imm32 else rn .- imm32 @@ -3250,19 +3253,19 @@ let vstm insInfo ctxt = builder addr - let mem2 = loadLE 32 (addr .+ (num <| BitVector.ofInt32 4 32)) - let data1 = extractLow 32 regList.[r] - let data2 = extractHigh 32 regList.[r] + let mem1 = AST.loadLE 32 addr + let mem2 = AST.loadLE 32 (addr .+ (AST.num <| BitVector.ofInt32 4 32)) + let data1 = AST.xtlo 32 regList.[r] + let data2 = AST.xthi 32 regList.[r] let isbig = ctxt.Endianness = Endian.Big builder )) + builder )) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let vldm insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder @@ -3273,8 +3276,8 @@ let vldm insInfo ctxt = | Op.VLDMDB -> false | _ -> raise InvalidOpcodeException let regs = List.length regList - let imm32 = num <| BitVector.ofInt32 ((regs * 2) <<< 2) 32 - let addr = tmpVar 32 + let imm32 = AST.num <| BitVector.ofInt32 ((regs * 2) <<< 2) 32 + let addr = builder.NewTempVar 32 let updateRn rn = if insInfo.WriteBack.Value then if add then rn .+ imm32 else rn .- imm32 @@ -3282,37 +3285,37 @@ let vldm insInfo ctxt = builder addr - let word2 = loadLE 32 (addr .+ (num <| BitVector.ofInt32 4 32)) + let word1 = AST.loadLE 32 addr + let word2 = AST.loadLE 32 (addr .+ (AST.num <| BitVector.ofInt32 4 32)) let isbig = ctxt.Endianness = Endian.Big builder )) + (regList.[r] := if isbig then AST.concat word1 word2 else AST.concat word2 word1) + builder )) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder let vecMulAccOrSub insInfo ctxt add = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rd, rn, rm = transThreeOprs insInfo ctxt let pInfo = getParsingInfo insInfo - let regs = if typeOf rd = 64 then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rn = extract rn 64 (r * 64) - let rm = extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rn = AST.extract rn 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) for e in 0 .. pInfo.Elements - 1 do - let sExt reg = sExt pInfo.RtESize (elem reg e pInfo.ESize) - let product = sExt rn .* sExt rm - let addend = if add then product else not product + let sext reg = AST.sext pInfo.RtESize (elem reg e pInfo.ESize) + let product = sext rn .* sext rm + let addend = if add then product else AST.not product builder raise InvalidOperandException let vecMulAccOrSubByScalar insInfo ctxt add = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rd, rn, (rm, index) = parseOprOfVMulByScalar insInfo ctxt let p = getParsingInfo insInfo - let regs = if typeOf rd = 64 then 1 else 2 - let op2val = sExt p.RtESize (elem rm index p.ESize) + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 + let op2val = AST.sext p.RtESize (elem rm index p.ESize) for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rn = extract rn 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rn = AST.extract rn 64 (r * 64) for e in 0 .. p.Elements - 1 do - let op1val = sExt p.RtESize (elem rn e p.ESize) - let addend = if add then op1val .* op2val else not (op1val .* op2val) + let op1val = AST.sext p.RtESize (elem rn e p.ESize) + let addend = if add then op1val .* op2val else AST.not (op1val .* op2val) builder then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 let polynomial = isPolynomial insInfo.SIMDTyp for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rn = extract rn 64 (r * 64) - let rm = extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rn = AST.extract rn 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) for e in 0 .. p.Elements - 1 do - let sExt reg = sExt (p.RtESize * 2) (elem reg e p.ESize) + let sext reg = AST.sext (p.RtESize * 2) (elem reg e p.ESize) let product = - if polynomial then polynomialMult rn rm p.ESize else sExt rn .* sExt rm - builder then 1 else 2 - let op2val = sExt (RegType.fromBitWidth p.ESize) (elem rm index p.ESize) + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 + let op2val = AST.sext (RegType.fromBitWidth p.ESize) (elem rm index p.ESize) for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rn = extract rn 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rn = AST.extract rn 64 (r * 64) for e in 0 .. p.Elements - 1 do - let op1val = sExt p.RtESize (elem rn e p.ESize) - builder raise InvalidOperandException let vmovn insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder @@ -3524,37 +3527,37 @@ let vmovn insInfo ctxt = let rtEsz = RegType.fromBitWidth esize let elements = 64 / esize for e in 0 .. elements - 1 do - builder then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rm = extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) for e in 0 .. p.Elements - 1 do - let result = neg <| sExt p.RtESize (elem rm e p.ESize) - builder - builder ) + let dest = builder.NewTempVar 64 + builder ) for e in 0 .. h - 1 do let addPair expr = elem expr (2 * e) p.ESize .+ elem expr (2 * e + 1) p.ESize @@ -3565,58 +3568,58 @@ let vpadd insInfo ctxt = endMark insInfo builder let vrshr insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rd, rm, imm = transThreeOprs insInfo ctxt - let imm = zExt 64 imm + let imm = AST.zext 64 imm let p = getParsingInfo insInfo - let regs = if typeOf rd = 64 then 1 else 2 - let extend = if isUnsigned insInfo.SIMDTyp then zExt else sExt - let roundConst = num1 64 << (imm .- num1 64) + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 + let extend = if isUnsigned insInfo.SIMDTyp then AST.zext else AST.sext + let roundConst = AST.num1 64 << (imm .- AST.num1 64) for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rm = extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) for e in 0 .. p.Elements - 1 do let result = (extend 64 (elem rm e p.ESize) .+ roundConst) >> imm - builder then 1 else 2 + let imm = AST.zext p.RtESize imm + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rm = extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) for e in 0 .. p.Elements - 1 do builder then 1 else 2 - let extend = if isUnsigned insInfo.SIMDTyp then zExt else sExt + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 + let extend = if isUnsigned insInfo.SIMDTyp then AST.zext else AST.sext for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rm = extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) for e in 0 .. p.Elements - 1 do - let shift = sExt 64 (extractLow 8 (elem rn e p.ESize)) + let shift = AST.sext 64 (AST.xtlo 8 (elem rn e p.ESize)) let result = extend 64 (elem rm e p.ESize) << shift - builder raise InvalidOperandException let vshr insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rd, rm, imm = transThreeOprs insInfo ctxt let p = getParsingInfo insInfo - let imm = zExt 64 imm - let regs = if typeOf rd = 64 then 1 else 2 - let extend = if isUnsigned insInfo.SIMDTyp then zExt else sExt + let imm = AST.zext 64 imm + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 + let extend = if isUnsigned insInfo.SIMDTyp then AST.zext else AST.sext for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rm = extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) for e in 0 .. p.Elements - 1 do let result = extend 64 (elem rm e p.ESize) >> imm - builder raise InvalidOperandException let vecTbl insInfo ctxt isVtbl = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rd, list, rm = parseOprOfVecTbl insInfo ctxt let vectors = list |> List.map (getRegVar ctxt) let length = List.length list - let table = concatExprs (List.toArray vectors) |> zExt 256 + let table = AST.concatArr (List.toArray vectors) |> AST.zext 256 for i in 0 .. 7 do let index = elem rm i 8 - let cond = lt index (num <| BitVector.ofInt32 (8 * length) 8) - let e = if isVtbl then num0 8 else elem rd i 8 - builder index 8) e) + let cond = AST.lt index (AST.num <| BitVector.ofInt32 (8 * length) 8) + let e = if isVtbl then AST.num0 8 else elem rd i 8 + builder index 8) e) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder @@ -3681,90 +3684,90 @@ let isImm = function | _ -> false let vectorCompare insInfo ctxt cmp = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rd, src1, src2 = transThreeOprs insInfo ctxt let p = getParsingInfo insInfo - let regs = if typeOf rd = 64 then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let src1 = extract src1 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let src1 = AST.extract src1 64 (r * 64) for e in 0 .. p.Elements - 1 do - let src2 = if isImm src2 then num0 p.RtESize - else elem (extract src2 64 (r * 64)) e p.ESize + let src2 = if isImm src2.E then AST.num0 p.RtESize + else elem (AST.extract src2 64 (r * 64)) e p.ESize let t = cmp (elem src1 e p.ESize) src2 - builder then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - let rd = extract rd 64 (r * 64) - let rn = extract rn 64 (r * 64) - let rm = extract rm 64 (r * 64) + let rd = AST.extract rd 64 (r * 64) + let rn = AST.extract rn 64 (r * 64) + let rm = AST.extract rm 64 (r * 64) for e in 0 .. p.Elements - 1 do - let c = (elem rn e p.ESize .& elem rm e p.ESize) != num0 p.RtESize - builder > imm - builder then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - let reg expr = extract expr 64 (r * 64) + let reg expr = AST.extract expr 64 (r * 64) builder then 1 else 2 + let imm = AST.concat imm imm // FIXME: A8-975 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - builder (r * 64) := extract rd 64 (r * 64) .| imm) + builder (r * 64) := AST.extract rd 64 (r * 64) .| imm) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder @@ -3775,29 +3778,29 @@ let vorr insInfo ctxt = | _ -> raise InvalidOperandException let vornReg insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rd, rn, rm = transThreeOprs insInfo ctxt - let regs = if typeOf rd = 64 then 1 else 2 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do - let reg expr = extract expr 64 (r * 64) - builder (r * 64) + builder then 1 else 2 + let imm = AST.concat imm imm // FIXME: A8-975 + let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 for r in 0 .. regs - 1 do builder (r * 64) := extract rd 64 (r * 64) .| not imm) + (AST.extract rd 64 (r * 64) := AST.extract rd 64 (r * 64) .| AST.not imm) putEndLabel ctxt lblIgnore isUnconditional None builder endMark insInfo builder @@ -3836,7 +3839,7 @@ let getRnAndRm ctxt = function let assignByEndian (ctxt: TranslationContext) dst src builder = let isbig = ctxt.Endianness = Endian.Big builder src else extractLow 32 src) + (dst := if isbig then AST.xthi 32 src else AST.xtlo 32 src) let parseOprOfVecStAndLd ctxt insInfo = let rdList = parseDstList insInfo.Operands |> List.map (getRegVar ctxt) @@ -3850,24 +3853,24 @@ let updateRn insInfo rn (rm: Expr option) n (regIdx: bool option) = let incAddr addr n = addr .+ (numI32 n 32) let vst1Multi insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rdList, rn, rm = parseOprOfVecStAndLd ctxt insInfo let pInfo = getParsingInfo insInfo let regs = getRegs insInfo.Operands - let addr = tmpVar 32 + let addr = builder.NewTempVar 32 builder 8 then - let mem = loadLE pInfo.RtESize addr + let mem = AST.loadLE pInfo.RtESize addr builder addr - let mem2 = loadLE 32 (incAddr addr 4) + let mem1 = AST.loadLE 32 addr + let mem2 = AST.loadLE 32 (incAddr addr 4) let reg = elem rdList.[r] e pInfo.ESize assignByEndian ctxt mem1 reg builder assignByEndian ctxt mem2 reg builder @@ -3876,16 +3879,16 @@ let vst1Multi insInfo ctxt = endMark insInfo builder let vst1Single insInfo ctxt index = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rd, rn, rm = parseOprOfVecStAndLd ctxt insInfo let pInfo = getParsingInfo insInfo - let addr = tmpVar 32 + let addr = builder.NewTempVar 32 builder raise InvalidOperandException let vld1SingleOne insInfo ctxt index = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rd, rn, rm = parseOprOfVecStAndLd ctxt insInfo let pInfo = getParsingInfo insInfo - let addr = tmpVar 32 + let addr = builder.NewTempVar 32 builder + let addr = builder.NewTempVar 32 builder concatExprs + let mem = AST.loadLE pInfo.RtESize addr + let repElem = Array.replicate pInfo.Elements mem |> AST.concatArr for r in 0 .. (List.length rdList - 1) do builder + let addr = builder.NewTempVar 32 builder 8 then - let data = tmpVar pInfo.RtESize - builder - let data2 = tmpVar 32 - let mem1 = loadLE 32 addr - let mem2 = loadLE 32 (addr .+ (num <| BitVector.ofInt32 4 32)) + let data1 = builder.NewTempVar 32 + let data2 = builder.NewTempVar 32 + let mem1 = AST.loadLE 32 addr + let mem2 = AST.loadLE 32 (addr .+ (AST.num <| BitVector.ofInt32 4 32)) let isbig = ctxt.Endianness = Endian.Big builder raise InvalidOperandException let vst2Multi insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rdList, rn, rm = parseOprOfVecStAndLd ctxt insInfo let regs = getRegs insInfo.Operands / 2 let pInfo = getParsingInfo insInfo - let addr = tmpVar 32 + let addr = builder.NewTempVar 32 builder )) + let mem1 = AST.loadLE pInfo.RtESize addr + let mem2 = AST.loadLE pInfo.RtESize (addr .+ (numI32 pInfo.EBytes 32)) builder )) @@ -3999,17 +4002,17 @@ let vst2Multi insInfo ctxt = endMark insInfo builder let vst2Single insInfo ctxt index = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rdList, rn, rm = parseOprOfVecStAndLd ctxt insInfo let pInfo = getParsingInfo insInfo - let addr = tmpVar 32 + let addr = builder.NewTempVar 32 builder )) + let mem1 = AST.loadLE pInfo.RtESize addr + let mem2 = AST.loadLE pInfo.RtESize (addr .+ (numI32 pInfo.EBytes 32)) builder raise InvalidOperandException let vst3Multi insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rdList, rn, rm = parseOprOfVecStAndLd ctxt insInfo let pInfo = getParsingInfo insInfo - let addr = tmpVar 32 + let addr = builder.NewTempVar 32 builder + let addr = builder.NewTempVar 32 builder raise InvalidOperandException let vst4Multi insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rdList, rn, rm = parseOprOfVecStAndLd ctxt insInfo let pInfo = getParsingInfo insInfo - let addr = tmpVar 32 + let addr = builder.NewTempVar 32 builder + let addr = builder.NewTempVar 32 builder raise InvalidOperandException let vld2SingleOne insInfo ctxt index = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rdList, rn, rm = parseOprOfVecStAndLd ctxt insInfo let pInfo = getParsingInfo insInfo - let addr = tmpVar 32 + let addr = builder.NewTempVar 32 builder + let addr = builder.NewTempVar 32 builder concatExprs - let repElem2 = Array.replicate pInfo.Elements mem2 |> concatExprs + let mem1 = AST.loadLE pInfo.RtESize addr + let mem2 = AST.loadLE pInfo.RtESize (incAddr addr pInfo.EBytes) + let repElem1 = Array.replicate pInfo.Elements mem1 |> AST.concatArr + let repElem2 = Array.replicate pInfo.Elements mem2 |> AST.concatArr builder + let addr = builder.NewTempVar 32 builder raise InvalidOperandException let vld3SingleOne insInfo ctxt index = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rdList, rn, rm = parseOprOfVecStAndLd ctxt insInfo let pInfo = getParsingInfo insInfo - let addr = tmpVar 32 + let addr = builder.NewTempVar 32 builder + let addr = builder.NewTempVar 32 builder concatExprs - let repElem2 = Array.replicate pInfo.Elements mem2 |> concatExprs - let repElem3 = Array.replicate pInfo.Elements mem3 |> concatExprs + let mem1 = AST.loadLE pInfo.RtESize addr + let mem2 = AST.loadLE pInfo.RtESize (incAddr addr pInfo.EBytes) + let mem3 = AST.loadLE pInfo.RtESize (incAddr addr (2 * pInfo.EBytes)) + let repElem1 = Array.replicate pInfo.Elements mem1 |> AST.concatArr + let repElem2 = Array.replicate pInfo.Elements mem2 |> AST.concatArr + let repElem3 = Array.replicate pInfo.Elements mem3 |> AST.concatArr builder + let addr = builder.NewTempVar 32 builder raise InvalidOperandException let vld4SingleOne insInfo ctxt index = - let builder = new StmtBuilder (8) + let builder = IRBuilder (8) let isUnconditional = ParseUtils.isUnconditional insInfo.Condition startMark insInfo builder let lblIgnore = checkCondition insInfo ctxt isUnconditional builder let rdList, rn, rm = parseOprOfVecStAndLd ctxt insInfo let pInfo = getParsingInfo insInfo - let addr = tmpVar 32 + let addr = builder.NewTempVar 32 builder + let addr = builder.NewTempVar 32 builder concatExprs - let repElem2 = Array.replicate pInfo.Elements mem2 |> concatExprs - let repElem3 = Array.replicate pInfo.Elements mem3 |> concatExprs - let repElem4 = Array.replicate pInfo.Elements mem4 |> concatExprs + let mem1 = AST.loadLE pInfo.RtESize addr + let mem2 = AST.loadLE pInfo.RtESize (incAddr addr pInfo.EBytes) + let mem3 = AST.loadLE pInfo.RtESize (incAddr addr (2 * pInfo.EBytes)) + let mem4 = AST.loadLE pInfo.RtESize (incAddr addr (3 * pInfo.EBytes)) + let repElem1 = Array.replicate pInfo.Elements mem1 |> AST.concatArr + let repElem2 = Array.replicate pInfo.Elements mem2 |> AST.concatArr + let repElem3 = Array.replicate pInfo.Elements mem3 |> AST.concatArr + let repElem4 = Array.replicate pInfo.Elements mem4 |> AST.concatArr builder + let addr = builder.NewTempVar 32 builder ldm Op.LDMIB insInfo ctxt (.+) | Op.LDMDA -> ldm Op.LDMDA insInfo ctxt (.-) | Op.LDMDB -> ldm Op.LDMDB insInfo ctxt (.-) - | Op.LDR -> ldr insInfo ctxt 32 zExt - | Op.LDRB -> ldr insInfo ctxt 8 zExt - | Op.LDRSB -> ldr insInfo ctxt 8 sExt + | Op.LDR -> ldr insInfo ctxt 32 AST.zext + | Op.LDRB -> ldr insInfo ctxt 8 AST.zext + | Op.LDRSB -> ldr insInfo ctxt 8 AST.sext | Op.LDRD -> ldrd insInfo ctxt - | Op.LDRH -> ldr insInfo ctxt 16 zExt - | Op.LDRSH -> ldr insInfo ctxt 16 sExt - | Op.LDREX -> ldr insInfo ctxt 32 zExt + | Op.LDRH -> ldr insInfo ctxt 16 AST.zext + | Op.LDRSH -> ldr insInfo ctxt 16 AST.sext + | Op.LDREX -> ldr insInfo ctxt 32 AST.zext | Op.SEL -> sel insInfo ctxt | Op.RBIT -> rbit insInfo ctxt | Op.REV -> rev insInfo ctxt @@ -4476,10 +4479,10 @@ let translate insInfo ctxt = | Op.UQSUB16 -> uqopr insInfo ctxt 16 (.-) | Op.ADR -> adr insInfo ctxt // for Thumb mode | Op.MLS -> mls insInfo ctxt - | Op.UXTB -> extend insInfo ctxt zExt 8 - | Op.SXTB -> extend insInfo ctxt sExt 8 - | Op.UXTH -> extend insInfo ctxt zExt 16 - | Op.SXTH -> extend insInfo ctxt sExt 16 + | Op.UXTB -> extend insInfo ctxt AST.zext 8 + | Op.SXTB -> extend insInfo ctxt AST.sext 8 + | Op.UXTH -> extend insInfo ctxt AST.zext 16 + | Op.SXTH -> extend insInfo ctxt AST.sext 16 | Op.VLDR -> vldr insInfo ctxt | Op.VSTR -> vstr insInfo ctxt | Op.VPOP -> vpop insInfo ctxt diff --git a/src/FrontEnd/ARM32/ARM32OperandHelper.fs b/src/FrontEnd/BinLifter/ARM32/ARM32OperandHelper.fs similarity index 98% rename from src/FrontEnd/ARM32/ARM32OperandHelper.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32OperandHelper.fs index 2aef4007..0783a7ce 100644 --- a/src/FrontEnd/ARM32/ARM32OperandHelper.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32OperandHelper.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.ARM32.OperandHelper +module internal B2R2.FrontEnd.BinLifter.ARM32.OperandHelper open B2R2 -open B2R2.FrontEnd -open B2R2.FrontEnd.ARM32.ParseUtils +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.ARM32.ParseUtils (* Offset *) let memOffsetImm offset = OprMemory (OffsetMode (ImmOffset offset)) @@ -653,6 +653,9 @@ let getRegAK b = (concat (extract b 15u 12u) (pickBit b 22u) 1) + 1u |> byte let getRegAL b = let regSize = if pickBit b 8u = 0u then 32 else 64 getVReg (pickBit b 22u) (extract b 15u 12u) regSize |> sVReg +let getRegAL' b = + let regSize = if pickBit b 8u = 0u then 64 else 32 + getVReg (pickBit b 22u) (extract b 15u 12u) regSize |> sVReg let getRegAM b = let regSize = if pickBit b 8u = 0u then 32 else 64 getVReg (pickBit b 7u) (extract b 19u 16u) regSize |> sVReg @@ -1459,8 +1462,8 @@ let checkStoreEx2 b (op1, op2, op3, _) = op2 b = OprReg R.LR || rn = OprReg R.PC || op1 b = rn || op1 b = op2 b || op1 b = op3 b) -let chkUnpreInAndNotLastItBlock ctxt = - inITBlock ctxt && lastInITBlock ctxt |> not +let chkUnpreInAndNotLastItBlock itstate = + inITBlock itstate && lastInITBlock itstate |> not let chkUnpreA b (op1, op2, op3) = checkUnpred (op1 b = OprReg R.PC || op2 b = OprReg R.PC || @@ -1501,10 +1504,10 @@ let chkUnpreP b (op1, op2, _) = checkUnpred (op1 b = OprReg R.PC || op2 b = OprReg R.PC) let chkUnpreQ b (op1, op2, _, _) = checkUnpred (op1 b = OprReg R.PC || op2 b = OprReg R.PC) -let chkUnpreR ctxt b _ = +let chkUnpreR itstate b _ = let d = concat (pickBit b 7u) (extract b 2u 0u) 3 checkUnpred ((extract b 6u 3u = 15u && d = 15u) && - d = 15u && inITBlock ctxt && lastInITBlock ctxt |> not) + d = 15u && inITBlock itstate && lastInITBlock itstate |> not) let chkUnpreS b _ = let rnd = concat (pickBit b 7u) (extract b 2u 0u) 3 let rm = extract b 6u 3u @@ -1659,17 +1662,17 @@ let chkUnpreBC b _ = let rL = ((pickBit b 8u) <<< 14) + (extract b 7u 0u) |> getRegList checkUnpred (List.length rL < 1) -let chkUnpreBD opcode ctxt b op1 = +let chkUnpreBD opcode itstate b op1 = let isITOpcode = function | Op.ITE | Op.ITET | Op.ITTE | Op.ITEE | Op.ITETT | Op.ITTET | Op.ITEET | Op.ITTTE | Op.ITETE | Op.ITTEE | Op.ITEEE -> true | _ -> false - checkUnpred (inITBlock ctxt || op1 b = OprCond Condition.UN || + checkUnpred (inITBlock itstate || op1 b = OprCond Condition.UN || (op1 b = OprCond Condition.AL && isITOpcode opcode)) -let chkUnpreBE ctxt b _ = +let chkUnpreBE itstate b _ = isUndefined (extract b 11u 8u = 14u) - checkUnpred (inITBlock ctxt) + checkUnpred (inITBlock itstate) let chkUnpreBF (b1, b2) _ = let n = extract b1 3u 0u @@ -1677,19 +1680,19 @@ let chkUnpreBF (b1, b2) _ = checkUnpred ((n = 15u || List.length rL < 2) || (pickBit b1 5u = 0b1u && pickBit b2 n = 0b1u)) -let chkUnpreBG ctxt (_, b2) _ = +let chkUnpreBG itstate (_, b2) _ = let pm = (extract b2 15u 14u) let rL = concat (pm <<< 1) (extract b2 12u 0u) 13 |> getRegList checkUnpred (List.length rL < 2 || pm = 0b11u || - (pickBit b2 15u = 1u && chkUnpreInAndNotLastItBlock ctxt)) + (pickBit b2 15u = 1u && chkUnpreInAndNotLastItBlock itstate)) -let chkUnpreBH ctxt (b1, b2) _ = +let chkUnpreBH itstate (b1, b2) _ = let n = extract b1 3u 0u let w = pickBit b1 5u let pm = extract b2 15u 14u let rl = getRegList (concat (pm <<< 1) (extract b2 12u 0u) 13) checkUnpred (n = 15u || List.length rl < 2 || pm = 0b11u) - checkUnpred (pickBit b2 15u = 1u && chkUnpreInAndNotLastItBlock ctxt) + checkUnpred (pickBit b2 15u = 1u && chkUnpreInAndNotLastItBlock itstate) checkUnpred (w = 1u && pickBit b2 n = 1u) let chkUnpreBI (_, b2) _ = @@ -1760,11 +1763,11 @@ let chkUnpreBQ (b1, b2) (op1, op2, op3, _) = rn = R.PC || op1 (b1, b2) = OprReg rn || op1 (b1, b2) = op2 (b1, b2)) -let chkUnpreBR ctxt (b1, b2) _ = +let chkUnpreBR itstate (b1, b2) _ = let rn = getRegister (extract b1 3u 0u |> byte) let rm = getRegister (extract b2 3u 0u |> byte) checkUnpred (rn = R.SP || rm = R.SP || rm = R.PC) - checkUnpred (chkUnpreInAndNotLastItBlock ctxt) + checkUnpred (chkUnpreInAndNotLastItBlock itstate) let chkUnpreBS (b1, b2) (op1, _) = let rn = getRegister (extract b1 3u 0u |> byte) @@ -1915,11 +1918,11 @@ let chkUnpreCQ (b1, b2) op1 = let chkUnpreCR (_, b2) _ = checkUnpred (pickBit b2 0u = 0b1u) -let chkUnpreCS ctxt (_, b2) _ = +let chkUnpreCS itstate (_, b2) _ = checkUnpred ((extract b2 4u 0u <> 0b0u && pickBit b2 8u = 0b0u) || (pickBit b2 10u = 0b1u && extract b2 7u 5u = 0b0u) || (pickBit b2 10u = 0b0u && extract b2 7u 5u <> 0b0u)) - checkUnpred (extract b2 10u 9u = 1u || inITBlock ctxt) + checkUnpred (extract b2 10u 9u = 1u || inITBlock itstate) let chkUnpreCT (b1, b2) (op1, _) = let rn = getRegister (extract b1 3u 0u |> byte) @@ -1928,11 +1931,11 @@ let chkUnpreCT (b1, b2) (op1, _) = checkUnpred (opr1 = OprReg R.SP || (opr1 = OprReg R.PC && w = 1u) || (w = 1u && OprReg rn = op1 (b1, b2))) -let chkUnpreCU ctxt (b1, b2) _ = +let chkUnpreCU itstate (b1, b2) _ = let n = extract b1 3u 0u let t = extract b2 15u 12u checkUnpred ((pickBit b2 8u = 1u && n = t) || - (t = 15u && chkUnpreInAndNotLastItBlock ctxt)) + (t = 15u && chkUnpreInAndNotLastItBlock itstate)) let chkUnpreCV (b1, b2) (op1, _) = checkUnpred (op1 (b1, b2) = OprReg R.SP) let chkUnpreCW (b1, b2) (op1, _) = @@ -1993,28 +1996,28 @@ let chkUnpreDC (b1, b2) (op1, op2, op3, op4) = let chkUnpreDD b _ = checkUnpred (List.length (getRegList (extract b 7u 0u)) < 1) -let chkUnpreDE ctxt _ _ = checkUnpred (inITBlock ctxt) +let chkUnpreDE itstate _ _ = checkUnpred (inITBlock itstate) -let chkUnpreDF ctxt b _ = +let chkUnpreDF itstate b _ = let d = concat (pickBit b 7u) (extract b 2u 0u) 3 - checkUnpred (d = 15u && chkUnpreInAndNotLastItBlock ctxt) + checkUnpred (d = 15u && chkUnpreInAndNotLastItBlock itstate) -let chkUnpreDG ctxt _ _ = - checkUnpred (chkUnpreInAndNotLastItBlock ctxt) +let chkUnpreDG itstate _ _ = + checkUnpred (chkUnpreInAndNotLastItBlock itstate) -let chkUnpreDH ctxt b op = - checkUnpred (op b = OprReg R.PC || chkUnpreInAndNotLastItBlock ctxt) +let chkUnpreDH itstate b op = + checkUnpred (op b = OprReg R.PC || chkUnpreInAndNotLastItBlock itstate) -let chkUnpreDI ctxt b _ = +let chkUnpreDI itstate b _ = checkUnpred (extract b 19u 16u = 15u || - chkUnpreInAndNotLastItBlock ctxt) + chkUnpreInAndNotLastItBlock itstate) let chkUnpreDJ it (b1, b2) op1 = checkUnpred (op1 (b1, b2) = OprReg R.SP || (op1 (b1, b2) = OprReg R.PC && chkUnpreInAndNotLastItBlock it)) -let chkUnpreDK ctxt b (op, _) = - checkUnpred (op b = OprReg R.PC && chkUnpreInAndNotLastItBlock ctxt) +let chkUnpreDK itstate b (op, _) = + checkUnpred (op b = OprReg R.PC && chkUnpreInAndNotLastItBlock itstate) let chkUnpreDL mode b (op1, _) = checkUnpred (op1 b = OprReg R.SP && mode <> ArchOperationMode.ARMMode) diff --git a/src/FrontEnd/ARM32/ARM32ParseUtils.fs b/src/FrontEnd/BinLifter/ARM32/ARM32ParseUtils.fs similarity index 93% rename from src/FrontEnd/ARM32/ARM32ParseUtils.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32ParseUtils.fs index 1e5dc24d..399d3ba2 100644 --- a/src/FrontEnd/ARM32/ARM32ParseUtils.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32ParseUtils.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.ARM32.ParseUtils +module internal B2R2.FrontEnd.BinLifter.ARM32.ParseUtils open B2R2 -open B2R2.FrontEnd.ARM32 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter.ARM32 +open B2R2.FrontEnd.BinLifter let extract binary n1 n2 = let m, n = if max n1 n2 = n1 then n1, n2 else n2, n1 @@ -62,10 +62,10 @@ let decodeRegShift = function | _ -> raise InvalidTypeException /// Test if the current instruction is in an IT block. -let inITBlock (ctxt: ParsingContext) = List.isEmpty ctxt.ITState |> not +let inITBlock itstate = List.isEmpty itstate |> not /// Test if the current instruction is the last instruction of an IT block. -let lastInITBlock (ctxt: ParsingContext) = List.length ctxt.ITState = 1 +let lastInITBlock itstate = List.length itstate = 1 let parseCond = function | 0x0uy -> Condition.EQ diff --git a/src/FrontEnd/ARM32/ARM32Parser.fs b/src/FrontEnd/BinLifter/ARM32/ARM32Parser.fs similarity index 76% rename from src/FrontEnd/ARM32/ARM32Parser.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32Parser.fs index 50855cc4..7041a694 100644 --- a/src/FrontEnd/ARM32/ARM32Parser.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32Parser.fs @@ -22,10 +22,9 @@ SOFTWARE. *) -module B2R2.FrontEnd.ARM32.Parser +module B2R2.FrontEnd.BinLifter.ARM32.Parser open B2R2 -open B2R2.FrontEnd let getThumbBytes (reader: BinReader) pos = let struct (b, nextPos) = reader.ReadUInt16 pos @@ -43,31 +42,25 @@ let isARMv8 = function | Arch.AARCH32 -> true | _ -> false -let parseThumb ctxt bin = function - | 2u -> Parserv7.parseV7Thumb16 ctxt bin - | 4u -> Parserv7.parseV7Thumb32 ctxt bin +let parseThumb (itstate: byref) bin = function + | 2u -> Parserv7.parseV7Thumb16 &itstate bin + | 4u -> Parserv7.parseV7Thumb32 &itstate bin | _ -> failwith "Invalid instruction length" -let computeContext opcode ctxt = - match opcode with - | Op.BLX -> struct (ParsingContext.ARMSwitchOperationMode ctxt, Some ctxt) - | _ -> struct (ctxt, None) - -let parse reader (ctxt: ParsingContext) arch addr pos = - let mode = ctxt.ArchOperationMode +let parse reader mode (it: byref) arch addr pos = let struct (bin, nextPos) = match mode with | ArchOperationMode.ThumbMode -> getThumbBytes reader pos | ArchOperationMode.ARMMode -> reader.ReadUInt32 pos | _-> raise InvalidTargetArchModeException let len = nextPos - pos |> uint32 - let opcode, cond, itState, wback, qualifier, simdt, oprs, cflag, ctxt = - match ctxt.ArchOperationMode with + let opcode, cond, itState, wback, qualifier, simdt, oprs, cflag = + match mode with | ArchOperationMode.ARMMode -> - if isARMv7 arch then Parserv7.parseV7ARM ctxt bin - else Parserv8.parseV8A32ARM ctxt bin // XXX + if isARMv7 arch then Parserv7.parseV7ARM bin + else Parserv8.parseV8A32ARM bin // XXX | ArchOperationMode.ThumbMode -> - if isARMv7 arch then parseThumb ctxt bin len + if isARMv7 arch then parseThumb &it bin len else raise UnallocatedException | _ -> raise InvalidTargetArchModeException let insInfo = @@ -82,7 +75,6 @@ let parse reader (ctxt: ParsingContext) arch addr pos = SIMDTyp = simdt Mode = mode Cflag = cflag } - let struct (ctxt, aux) = computeContext opcode ctxt - ARM32Instruction (addr, len, insInfo, ctxt, aux) + ARM32Instruction (addr, len, insInfo) // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/ARM32/ARM32ParserV7.fs b/src/FrontEnd/BinLifter/ARM32/ARM32ParserV7.fs similarity index 94% rename from src/FrontEnd/ARM32/ARM32ParserV7.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32ParserV7.fs index 063a9fb3..729fd6f7 100644 --- a/src/FrontEnd/ARM32/ARM32ParserV7.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32ParserV7.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.ARM32.Parserv7 +module internal B2R2.FrontEnd.BinLifter.ARM32.Parserv7 open B2R2 -open B2R2.FrontEnd -open B2R2.FrontEnd.ARM32.ParseUtils -open B2R2.FrontEnd.ARM32.OperandHelper +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.ARM32.ParseUtils +open B2R2.FrontEnd.BinLifter.ARM32.OperandHelper let getCFThumb (b1, b2) = let imm1 = pickBit b1 10u @@ -1363,7 +1363,7 @@ let parseOtherVFP bin = | 0b010111u -> Op.VCMPE, None, getOneDtAF bin, p2Oprs bin dummyChk (getRegAL, getImm0) | 0b011111u -> - Op.VCVT, None, getTwoDtD bin, p2Oprs bin dummyChk (getRegAL, getRegAN) + Op.VCVT, None, getTwoDtD bin, p2Oprs bin dummyChk (getRegAL', getRegAN) | op when op &&& 0b111101u = 0b100001u -> Op.VCVT, None, getTwoDtF bin, p2Oprs bin dummyChk (getRegAP, getRegAQ) | op when op &&& 0b111001u = 0b101001u -> @@ -1484,7 +1484,7 @@ let uncond000 bin = opcode, None, None, operands /// ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition, DDI0406C.b -let parseV7ARMUncond ctxt bin = +let parseV7ARMUncond bin = let opcode, wback, dt, operands = match extract bin 27u 25u with | op when op &&& 0b111u = 0b000u -> uncond000 bin @@ -1498,13 +1498,13 @@ let parseV7ARMUncond ctxt bin = | op when op &&& 0b111u = 0b110u -> uncond110 bin | op when op &&& 0b111u = 0b111u -> uncond111 bin | _ -> failwith "Wrong group specified." - opcode, None, 0uy, wback, None, dt, operands, None, ctxt + opcode, None, 0uy, wback, None, dt, operands, None /// ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition, DDI0406C.b -let parseV7ARM ctxt bin = +let parseV7ARM bin = let op = concat (extract bin 27u 25u) (pickBit bin 4u) 1 let cond = extract bin 31u 28u |> byte |> parseCond - if cond = Condition.UN then parseV7ARMUncond ctxt bin + if cond = Condition.UN then parseV7ARMUncond bin else let (opcode, wback, SIMDTyp, operands), cflag = match op with @@ -1520,7 +1520,7 @@ let parseV7ARM ctxt bin = | op when op &&& 0b1110u = 0b1100u -> parseGroup110 bin, None | op when op &&& 0b1110u = 0b1110u -> parseGroup111 bin, None | _ -> failwith "Wrong group specified." - opcode, Some cond, 0uy, wback, None, SIMDTyp, operands, cflag, ctxt + opcode, Some cond, 0uy, wback, None, SIMDTyp, operands, cflag /// Shift (immediate), add, subtract, move, and compare, page A6-224 let group0LSLInITBlock bin = @@ -1529,7 +1529,7 @@ let group0LSLInITBlock bin = | _ -> Op.LSL, p3Oprs bin dummyChk (getRegI, getRegH, getImm5D) /// Shift (immediate), add, subtract, move, and compare, page A6-224 -let parseGroup0InITBlock ctxt cond bin = +let parseGroup0InITBlock cond bin = let opcode, operands = match extract bin 13u 9u with | op when op &&& 0b11100u = 0b00000u -> group0LSLInITBlock bin @@ -1548,7 +1548,7 @@ let parseGroup0InITBlock ctxt cond bin = | op when op &&& 0b11100u = 0b11100u -> Op.SUB, p2Oprs bin dummyChk (getRegJ, getImm8A) | _ -> failwith "Wrong opcode in parseGroup0." - opcode, cond, 0uy, None, None, operands, ctxt + opcode, cond, 0uy, None, None, operands /// Shift (immediate), add, subtract, move, and compare, page A6-224 let group0LSLOutITBlock bin = @@ -1557,7 +1557,7 @@ let group0LSLOutITBlock bin = | _ -> Op.LSLS, p3Oprs bin dummyChk (getRegI, getRegH, getImm5D) /// Shift (immediate), add, subtract, move, and compare, page A6-224 -let parseGroup0OutITBlock ctxt bin = +let parseGroup0OutITBlock bin = let opcode, operands = match extract bin 13u 9u with | op when op &&& 0b11100u = 0b00000u -> group0LSLOutITBlock bin @@ -1576,16 +1576,16 @@ let parseGroup0OutITBlock ctxt bin = | op when op &&& 0b11100u = 0b11100u -> Op.SUBS, p2Oprs bin dummyChk (getRegJ, getImm8A) | _ -> failwith "Wrong opcode in parseGroup0." - opcode, None, 0uy, None, None, operands, ctxt + opcode, None, 0uy, None, None, operands /// Shift (immediate), add, subtract, move, and compare, page A6-224 -let parseGroup0 ctxt cond bin = +let parseGroup0 itstate cond bin = if extract bin 13u 9u &&& 0b11100u = 0b10100u then - Op.CMP, cond, 0uy, None, None, p2Oprs bin dummyChk (getRegJ, getImm8A), ctxt + Op.CMP, cond, 0uy, None, None, p2Oprs bin dummyChk (getRegJ, getImm8A) else - match inITBlock ctxt with - | true -> parseGroup0InITBlock ctxt cond bin - | false -> parseGroup0OutITBlock ctxt bin + match inITBlock itstate with + | true -> parseGroup0InITBlock cond bin + | false -> parseGroup0OutITBlock bin let parseGroup1InITBlock bin = match extract bin 9u 6u with @@ -1622,99 +1622,99 @@ let parseGroup1OutITBlock bin = | _ -> failwith "Wrong opcode in parseGroup1." /// Data-processing, page A6-225 -let parseGroup1 ctxt cond bin = +let parseGroup1 itstate cond bin = let parseWithITSTATE () = // XXX FIXME - if inITBlock ctxt then + if inITBlock itstate then let op, oprs = parseGroup1InITBlock bin - op, cond, 0uy, None, None, oprs, ctxt + op, cond, 0uy, None, None, oprs else let op, oprs = parseGroup1OutITBlock bin - op, None, 0uy, None, None, oprs, ctxt + op, None, 0uy, None, None, oprs match extract bin 9u 6u with | 0b1000u -> - Op.TST, cond, 0uy, None, None, p2Oprs bin dummyChk (getRegI, getRegH), ctxt + Op.TST, cond, 0uy, None, None, p2Oprs bin dummyChk (getRegI, getRegH) | 0b1010u -> - Op.CMP, cond, 0uy, None, None, p2Oprs bin dummyChk (getRegI, getRegH), ctxt + Op.CMP, cond, 0uy, None, None, p2Oprs bin dummyChk (getRegI, getRegH) | 0b1011u -> - Op.CMN, cond, 0uy, None, None, p2Oprs bin dummyChk (getRegI, getRegH), ctxt + Op.CMN, cond, 0uy, None, None, p2Oprs bin dummyChk (getRegI, getRegH) | _ -> parseWithITSTATE () -let parseGroup2ADD ctxt bin = +let parseGroup2ADD itstate bin = match concat (pickBit bin 7u) (extract bin 2u 0u) 3, extract bin 6u 3u with | 0b1101u, _ -> Op.ADD, p2Oprs bin dummyChk (getRegO, getRegP) | _ , 0b1101u -> - Op.ADD, p3Oprs bin (chkUnpreDF ctxt) (getRegO, getRegP, getRegO) - | _ -> Op.ADD, p2Oprs bin (chkUnpreR ctxt) (getRegO, getRegP) + Op.ADD, p3Oprs bin (chkUnpreDF itstate) (getRegO, getRegP, getRegO) + | _ -> Op.ADD, p2Oprs bin (chkUnpreR itstate) (getRegO, getRegP) /// Special data instructions and branch and exchange, page A6-226 -let parseGroup2 ctxt cond bin = +let parseGroup2 itstate cond bin = let opcode, operands = match extract bin 9u 7u with - | 0b000u | 0b001u -> parseGroup2ADD ctxt bin + | 0b000u | 0b001u -> parseGroup2ADD itstate bin | 0b010u | 0b011u -> Op.CMP, p2Oprs bin chkUnpreS (getRegO, getRegP) | 0b100u | 0b101u -> - Op.MOV, p2Oprs bin (chkUnpreDF ctxt) (getRegO, getRegP) - | 0b110u -> Op.BX, p1Opr bin (chkUnpreDG ctxt) getRegP - | 0b111u -> Op.BLX, p1Opr bin (chkUnpreDH ctxt) getRegP + Op.MOV, p2Oprs bin (chkUnpreDF itstate) (getRegO, getRegP) + | 0b110u -> Op.BX, p1Opr bin (chkUnpreDG itstate) getRegP + | 0b111u -> Op.BLX, p1Opr bin (chkUnpreDH itstate) getRegP | _ -> failwith "Wrong opcode in parseGroup2." - opcode, cond, 0uy, None, None, operands, ctxt + opcode, cond, 0uy, None, None, operands -let parseGroup3Sub ctxt cond bin = +let parseGroup3Sub cond bin = match extract bin 15u 11u with | 0b01100u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemE) - Op.STR, cond, 0uy, Some false, None, oprs, ctxt + Op.STR, cond, 0uy, Some false, None, oprs | 0b01101u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemE) - Op.LDR, cond, 0uy, Some false, None, oprs, ctxt + Op.LDR, cond, 0uy, Some false, None, oprs | 0b01110u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemF) - Op.STRB, cond, 0uy, Some false, None, oprs, ctxt + Op.STRB, cond, 0uy, Some false, None, oprs | 0b01111u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemF) - Op.LDRB, cond, 0uy, Some false, None, oprs, ctxt + Op.LDRB, cond, 0uy, Some false, None, oprs | 0b10000u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemG) - Op.STRH, cond, 0uy, Some false, None, oprs, ctxt + Op.STRH, cond, 0uy, Some false, None, oprs | 0b10001u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemG) - Op.LDRH, cond, 0uy, Some false, None, oprs, ctxt + Op.LDRH, cond, 0uy, Some false, None, oprs | 0b10010u -> let oprs = p2Oprs bin dummyChk (getRegJ, getMemC) - Op.STR, cond, 0uy, Some false, None, oprs, ctxt + Op.STR, cond, 0uy, Some false, None, oprs | 0b10011u -> let oprs = p2Oprs bin dummyChk (getRegJ, getMemC) - Op.LDR, cond, 0uy, Some false, None, oprs, ctxt + Op.LDR, cond, 0uy, Some false, None, oprs | _ -> failwith "Wrong opcode in parseGroup3." /// Load/store single data item, page A6-227 -let parseGroup3 ctxt cond bin = +let parseGroup3 cond bin = match concat (extract bin 15u 12u) (extract bin 11u 9u) 3 with | 0b0101000u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemD) - Op.STR, cond, 0uy, Some false, None, oprs, ctxt + Op.STR, cond, 0uy, Some false, None, oprs | 0b0101001u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemD) - Op.STRH, cond, 0uy, Some false, None, oprs, ctxt + Op.STRH, cond, 0uy, Some false, None, oprs | 0b0101010u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemD) - Op.STRB, cond, 0uy, Some false, None, oprs, ctxt + Op.STRB, cond, 0uy, Some false, None, oprs | 0b0101011u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemD) - Op.LDRSB, cond, 0uy, Some false, None, oprs, ctxt + Op.LDRSB, cond, 0uy, Some false, None, oprs | 0b0101100u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemD) - Op.LDR, cond, 0uy, None, None, oprs, ctxt + Op.LDR, cond, 0uy, None, None, oprs | 0b0101101u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemD) - Op.LDRH, cond, 0uy, Some false, None, oprs, ctxt + Op.LDRH, cond, 0uy, Some false, None, oprs | 0b0101110u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemD) - Op.LDRB, cond, 0uy, Some false, None, oprs, ctxt + Op.LDRB, cond, 0uy, Some false, None, oprs | 0b0101111u -> let oprs = p2Oprs bin dummyChk (getRegI, getMemD) - Op.LDRSH, cond, 0uy, Some false, None, oprs, ctxt - | _ -> parseGroup3Sub ctxt cond bin + Op.LDRSH, cond, 0uy, Some false, None, oprs + | _ -> parseGroup3Sub cond bin let inverseCond cond = (cond &&& 0xeuy) ||| ((~~~ cond) &&& 0b1uy) @@ -1761,113 +1761,113 @@ let getIT fstCond cond mask = opcode, itState /// If-Then, and hints, page A6-229 -let getIfThenNHints cond (ctxt: ParsingContext) bin = +let getIfThenNHints cond (itstate: byref) bin = match extract bin 7u 4u, extract bin 3u 0u with | o1, o2 when o2 <> 0b0000u -> - let opcode, itState = getIT (pickBit o1 0u) (byte o1) o2 - let operand = p1Opr bin (chkUnpreBD opcode ctxt) getFirstCond - opcode, None, (byte bin), None, None, operand, - ParsingContext.InitThumb (ctxt.ArchOperationMode, itState) - | 0b0000u, _ -> Op.NOP, cond, 0uy, None, None, NoOperand, ctxt - | 0b0001u, _ -> Op.YIELD, cond, 0uy, None, None, NoOperand, ctxt - | 0b0010u, _ -> Op.WFE, cond, 0uy, None, None, NoOperand, ctxt - | 0b0011u, _ -> Op.WFI, cond, 0uy, None, None, NoOperand, ctxt - | 0b0100u, _ -> Op.SEV, cond, 0uy, None, None, NoOperand, ctxt + let opcode, itstate' = getIT (pickBit o1 0u) (byte o1) o2 + let operand = p1Opr bin (chkUnpreBD opcode itstate) getFirstCond + itstate <- itstate' + opcode, None, (byte bin), None, None, operand + | 0b0000u, _ -> Op.NOP, cond, 0uy, None, None, NoOperand + | 0b0001u, _ -> Op.YIELD, cond, 0uy, None, None, NoOperand + | 0b0010u, _ -> Op.WFE, cond, 0uy, None, None, NoOperand + | 0b0011u, _ -> Op.WFI, cond, 0uy, None, None, NoOperand + | 0b0100u, _ -> Op.SEV, cond, 0uy, None, None, NoOperand | _ -> failwith "Wrong if-then & hints." /// Miscellaneous 16-bit instructions, page A6-228 -let parseGroup4 ctxt cond bin = +let parseGroup4 (itstate: byref) cond bin = match extract bin 11u 5u with | op when op &&& 0b1111100u = 0b0000000u -> Op.ADD, cond, 0uy, None, None, - p3Oprs bin dummyChk (getRegSP, getRegSP, getImm7A), ctxt + p3Oprs bin dummyChk (getRegSP, getRegSP, getImm7A) | op when op &&& 0b1111100u = 0b0000100u -> Op.SUB, cond, 0uy, None, None, - p3Oprs bin dummyChk (getRegSP, getRegSP, getImm7A), ctxt + p3Oprs bin dummyChk (getRegSP, getRegSP, getImm7A) | op when op &&& 0b1111000u = 0b0001000u -> Op.CBZ, None, 0uy, None, None, - p2Oprs bin (chkUnpreDE ctxt) (getRegI, getLbl7A), ctxt + p2Oprs bin (chkUnpreDE itstate) (getRegI, getLbl7A) | op when op &&& 0b1111110u = 0b0010000u -> Op.SXTH, cond, 0uy, None, None, - p2Oprs bin dummyChk (getRegI, getRegH), ctxt + p2Oprs bin dummyChk (getRegI, getRegH) | op when op &&& 0b1111110u = 0b0010010u -> Op.SXTB, cond, 0uy, None, None, - p2Oprs bin dummyChk (getRegI, getRegH), ctxt + p2Oprs bin dummyChk (getRegI, getRegH) | op when op &&& 0b1111110u = 0b0010100u -> Op.UXTH, cond, 0uy, None, None, - p2Oprs bin dummyChk (getRegI, getRegH), ctxt + p2Oprs bin dummyChk (getRegI, getRegH) | op when op &&& 0b1111110u = 0b0010110u -> Op.UXTB, cond, 0uy, None, None, - p2Oprs bin dummyChk (getRegI, getRegH), ctxt + p2Oprs bin dummyChk (getRegI, getRegH) | op when op &&& 0b1111000u = 0b0011000u -> Op.CBZ, None, 0uy, None, None, - p2Oprs bin (chkUnpreDE ctxt) (getRegI, getLbl7A), ctxt + p2Oprs bin (chkUnpreDE itstate) (getRegI, getLbl7A) | op when op &&& 0b1110000u = 0b0100000u -> - Op.PUSH, cond, 0uy, None, None, p1Opr bin chkUnpreBC getRegListN, ctxt + Op.PUSH, cond, 0uy, None, None, p1Opr bin chkUnpreBC getRegListN | 0b0110010u -> Op.SETEND, None, 0uy, None, None, - p1Opr bin (chkUnpreDE ctxt) getEndianB, ctxt + p1Opr bin (chkUnpreDE itstate) getEndianB | 0b0110011u when pickBit bin 4u = 0b0u -> Op.CPSIE, None, 0uy, None, None, - p1Opr bin (chkUnpreDE ctxt) getFlagB, ctxt + p1Opr bin (chkUnpreDE itstate) getFlagB | 0b0110011u -> Op.CPSID, None, 0uy, None, None, - p1Opr bin (chkUnpreDE ctxt) getFlagB, ctxt + p1Opr bin (chkUnpreDE itstate) getFlagB | op when op &&& 0b1111000u = 0b1001000u -> Op.CBNZ, None, 0uy, None, None, - p2Oprs bin (chkUnpreDE ctxt) (getRegI, getLbl7A), ctxt + p2Oprs bin (chkUnpreDE itstate) (getRegI, getLbl7A) | op when op &&& 0b1111110u = 0b1010000u -> Op.REV, cond, 0uy, None, None, - p2Oprs bin dummyChk (getRegI, getRegH), ctxt + p2Oprs bin dummyChk (getRegI, getRegH) | op when op &&& 0b1111110u = 0b1010010u -> Op.REV16, cond, 0uy, None, None, - p2Oprs bin dummyChk (getRegI, getRegH), ctxt + p2Oprs bin dummyChk (getRegI, getRegH) | op when op &&& 0b1111110u = 0b1010110u -> Op.REVSH, cond, 0uy, None, None, - p2Oprs bin dummyChk (getRegI, getRegH), ctxt + p2Oprs bin dummyChk (getRegI, getRegH) | op when op &&& 0b1111000u = 0b1011000u -> Op.CBNZ, None, 0uy, None, None, - p2Oprs bin (chkUnpreDE ctxt) (getRegI, getLbl7A), ctxt + p2Oprs bin (chkUnpreDE itstate) (getRegI, getLbl7A) | op when op &&& 0b1110000u = 0b1100000u -> - Op.POP, cond, 0uy, None, None, p1Opr bin chkUnpreBC getRegListO, ctxt + Op.POP, cond, 0uy, None, None, p1Opr bin chkUnpreBC getRegListO | op when op &&& 0b1111000u = 0b1110000u -> - Op.BKPT, None, 0uy, None, None, p1Opr bin dummyChk getImm8A, ctxt - | op when op &&& 0b1111000u = 0b1111000u -> getIfThenNHints cond ctxt bin + Op.BKPT, None, 0uy, None, None, p1Opr bin dummyChk getImm8A + | op when op &&& 0b1111000u = 0b1111000u -> getIfThenNHints cond &itstate bin | _ -> failwith "Wrong opcode in parseGroup4." /// Conditional branch, and Supervisor Call, page A6-229 -let parseGroup5 ctxt cond bin = +let parseGroup5 itstate cond bin = let bCond c = c |> byte |> parseCond |> Some match extract bin 11u 8u with - | 0b1110u -> Op.UDF, cond, 0uy, None, None, p1Opr bin dummyChk getImm8A, ctxt - | 0b1111u -> Op.SVC, cond, 0uy, None, None, p1Opr bin dummyChk getImm8A, ctxt + | 0b1110u -> Op.UDF, cond, 0uy, None, None, p1Opr bin dummyChk getImm8A + | 0b1111u -> Op.SVC, cond, 0uy, None, None, p1Opr bin dummyChk getImm8A | c -> Op.B, bCond c, 0uy, None, getQfN (), - p1Opr bin (chkUnpreBE ctxt) getLbl9A, ctxt + p1Opr bin (chkUnpreBE itstate) getLbl9A /// Load/store multiple. page A6-237 -let parseGroup6 ctxt bin = +let parseGroup6 itstate bin = let b1, b2 = halve bin let b = concat b1 b2 16 let chkWRn = concat (pickBit b1 5u) (extract b1 3u 0u) 4 = 0b11101u let wback = pickBit b1 5u = 0b1u |> Some match concat (extract b1 8u 7u) (pickBit b1 4u) 1 with | 0b000u -> Op.SRSDB, wback, None, None, p2Oprs b dummyChk (getRegM, getImm5B) - | 0b001u -> Op.RFEDB, wback, None, None, p1Opr b (chkUnpreDI ctxt) getRegAA + | 0b001u -> Op.RFEDB, wback, None, None, p1Opr b (chkUnpreDI itstate) getRegAA | 0b010u -> Op.STM, wback, getQfW (), None, p2Oprs (b1, b2) chkUnpreBF (getRegisterWB, getRegListP) | 0b011u when chkWRn -> - Op.POP, None, getQfW (), None, p1Opr (b1, b2) (chkUnpreBG ctxt) getRegListQ + Op.POP, None, getQfW (), None, p1Opr (b1, b2) (chkUnpreBG itstate) getRegListQ | 0b011u -> Op.LDM, wback, getQfW (), None, - p2Oprs (b1, b2) (chkUnpreBH ctxt) (getRegisterWB, getRegListQ) + p2Oprs (b1, b2) (chkUnpreBH itstate) (getRegisterWB, getRegListQ) | 0b100u when chkWRn -> Op.PUSH, None, getQfW (), None, p1Opr (b1, b2) chkUnpreBI getRegListP | 0b100u -> Op.STMDB, wback, None, None, p2Oprs (b1, b2) chkUnpreBF (getRegisterWB, getRegListP) | 0b101u -> Op.LDMDB, wback, None, None, - p2Oprs (b1, b2) (chkUnpreBH ctxt) (getRegisterWB, getRegListQ) + p2Oprs (b1, b2) (chkUnpreBH itstate) (getRegisterWB, getRegListQ) | 0b110u -> Op.SRSIA, wback, None, None, p2Oprs b dummyChk (getRegM, getImm5B) - | 0b111u -> Op.RFEIA, wback, None, None, p1Opr b (chkUnpreDI ctxt) getRegAA + | 0b111u -> Op.RFEIA, wback, None, None, p1Opr b (chkUnpreDI itstate) getRegAA | _ -> failwith "Wrong opcode in parseGroup6." /// Load/store dual, load/store exclusive, table branch, page A6-238 @@ -1895,7 +1895,7 @@ let parseGroup7Not010 b1 b2 = | _ -> failwith "Wrong opcode in parseGroup7." /// Load/store dual, load/store exclusive, table branch, page A6-238 -let parseGroup7With010 ctxt b1 b2 = +let parseGroup7With010 itstate b1 b2 = match concat (pickBit b1 4u) (extract b2 6u 4u) 3 with | 0b0100u -> Op.STREXB, None, p3Oprs (b1, b2) chkUnpreBJ (getRegAX, getRegAW, getMemAJ) @@ -1904,8 +1904,8 @@ let parseGroup7With010 ctxt b1 b2 = | 0b0111u -> Op.STREXD, None, p4Oprs (b1, b2) chkUnpreBQ (getRegAX, getRegAW, getRegAV, getMemAJ) - | 0b1000u -> Op.TBB, None, p1Opr (b1, b2) (chkUnpreBR ctxt) getMemAK - | 0b1001u -> Op.TBH, None, p1Opr (b1, b2) (chkUnpreBR ctxt) getMemAL + | 0b1000u -> Op.TBB, None, p1Opr (b1, b2) (chkUnpreBR itstate) getMemAK + | 0b1001u -> Op.TBH, None, p1Opr (b1, b2) (chkUnpreBR itstate) getMemAL | 0b1100u -> Op.LDREXB, None, p2Oprs (b1, b2) chkUnpreBS (getRegAW, getMemAJ) | 0b1101u -> Op.LDREXH, None, p2Oprs (b1, b2) chkUnpreBS (getRegAW, getMemAJ) | 0b1111u -> @@ -1913,11 +1913,11 @@ let parseGroup7With010 ctxt b1 b2 = | _ -> failwith "Wrong opcode in parseGroup7." /// Load/store dual, load/store exclusive, table branch, page A6-238 -let parseGroup7 ctxt bin = +let parseGroup7 itstate bin = let b1, b2 = halve bin let opcode, wback, operands = match extract b1 8u 7u, pickBit b1 5u with - | 0b01u, 0b0u -> parseGroup7With010 ctxt b1 b2 + | 0b01u, 0b0u -> parseGroup7With010 itstate b1 b2 | _ -> parseGroup7Not010 b1 b2 opcode, wback, None, None, operands @@ -2307,18 +2307,18 @@ let parseGroup11 cond bin = | _ -> failwith "Wrong opcode in parseGroup11." opcode, cond, None, operands -let parseChangeProcStateHintsCPS ctxt b1 b2 = +let parseChangeProcStateHintsCPS itstate b1 b2 = let opcode, operands = match extract b2 10u 8u with - | 0b100u -> Op.CPSIE, p1Opr (b1, b2) (chkUnpreCS ctxt) getFlagC - | 0b101u -> Op.CPSIE, p2Oprs (b1, b2) (chkUnpreCS ctxt) (getFlagC, getImm5H) - | 0b110u -> Op.CPSID, p1Opr (b1, b2) (chkUnpreCS ctxt) getFlagC - | 0b111u -> Op.CPSID, p2Oprs (b1, b2) (chkUnpreCS ctxt) (getFlagC, getImm5H) + | 0b100u -> Op.CPSIE, p1Opr (b1, b2) (chkUnpreCS itstate) getFlagC + | 0b101u -> Op.CPSIE, p2Oprs (b1, b2) (chkUnpreCS itstate) (getFlagC, getImm5H) + | 0b110u -> Op.CPSID, p1Opr (b1, b2) (chkUnpreCS itstate) getFlagC + | 0b111u -> Op.CPSID, p2Oprs (b1, b2) (chkUnpreCS itstate) (getFlagC, getImm5H) | _ -> failwith "Wrong opcode in change processor state and hints." opcode, None, getQfW (), operands /// Change Processor State, and hints, page A6-236 -let parseChangeProcStateHints ctxt cond b1 b2 = +let parseChangeProcStateHints itstate cond b1 b2 = match extract b2 10u 8u, extract b2 7u 0u with | 0b000u, 0b00000000u -> Op.NOP, cond, Some W, NoOperand | 0b000u, 0b00000001u -> Op.YIELD, cond, Some W, NoOperand @@ -2327,10 +2327,10 @@ let parseChangeProcStateHints ctxt cond b1 b2 = | 0b000u, 0b00000100u -> Op.SEV, cond, Some W, NoOperand | 0b000u, o2 when o2 &&& 0b11110000u = 0b11110000u -> Op.DBG, cond, None, p1Opr b2 dummyChk getImm4A - | 0b001u, _ -> Op.CPS, None, None, p1Opr (b1, b2) (chkUnpreCS ctxt) getImm5H + | 0b001u, _ -> Op.CPS, None, None, p1Opr (b1, b2) (chkUnpreCS itstate) getImm5H | 0b010u, _ -> raise UnpredictableException | 0b011u, _ -> raise UnpredictableException - | _ -> parseChangeProcStateHintsCPS ctxt b1 b2 + | _ -> parseChangeProcStateHintsCPS itstate b1 b2 /// Miscellaneous control instructions, page A6-237 let parseMiscellaneousInstrs cond b2 = @@ -2346,7 +2346,7 @@ let parseMiscellaneousInstrs cond b2 = opcode, cond, None, operands /// Branches and miscellaneous control, page A6-235 -let parseGroup12Sub (ctxt: ParsingContext) cond bin = +let parseGroup12Sub itstate cond bin = let b1, b2 = halve bin let chkBit5 = pickBit b2 5u = 0b1u let chkOp2 = extract b2 9u 8u = 0b00u @@ -2355,14 +2355,14 @@ let parseGroup12Sub (ctxt: ParsingContext) cond bin = match extract b1 10u 4u with | op when op &&& 0b0111000u <> 0b0111000u -> Op.B, extract b1 9u 6u |> byte |> parseCond |> Some, getQfW (), - p1Opr (b1, b2) (chkUnpreDE ctxt) getLbl21A + p1Opr (b1, b2) (chkUnpreDE itstate) getLbl21A | op when op &&& 0b1111110u = 0b0111000u && chkBit5 -> Op.MSR, cond, None, p2Oprs (b1, b2) chkUnpreCN (getBankedRegB, getRegAY) | 0b0111000u when not chkBit5 && chkOp2 -> Op.MSR, cond, None, p2Oprs (b1, b2) chkUnpreCO (getAPSRxC, getRegAY) | 0b0111000u when not chkBit5 -> Op.MSR, cond, None, p2Oprs (b1, b2) chkUnpreCP (getxPSRxA, getRegAY) - | 0b0111010u -> parseChangeProcStateHints ctxt cond b1 b2 + | 0b0111010u -> parseChangeProcStateHints itstate cond b1 b2 | 0b0111011u -> parseMiscellaneousInstrs cond b2 | 0b0111100u -> Op.BXJ, cond, None, p1Opr (b1, b2) chkUnpreCQ getRegAY | 0b0111101u when chkI8 -> Op.ERET, cond, None, NoOperand @@ -2376,7 +2376,7 @@ let parseGroup12Sub (ctxt: ParsingContext) cond bin = opcode, cond, qualifiers, operands /// Branches and miscellaneous control, page A6-235 -let parseGroup12 ctxt cond bin = +let parseGroup12 itstate cond bin = let b1, b2 = halve bin let chkA = extract b1 10u 4u = 0b1111110u let chkB = extract b1 10u 4u = 0b1111111u @@ -2385,9 +2385,9 @@ let parseGroup12 ctxt cond bin = Op.HVC, None, None, p1Opr (b1, b2) dummyChk getImm16B | 0b000u when chkB -> Op.SMC, cond, None, p1Opr bin dummyChk getImm4A | 0b010u when chkB -> Op.UDF, cond, None, p1Opr (b1, b2) dummyChk getImm16B - | op when op &&& 0b101u = 0b000u -> parseGroup12Sub ctxt cond bin + | op when op &&& 0b101u = 0b000u -> parseGroup12Sub itstate cond bin | op when op &&& 0b101u = 0b001u -> - Op.B, cond, getQfW (), p1Opr (b1, b2) (chkUnpreDG ctxt) getLbl25A + Op.B, cond, getQfW (), p1Opr (b1, b2) (chkUnpreDG itstate) getLbl25A | op when op &&& 0b101u = 0b100u -> Op.BLX, cond, None, p1Opr (b1, b2) chkUnpreCR getLbl25B | op when op &&& 0b101u = 0b101u -> @@ -2569,7 +2569,7 @@ let parseGroup15 bin = | _ -> failwith "Wrong opcode in parseGroup15." /// Load word, page A6-239 -let parseGroup16 ctxt bin = +let parseGroup16 itstate bin = let b1, b2 = halve bin let chkRn = extract b1 3u 0u = 0b1111u let chkRn2 = extract b1 3u 0u = 0b1101u @@ -2578,21 +2578,21 @@ let parseGroup16 ctxt bin = match concat (extract b1 8u 7u) (extract b2 11u 6u) 6 with | op when op &&& 0b10000000u = 0b0u && chkRn -> Op.LDR, Some false, getQfW (), None, - p2Oprs (b1, b2) (chkUnpreDK ctxt) (getRegAW, getMemAQ) + p2Oprs (b1, b2) (chkUnpreDK itstate) (getRegAW, getMemAQ) | 0b00000000u -> Op.LDR, None, getQfW (), None, - p2Oprs (b1, b2) (chkUnpreCX ctxt) (getRegAW, getMemAO) + p2Oprs (b1, b2) (chkUnpreCX itstate) (getRegAW, getMemAO) | 0b00101100u when chkRn2 && chkPop -> - Op.POP, None, getQfW (), None, p1Opr (b1, b2) (chkUnpreDJ ctxt) getRegAW + Op.POP, None, getQfW (), None, p1Opr (b1, b2) (chkUnpreDJ itstate) getRegAW | op when op &&& 0b11100100u = 0b00100100u -> Op.LDR, wback, None, None, - p2Oprs (b1, b2) (chkUnpreCU ctxt) (getRegAW, getMemAM) + p2Oprs (b1, b2) (chkUnpreCU itstate) (getRegAW, getMemAM) | op when op &&& 0b11111100u = 0b00110000u -> Op.LDR, wback, None, None, - p2Oprs (b1, b2) (chkUnpreCU ctxt) (getRegAW, getMemAM) + p2Oprs (b1, b2) (chkUnpreCU itstate) (getRegAW, getMemAM) | op when op &&& 0b11000000u = 0b01000000u -> Op.LDR, Some false, getQfW (), None, - p2Oprs (b1, b2) (chkUnpreDK ctxt) (getRegAW, getMemAN) + p2Oprs (b1, b2) (chkUnpreDK itstate) (getRegAW, getMemAN) | op when op &&& 0b11111100u = 0b00111000u -> Op.LDRT, None, None, None, p2Oprs (b1, b2) chkUnpreBL (getRegAW, getMemAG) | _ -> failwith "Wrong opcode in parseGroup16." @@ -2829,17 +2829,17 @@ let parseGroup20 bin = | 0b1100110u -> Op.UMAAL, None, None, None, getFourOprs () | _ -> failwith "Wrong opcode in parseGroup20." -let parseV7Thumb32Group01 ctxt cond bin = +let parseV7Thumb32Group01 itstate cond bin = let opcode, wback, q, dt, operands = match extract bin 10u 9u with - | 0b00u when pickBit bin 6u = 0u -> parseGroup6 ctxt bin - | 0b00u -> parseGroup7 ctxt bin + | 0b00u when pickBit bin 6u = 0u -> parseGroup6 itstate bin + | 0b00u -> parseGroup7 itstate bin | 0b01u -> parseGroup8 bin | 0b10u | 0b11u -> parseGroup9 bin | _ -> failwith "Wrong thumb group specified." opcode, cond, 0uy, wback, q, dt, operands, None -let parseV7Thumb32Group10 ctxt cond bin = +let parseV7Thumb32Group10 itstate cond bin = let opcode, cond, q, operands, cflag = match pickBit bin 9u, pickBit bin 31u with | 0b0u, 0b0u -> parseGroup10 cond bin @@ -2847,18 +2847,18 @@ let parseV7Thumb32Group10 ctxt cond bin = let opc, c, qual, opr = parseGroup11 cond bin opc, c, qual, opr, None | _, 0b1u -> - let opc, c, qual, opr = parseGroup12 ctxt cond bin + let opc, c, qual, opr = parseGroup12 itstate cond bin opc, c, qual, opr, None | _ -> failwith "Wrong thumb group specified." opcode, cond, 0uy, None, q, None, operands, cflag -let parseV7Thumb32Group11 ctxt cond bin = +let parseV7Thumb32Group11 itstate cond bin = let opcode, wback, q, dt, operands = match extract bin 10u 4u with | op when op &&& 0b1110001u = 0b0000000u -> parseGroup13 bin | op when op &&& 0b1100111u = 0b0000001u -> parseGroup14 bin | op when op &&& 0b1100111u = 0b0000011u -> parseGroup15 bin - | op when op &&& 0b1100111u = 0b0000101u -> parseGroup16 ctxt bin + | op when op &&& 0b1100111u = 0b0000101u -> parseGroup16 itstate bin | op when op &&& 0b1100111u = 0b0000111u -> raise UndefinedException | op when op &&& 0b1110001u = 0b0010000u -> parseGroup17 bin | op when op &&& 0b1110000u = 0b0100000u -> parseGroup18 bin @@ -2868,63 +2868,62 @@ let parseV7Thumb32Group11 ctxt cond bin = | _ -> failwith "Wrong thumb group specified." opcode, cond, 0uy, wback, q, dt, operands, None -let inline updateITSTATE (ctxt: ParsingContext) = - ParsingContext.InitThumb (ctxt.ArchOperationMode, List.tail ctxt.ITState) +let inline updateITSTATE (itstate: byref) = + itstate <- List.tail itstate -let getCondWithITSTATE (ctxt: ParsingContext) = - match List.tryHead ctxt.ITState with +let getCondWithITSTATE itstate = + match List.tryHead itstate with | Some st -> st |> parseCond |> Some | None -> Condition.AL |> Some /// ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition, DDI0406C.b -let parseV7Thumb32 (ctxt: ParsingContext) bin = - let isInITBlock = not ctxt.ITState.IsEmpty - let cond = getCondWithITSTATE ctxt +let parseV7Thumb32 (itstate: byref) bin = + let isInITBlock = not itstate.IsEmpty + let cond = getCondWithITSTATE itstate let opcode, cond, itState, wback, qualifier, simdt, oprs, cflag = match extract bin 12u 11u with - | 0b01u -> parseV7Thumb32Group01 ctxt cond bin - | 0b10u -> parseV7Thumb32Group10 ctxt cond bin - | 0b11u -> parseV7Thumb32Group11 ctxt cond bin + | 0b01u -> parseV7Thumb32Group01 itstate cond bin + | 0b10u -> parseV7Thumb32Group10 itstate cond bin + | 0b11u -> parseV7Thumb32Group11 itstate cond bin | _ -> failwith "Wrong thumb group specified." - opcode, cond, itState, wback, qualifier, simdt, oprs, cflag, - if isInITBlock then updateITSTATE ctxt else ctxt + if isInITBlock then updateITSTATE &itstate else () + opcode, cond, itState, wback, qualifier, simdt, oprs, cflag /// ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition, DDI0406C.b -let parseV7Thumb16 (ctxt: ParsingContext) bin = - let isInITBlock = not ctxt.ITState.IsEmpty - let cond = getCondWithITSTATE ctxt - let opcode, cond, itState, wback, qualifier, operands, ctxt = +let parseV7Thumb16 (itstate: byref) bin = + let isInITBlock = not itstate.IsEmpty + let cond = getCondWithITSTATE itstate + let opcode, cond, itState, wback, qualifier, operands = match extract bin 15u 11u with - | op when op &&& 0b11000u = 0b00000u -> parseGroup0 ctxt cond bin - | 0b01000u when pickBit bin 10u = 0b0u -> parseGroup1 ctxt cond bin - | 0b01000u -> parseGroup2 ctxt cond bin + | op when op &&& 0b11000u = 0b00000u -> parseGroup0 itstate cond bin + | 0b01000u when pickBit bin 10u = 0b0u -> parseGroup1 itstate cond bin + | 0b01000u -> parseGroup2 itstate cond bin | 0b01001u -> let oprs = p2Oprs bin dummyChk (getRegJ, getLbl8A) - Op.LDR, cond, 0uy, None, None, oprs, ctxt - | op when op &&& 0b11110u = 0b01010u -> parseGroup3 ctxt cond bin - | op when op &&& 0b11100u = 0b01100u -> parseGroup3 ctxt cond bin - | op when op &&& 0b11100u = 0b10000u -> parseGroup3 ctxt cond bin + Op.LDR, cond, 0uy, None, None, oprs + | op when op &&& 0b11110u = 0b01010u -> parseGroup3 cond bin + | op when op &&& 0b11100u = 0b01100u -> parseGroup3 cond bin + | op when op &&& 0b11100u = 0b10000u -> parseGroup3 cond bin | 0b10100u -> - Op.ADR, cond, 0uy, None, None, - p2Oprs bin dummyChk (getRegJ, getLbl8A), ctxt + Op.ADR, cond, 0uy, None, None, p2Oprs bin dummyChk (getRegJ, getLbl8A) | 0b10101u -> Op.ADD, cond, 0uy, None, None, - p3Oprs bin dummyChk (getRegJ, getRegSP, getImm8B), ctxt - | op when op &&& 0b11110u = 0b10110u -> parseGroup4 ctxt cond bin + p3Oprs bin dummyChk (getRegJ, getRegSP, getImm8B) + | op when op &&& 0b11110u = 0b10110u -> parseGroup4 &itstate cond bin | 0b11000u -> Op.STM, cond, 0uy, Some true, None, - p2Oprs bin chkUnpreDD (getRegisterWC, getRegListR), ctxt + p2Oprs bin chkUnpreDD (getRegisterWC, getRegListR) | 0b11001u -> let registers = concat 0b00000000u (extract bin 7u 0u) 8 let n = extract bin 10u 8u let wback = pickBit registers n = 0u |> Some Op.LDM, cond, 0uy, wback, None, - p2Oprs bin chkUnpreDD (getRegisterWD, getRegListR), ctxt - | op when op &&& 0b11110u = 0b11010u -> parseGroup5 ctxt cond bin + p2Oprs bin chkUnpreDD (getRegisterWD, getRegListR) + | op when op &&& 0b11110u = 0b11010u -> parseGroup5 itstate cond bin | 0b11100u -> - Op.B, cond, 0uy, None, getQfN (), p1Opr bin dummyChk getLbl12A, ctxt + Op.B, cond, 0uy, None, getQfN (), p1Opr bin dummyChk getLbl12A | _ -> failwith "Wrong thumb group specified." - opcode, cond, itState, wback, qualifier, None, operands, None, - if isInITBlock then updateITSTATE ctxt else ctxt + if isInITBlock then updateITSTATE &itstate else () + opcode, cond, itState, wback, qualifier, None, operands, None // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/ARM32/ARM32ParserV8.fs b/src/FrontEnd/BinLifter/ARM32/ARM32ParserV8.fs similarity index 99% rename from src/FrontEnd/ARM32/ARM32ParserV8.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32ParserV8.fs index 9acabd22..92ccce2b 100644 --- a/src/FrontEnd/ARM32/ARM32ParserV8.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32ParserV8.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.ARM32.Parserv8 +module internal B2R2.FrontEnd.BinLifter.ARM32.Parserv8 -open B2R2.FrontEnd.ARM32.ParseUtils -open B2R2.FrontEnd.ARM32.OperandHelper +open B2R2.FrontEnd.BinLifter.ARM32.ParseUtils +open B2R2.FrontEnd.BinLifter.ARM32.OperandHelper let getRegDCAOprsWithUnpreA bin = p3Oprs bin chkUnpreA (getRegD, getRegC, getRegA) @@ -992,7 +992,7 @@ let parseGroup110v8 cond bin = opcode, None, operands /// ARM Architecture Reference Manual ARMv8-A ARM DDI 0487A.k -let parseV8A32ARM ctxt bin = +let parseV8A32ARM bin = let op = concat (extract bin 27u 25u) (pickBit bin 4u) 1 let cond = extract bin 31u 28u |> byte |> parseCond let opcode, SIMDTyp, operands = @@ -1007,6 +1007,6 @@ let parseV8A32ARM ctxt bin = | op when op &&& 0b1110u = 0b1100u -> parseGroup110v8 cond bin | op when op &&& 0b1110u = 0b1110u -> raise UnallocatedException | _ -> failwith "Wrong group specified." - opcode, Some cond, 0uy, None, None, SIMDTyp, operands, None, ctxt + opcode, Some cond, 0uy, None, None, SIMDTyp, operands, None // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/ARM32/ARM32RegExprs.fs b/src/FrontEnd/BinLifter/ARM32/ARM32RegExprs.fs similarity index 79% rename from src/FrontEnd/ARM32/ARM32RegExprs.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32RegExprs.fs index 5d95266f..8c203af0 100644 --- a/src/FrontEnd/ARM32/ARM32RegExprs.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32RegExprs.fs @@ -22,11 +22,10 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM32 +namespace B2R2.FrontEnd.BinLifter.ARM32 open B2R2 open B2R2.BinIR.LowUIR -open B2R2.BinIR.LowUIR.AST type internal RegExprs () = let var sz t name = AST.var sz t name (ARM32RegisterSet.singleton t) @@ -48,71 +47,71 @@ type internal RegExprs () = let q14 = var 128 (Register.toRegID Register.Q14) "Q14" let q15 = var 128 (Register.toRegID Register.Q15) "Q15" - let d0 = extractLow 64 q0 - let d1 = extractHigh 64 q0 - let d2 = extractLow 64 q1 - let d3 = extractHigh 64 q1 - let d4 = extractLow 64 q2 - let d5 = extractHigh 64 q2 - let d6 = extractLow 64 q3 - let d7 = extractHigh 64 q3 - let d8 = extractLow 64 q4 - let d9 = extractHigh 64 q4 - let d10 = extractLow 64 q5 - let d11 = extractHigh 64 q5 - let d12 = extractLow 64 q6 - let d13 = extractHigh 64 q6 - let d14 = extractLow 64 q7 - let d15 = extractHigh 64 q7 - let d16 = extractLow 64 q8 - let d17 = extractHigh 64 q8 - let d18 = extractLow 64 q9 - let d19 = extractHigh 64 q9 - let d20 = extractLow 64 q10 - let d21 = extractHigh 64 q10 - let d22 = extractLow 64 q11 - let d23 = extractHigh 64 q11 - let d24 = extractLow 64 q12 - let d25 = extractHigh 64 q12 - let d26 = extractLow 64 q13 - let d27 = extractHigh 64 q13 - let d28 = extractLow 64 q14 - let d29 = extractHigh 64 q14 - let d30 = extractLow 64 q15 - let d31 = extractHigh 64 q15 + let d0 = AST.xtlo 64 q0 + let d1 = AST.xthi 64 q0 + let d2 = AST.xtlo 64 q1 + let d3 = AST.xthi 64 q1 + let d4 = AST.xtlo 64 q2 + let d5 = AST.xthi 64 q2 + let d6 = AST.xtlo 64 q3 + let d7 = AST.xthi 64 q3 + let d8 = AST.xtlo 64 q4 + let d9 = AST.xthi 64 q4 + let d10 = AST.xtlo 64 q5 + let d11 = AST.xthi 64 q5 + let d12 = AST.xtlo 64 q6 + let d13 = AST.xthi 64 q6 + let d14 = AST.xtlo 64 q7 + let d15 = AST.xthi 64 q7 + let d16 = AST.xtlo 64 q8 + let d17 = AST.xthi 64 q8 + let d18 = AST.xtlo 64 q9 + let d19 = AST.xthi 64 q9 + let d20 = AST.xtlo 64 q10 + let d21 = AST.xthi 64 q10 + let d22 = AST.xtlo 64 q11 + let d23 = AST.xthi 64 q11 + let d24 = AST.xtlo 64 q12 + let d25 = AST.xthi 64 q12 + let d26 = AST.xtlo 64 q13 + let d27 = AST.xthi 64 q13 + let d28 = AST.xtlo 64 q14 + let d29 = AST.xthi 64 q14 + let d30 = AST.xtlo 64 q15 + let d31 = AST.xthi 64 q15 - let s0 = extractLow 32 d0 - let s1 = extractHigh 32 d0 - let s2 = extractLow 32 d1 - let s3 = extractHigh 32 d1 - let s4 = extractLow 32 d2 - let s5 = extractHigh 32 d2 - let s6 = extractLow 32 d3 - let s7 = extractHigh 32 d3 - let s8 = extractLow 32 d4 - let s9 = extractHigh 32 d4 - let s10 = extractLow 32 d5 - let s11 = extractHigh 32 d5 - let s12 = extractLow 32 d6 - let s13 = extractHigh 32 d6 - let s14 = extractLow 32 d7 - let s15 = extractHigh 32 d7 - let s16 = extractLow 32 d8 - let s17 = extractHigh 32 d8 - let s18 = extractLow 32 d9 - let s19 = extractHigh 32 d9 - let s20 = extractLow 32 d10 - let s21 = extractHigh 32 d10 - let s22 = extractLow 32 d11 - let s23 = extractHigh 32 d11 - let s24 = extractLow 32 d12 - let s25 = extractHigh 32 d12 - let s26 = extractLow 32 d13 - let s27 = extractHigh 32 d13 - let s28 = extractLow 32 d14 - let s29 = extractHigh 32 d14 - let s30 = extractLow 32 d15 - let s31 = extractHigh 32 d15 + let s0 = AST.xtlo 32 d0 + let s1 = AST.xthi 32 d0 + let s2 = AST.xtlo 32 d1 + let s3 = AST.xthi 32 d1 + let s4 = AST.xtlo 32 d2 + let s5 = AST.xthi 32 d2 + let s6 = AST.xtlo 32 d3 + let s7 = AST.xthi 32 d3 + let s8 = AST.xtlo 32 d4 + let s9 = AST.xthi 32 d4 + let s10 = AST.xtlo 32 d5 + let s11 = AST.xthi 32 d5 + let s12 = AST.xtlo 32 d6 + let s13 = AST.xthi 32 d6 + let s14 = AST.xtlo 32 d7 + let s15 = AST.xthi 32 d7 + let s16 = AST.xtlo 32 d8 + let s17 = AST.xthi 32 d8 + let s18 = AST.xtlo 32 d9 + let s19 = AST.xthi 32 d9 + let s20 = AST.xtlo 32 d10 + let s21 = AST.xthi 32 d10 + let s22 = AST.xtlo 32 d11 + let s23 = AST.xthi 32 d11 + let s24 = AST.xtlo 32 d12 + let s25 = AST.xthi 32 d12 + let s26 = AST.xtlo 32 d13 + let s27 = AST.xthi 32 d13 + let s28 = AST.xtlo 32 d14 + let s29 = AST.xthi 32 d14 + let s30 = AST.xtlo 32 d15 + let s31 = AST.xthi 32 d15 member val R0 = var 32 (Register.toRegID Register.R0) "R0" with get member val R1 = var 32 (Register.toRegID Register.R1) "R1" with get @@ -214,7 +213,7 @@ type internal RegExprs () = member val S31 = s31 with get (* Program counters *) - member val PC = pcVar 32 "PC" with get + member val PC = AST.pcvar 32 "PC" with get (*Program Status Register*) member val APSR = var 32 (Register.toRegID Register.APSR) "APSR" with get @@ -339,6 +338,6 @@ type internal RegExprs () = | R.SCTLR -> __.SCTLR | R.NSACR -> __.NSACR | R.FPSCR -> __.FPSCR - | _ -> raise B2R2.FrontEnd.UnhandledRegExprException + | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/ARM32/ARM32Register.fs b/src/FrontEnd/BinLifter/ARM32/ARM32Register.fs similarity index 99% rename from src/FrontEnd/ARM32/ARM32Register.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32Register.fs index c5f332ea..2d9752be 100644 --- a/src/FrontEnd/ARM32/ARM32Register.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32Register.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM32 +namespace B2R2.FrontEnd.BinLifter.ARM32 open B2R2 diff --git a/src/FrontEnd/ARM32/ARM32RegisterBay.fs b/src/FrontEnd/BinLifter/ARM32/ARM32RegisterBay.fs similarity index 96% rename from src/FrontEnd/ARM32/ARM32RegisterBay.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32RegisterBay.fs index 7901411b..7823bc69 100644 --- a/src/FrontEnd/ARM32/ARM32RegisterBay.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32RegisterBay.fs @@ -22,17 +22,15 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM32 +namespace B2R2.FrontEnd.BinLifter.ARM32 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type ARM32RegisterBay () = +type ARM32RegisterBay internal (R: RegExprs) = inherit RegisterBay () - let R = RegExprs () - override __.GetAllRegExprs () = [ R.R0; R.R1; R.R2 ; R.R3; R.R4; R.R5; R.R6; R.R7; R.R8; R.SB; R.SL; R.FP; R.IP; R.SP; R.LR; R.Q0; R.Q1; R.Q2; R.Q3; R.Q4; R.Q5; R.Q6; R.Q7; R.Q8; @@ -54,11 +52,14 @@ type ARM32RegisterBay () = R.IP; R.SP; R.LR; R.PC; R.APSR; R.SPSR; R.CPSR ] override __.RegIDFromRegExpr (e) = - match e with + match e.E with | Var (_, id, _ ,_) -> id | PCVar (_, _) -> Register.toRegID Register.PC | _ -> failwith "not a register expression" + override __.RegIDToRegExpr (id) = + Register.ofRegID id |> R.GetRegVar + override __.StrToRegExpr s = match s with | "R0" -> R.R0 diff --git a/src/FrontEnd/ARM32/ARM32RegisterSet.fs b/src/FrontEnd/BinLifter/ARM32/ARM32RegisterSet.fs similarity index 64% rename from src/FrontEnd/ARM32/ARM32RegisterSet.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32RegisterSet.fs index 728630a5..22b46136 100644 --- a/src/FrontEnd/ARM32/ARM32RegisterSet.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32RegisterSet.fs @@ -22,25 +22,28 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM32 +namespace B2R2.FrontEnd.BinLifter.ARM32 open B2R2 +module private RegisterSetLiteral = + let [] arrLen = 1 + +open RegisterSetLiteral + type ARM32RegisterSet (bitArray: uint64 [], s: Set) = inherit NonEmptyRegisterSet (bitArray, s) - static let defaultSize = 1 - static let emptyArr = Array.init defaultSize (fun _ -> 0UL) - static member EmptySet = - new ARM32RegisterSet (emptyArr, Set.empty) :> RegisterSet + new () = ARM32RegisterSet (RegisterSet.MakeInternalBitArray arrLen, Set.empty) override __.Tag = RegisterSetTag.ARM32 - override __.ArrSize = defaultSize + + override __.ArrSize = arrLen + override __.New x s = new ARM32RegisterSet (x, s) :> RegisterSet - override __.Empty = ARM32RegisterSet.EmptySet - override __.EmptyArr = emptyArr - override __.Project x = - match Register.ofRegID x with + + override __.RegIDToIndex rid = + match Register.ofRegID rid with | R.Q0 -> 0 | R.Q1 -> 1 | R.Q2 -> 2 @@ -81,10 +84,53 @@ type ARM32RegisterSet (bitArray: uint64 [], s: Set) = | R.NSACR -> 37 | _ -> -1 + override __.IndexToRegID index = + match index with + | 0 -> R.Q0 + | 1 -> R.Q1 + | 2 -> R.Q2 + | 3 -> R.Q3 + | 4 -> R.Q4 + | 5 -> R.Q5 + | 6 -> R.Q6 + | 7 -> R.Q7 + | 8 -> R.Q8 + | 9 -> R.Q9 + | 10 -> R.Q10 + | 11 -> R.Q11 + | 12 -> R.Q12 + | 13 -> R.Q13 + | 14 -> R.Q14 + | 15 -> R.Q15 + | 16 -> R.R0 + | 17 -> R.R1 + | 18 -> R.R2 + | 19 -> R.R3 + | 20 -> R.R4 + | 21 -> R.R5 + | 22 -> R.R6 + | 23 -> R.R7 + | 24 -> R.R8 + | 25 -> R.SB + | 26 -> R.SL + | 27 -> R.FP + | 28 -> R.IP + | 29 -> R.SP + | 30 -> R.LR + | 31 -> R.APSR + | 32 -> R.SPSR + | 33 -> R.CPSR + | 34 -> R.FPSCR + | 35 -> R.SCTLR + | 36 -> R.SCR + | 37 -> R.NSACR + | _ -> Utils.impossible () + |> Register.toRegID + override __.ToString () = sprintf "ARM32RegisterSet<%x>" __.BitArray.[0] [] module ARM32RegisterSet = - let singleton = RegisterSetBuilder.singletonBuilder ARM32RegisterSet.EmptySet - let empty = ARM32RegisterSet.EmptySet + let singleton rid = ARM32RegisterSet().Add(rid) + let empty = ARM32RegisterSet () :> RegisterSet diff --git a/src/FrontEnd/ARM32/ARM32SupportedOpcode.txt b/src/FrontEnd/BinLifter/ARM32/ARM32SupportedOpcode.txt similarity index 100% rename from src/FrontEnd/ARM32/ARM32SupportedOpcode.txt rename to src/FrontEnd/BinLifter/ARM32/ARM32SupportedOpcode.txt diff --git a/src/FrontEnd/ARM32/ARM32Types.fs b/src/FrontEnd/BinLifter/ARM32/ARM32Types.fs similarity index 99% rename from src/FrontEnd/ARM32/ARM32Types.fs rename to src/FrontEnd/BinLifter/ARM32/ARM32Types.fs index 1e87c3da..8c3def56 100644 --- a/src/FrontEnd/ARM32/ARM32Types.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32Types.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM32 +namespace B2R2.FrontEnd.BinLifter.ARM32 open B2R2 open System.Runtime.CompilerServices -[] +[] do () /// diff --git a/src/FrontEnd/ARM32/B2R2.FrontEnd.ARM32.fsproj b/src/FrontEnd/BinLifter/ARM32/B2R2.FrontEnd.BinLifter.ARM32.fsproj similarity index 52% rename from src/FrontEnd/ARM32/B2R2.FrontEnd.ARM32.fsproj rename to src/FrontEnd/BinLifter/ARM32/B2R2.FrontEnd.BinLifter.ARM32.fsproj index f915b347..a1b17847 100644 --- a/src/FrontEnd/ARM32/B2R2.FrontEnd.ARM32.fsproj +++ b/src/FrontEnd/BinLifter/ARM32/B2R2.FrontEnd.BinLifter.ARM32.fsproj @@ -1,9 +1,11 @@ - + - netstandard2.1 - false - false + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 ARM32 frontend. @@ -21,16 +23,17 @@ - + + + - - - - + + + diff --git a/src/FrontEnd/BinLifter/ARM32/README.md b/src/FrontEnd/BinLifter/ARM32/README.md new file mode 100644 index 00000000..cfdfe5eb --- /dev/null +++ b/src/FrontEnd/BinLifter/ARM32/README.md @@ -0,0 +1,11 @@ +# B2R2.FrontEnd.BinLifter.ARM32 + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.BinLifter.ARM32 Package? + +`B2R2.FrontEnd.BinLifter.ARM32` includes ARMv7 parsers and lifters. diff --git a/src/FrontEnd/ARM64/ARM64.fs b/src/FrontEnd/BinLifter/ARM64/ARM64.fs similarity index 76% rename from src/FrontEnd/ARM64/ARM64.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64.fs index 65da5d4a..5bd0c242 100644 --- a/src/FrontEnd/ARM64/ARM64.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64.fs @@ -22,15 +22,16 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM64 +namespace B2R2.FrontEnd.BinLifter.ARM64 -open B2R2.FrontEnd +open B2R2 +open B2R2.FrontEnd.BinLifter /// Translation context for 64-bit ARM instructions. -type ARM64TranslationContext (isa) = +type ARM64TranslationContext internal (isa, regexprs) = inherit TranslationContext (isa) /// Register expressions. - member val private RegExprs : RegExprs = RegExprs () + member val private RegExprs: RegExprs = regexprs override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar override __.GetPseudoRegVar _id _pos = failwith "Implement" @@ -38,7 +39,17 @@ type ARM64TranslationContext (isa) = /// instruction type (Instruction). type ARM64Parser () = inherit Parser () - override __.Parse binReader _ctxt addr pos = + override __.Parse binReader addr pos = Parser.parse binReader addr pos :> Instruction + override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () + +module Basis = + let init isa = + let regexprs = RegExprs () + struct ( + ARM64TranslationContext (isa, regexprs) :> TranslationContext, + ARM64RegisterBay (regexprs) :> RegisterBay + ) + // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/ARM64/ARM64Disasm.fs b/src/FrontEnd/BinLifter/ARM64/ARM64Disasm.fs similarity index 72% rename from src/FrontEnd/ARM64/ARM64Disasm.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64Disasm.fs index 68f744b7..fb998b61 100644 --- a/src/FrontEnd/ARM64/ARM64Disasm.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64Disasm.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.ARM64.Disasm +module internal B2R2.FrontEnd.BinLifter.ARM64.Disasm open B2R2 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter let condToString = function | Some EQ -> "eq" @@ -551,90 +551,91 @@ let simdVectorToString = function | TwoD -> "2d" | OneQ -> "1q" -let simdFPRegToString simdOpr builder acc = +let simdFPRegToString simdOpr (builder: DisasmBuilder<_>) = match simdOpr with | SIMDFPScalarReg sReg -> - builder AsmWordKind.Variable (Register.toString sReg) acc + builder.Accumulate AsmWordKind.Variable (Register.toString sReg) | SIMDVecReg (reg, vec) -> - builder AsmWordKind.Variable (Register.toString reg) acc - |> builder AsmWordKind.String ("." + simdVectorToString vec) + builder.Accumulate AsmWordKind.Variable (Register.toString reg) + builder.Accumulate AsmWordKind.String ("." + simdVectorToString vec) | SIMDVecRegWithIdx (reg, vec, _) -> - builder AsmWordKind.Variable (Register.toString reg) acc - |> builder AsmWordKind.String ("." + simdVectorToString vec) + builder.Accumulate AsmWordKind.Variable (Register.toString reg) + builder.Accumulate AsmWordKind.String ("." + simdVectorToString vec) -let finalSIMDOpr s builder acc = +let finalSIMDOpr s (builder: DisasmBuilder<_>) = match s with | SIMDVecRegWithIdx (_, _, idx) -> - builder AsmWordKind.String "[" acc - |> builder AsmWordKind.String (string idx) - |> builder AsmWordKind.String "]" - | _ -> acc + builder.Accumulate AsmWordKind.String "[" + builder.Accumulate AsmWordKind.String (string idx) + builder.Accumulate AsmWordKind.String "]" + | _ -> () -let simdToString simdOprs builder acc = +let simdToString simdOprs builder = match simdOprs with (* SIMD & FP register *) - | SFReg s -> simdFPRegToString s builder acc |> finalSIMDOpr s builder + | SFReg s -> + simdFPRegToString s builder + finalSIMDOpr s builder (* SIMD vector register list or SIMD vector element list *) | OneReg s -> - builder AsmWordKind.String "{ " acc - |> simdFPRegToString s builder - |> builder AsmWordKind.String " }" - |> finalSIMDOpr s builder + builder.Accumulate AsmWordKind.String "{ " + simdFPRegToString s builder + builder.Accumulate AsmWordKind.String " }" + finalSIMDOpr s builder | TwoRegs (s1, s2) -> - builder AsmWordKind.String "{ " acc - |> simdFPRegToString s1 builder - |> builder AsmWordKind.String ", " - |> simdFPRegToString s2 builder - |> builder AsmWordKind.String " }" - |> finalSIMDOpr s1 builder + builder.Accumulate AsmWordKind.String "{ " + simdFPRegToString s1 builder + builder.Accumulate AsmWordKind.String ", " + simdFPRegToString s2 builder + builder.Accumulate AsmWordKind.String " }" + finalSIMDOpr s1 builder | ThreeRegs (s1, s2, s3) -> - builder AsmWordKind.String "{ " acc - |> simdFPRegToString s1 builder - |> builder AsmWordKind.String ", " - |> simdFPRegToString s2 builder - |> builder AsmWordKind.String ", " - |> simdFPRegToString s3 builder - |> builder AsmWordKind.String " }" - |> finalSIMDOpr s1 builder + builder.Accumulate AsmWordKind.String "{ " + simdFPRegToString s1 builder + builder.Accumulate AsmWordKind.String ", " + simdFPRegToString s2 builder + builder.Accumulate AsmWordKind.String ", " + simdFPRegToString s3 builder + builder.Accumulate AsmWordKind.String " }" + finalSIMDOpr s1 builder | FourRegs (s1, _, _, s4) -> - builder AsmWordKind.String "{ " acc - |> simdFPRegToString s1 builder - |> builder AsmWordKind.String " - " - |> simdFPRegToString s4 builder - |> builder AsmWordKind.String " }" - |> finalSIMDOpr s1 builder - -let immToString (imm: int64) builder acc = - builder AsmWordKind.String "#" acc - |> builder AsmWordKind.String ("0x" + imm.ToString "X") - -let fpImmToString (fp: float) builder acc = - builder AsmWordKind.String "#" acc - |> builder AsmWordKind.String (fp.ToString ("N8")) - -let nzcvToString (imm: uint8) builder acc = - builder AsmWordKind.String "#" acc - |> builder AsmWordKind.String ("0x" + imm.ToString "X") - -let amountToString amount builder acc = + builder.Accumulate AsmWordKind.String "{ " + simdFPRegToString s1 builder + builder.Accumulate AsmWordKind.String " - " + simdFPRegToString s4 builder + builder.Accumulate AsmWordKind.String " }" + finalSIMDOpr s1 builder + +let immToString imm (builder: DisasmBuilder<_>) = + builder.Accumulate AsmWordKind.String "#" + builder.Accumulate AsmWordKind.String (String.i64ToHex imm) + +let fpImmToString (fp: float) (builder: DisasmBuilder<_>) = + builder.Accumulate AsmWordKind.String "#" + builder.Accumulate AsmWordKind.String (fp.ToString ("N8")) + +let nzcvToString (imm: uint8) (builder: DisasmBuilder<_>) = + builder.Accumulate AsmWordKind.String "#" + builder.Accumulate AsmWordKind.String ("0x" + imm.ToString "x") + +let amountToString amount builder = match amount with - | Imm i -> immToString i builder acc - | Reg r -> builder AsmWordKind.Variable (Register.toString r) acc + | Imm i -> immToString i builder + | Reg r -> builder.Accumulate AsmWordKind.Variable (Register.toString r) -let prependDelimiter delimiter builder acc = +let prependDelimiter delimiter (builder: DisasmBuilder<_>) = match delimiter with - | None -> acc - | Some delim -> - builder AsmWordKind.String delim acc + | None -> () + | Some delim -> builder.Accumulate AsmWordKind.String delim -let shiftToString shift delim builder acc = +let shiftToString shift delim builder = match shift with - | _, Imm 0L -> acc + | _, Imm 0L -> () | s, amount -> - prependDelimiter delim builder acc - |> builder AsmWordKind.String (srtypeToString s) - |> builder AsmWordKind.String " " - |> amountToString amount builder + prependDelimiter delim builder + builder.Accumulate AsmWordKind.String (srtypeToString s) + builder.Accumulate AsmWordKind.String " " + amountToString amount builder let extToString = function | ExtUXTB -> "uxtb" @@ -646,22 +647,22 @@ let extToString = function | ExtSXTW -> "sxtw" | ExtSXTX -> "sxtx" -let extRegToString regOff delim builder acc = +let extRegToString regOff delim builder = match regOff with | (ext, None) | (ext, Some 0L) -> - prependDelimiter delim builder acc - |> builder AsmWordKind.String (extToString ext) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.String (extToString ext) | (ext, Some i) -> - prependDelimiter delim builder acc - |> builder AsmWordKind.String (extToString ext) - |> builder AsmWordKind.String " #" - |> builder AsmWordKind.Value (i.ToString ("X")) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.String (extToString ext) + builder.Accumulate AsmWordKind.String " #" + builder.Accumulate AsmWordKind.Value (i.ToString ("x")) -let regOffString regOff delim builder acc = +let regOffString regOff delim builder = match regOff with - | ShiftOffset regOff -> shiftToString regOff delim builder acc - | ExtRegOffset regOff -> extRegToString regOff delim builder acc + | ShiftOffset regOff -> shiftToString regOff delim builder + | ExtRegOffset regOff -> extRegToString regOff delim builder let delimPostIdx = function | PostIdxMode _ -> "], " @@ -672,52 +673,52 @@ let processAddrExn64 ins addr = | Opcode.ADRP -> addr &&& 0xFFFFFFFFFFFFF000UL | _ -> addr -let immOffsetToString i addr mode offset builder acc = +let immOffsetToString i addr mode offset (builder: DisasmBuilder<_>) = match offset with | BaseOffset (reg, None) | BaseOffset (reg, Some 0L) -> - builder AsmWordKind.Variable (Register.toString reg) acc + builder.Accumulate AsmWordKind.Variable (Register.toString reg) | BaseOffset (reg, Some imm) -> - builder AsmWordKind.Variable (Register.toString reg) acc - |> builder AsmWordKind.String (delimPostIdx mode) - |> immToString imm builder + builder.Accumulate AsmWordKind.Variable (Register.toString reg) + builder.Accumulate AsmWordKind.String (delimPostIdx mode) + immToString imm builder | Lbl imm -> let addr = processAddrExn64 i addr - builder AsmWordKind.Value ("0x" + (int64 addr + imm).ToString ("X")) acc + builder.Accumulate AsmWordKind.Value (String.i64ToHex (int64 addr + imm)) -let regOffsetToString mode offset builder acc = +let regOffsetToString mode offset (builder: DisasmBuilder<_>) = match offset with | r1, r2, Some regOff -> - builder AsmWordKind.Variable (Register.toString r1) acc - |> builder AsmWordKind.String ", " - |> builder AsmWordKind.Variable (Register.toString r2) - |> regOffString regOff (Some ", ") builder + builder.Accumulate AsmWordKind.Variable (Register.toString r1) + builder.Accumulate AsmWordKind.String ", " + builder.Accumulate AsmWordKind.Variable (Register.toString r2) + regOffString regOff (Some ", ") builder | r1, r2, None -> - builder AsmWordKind.Variable (Register.toString r1) acc - |> builder AsmWordKind.String (delimPostIdx mode) - |> builder AsmWordKind.Variable (Register.toString r2) + builder.Accumulate AsmWordKind.Variable (Register.toString r1) + builder.Accumulate AsmWordKind.String (delimPostIdx mode) + builder.Accumulate AsmWordKind.Variable (Register.toString r2) -let postBracket mode builder acc = +let postBracket mode (builder: DisasmBuilder<_>) = match mode with - | BaseMode _ -> builder AsmWordKind.String "]" acc - | PreIdxMode _ -> builder AsmWordKind.String "]!" acc - | _ -> acc + | BaseMode _ -> builder.Accumulate AsmWordKind.String "]" + | PreIdxMode _ -> builder.Accumulate AsmWordKind.String "]!" + | _ -> () -let offsetToString i addr mode offset builder acc = +let offsetToString i addr mode offset builder = match offset with | ImmOffset offset -> - immOffsetToString i addr mode offset builder acc - |> postBracket mode builder + immOffsetToString i addr mode offset builder + postBracket mode builder | RegOffset (r1, r2, offset) -> - regOffsetToString mode (r1, r2, offset) builder acc - |> postBracket mode builder + regOffsetToString mode (r1, r2, offset) builder + postBracket mode builder -let memToString insInfo addr mode builder acc = +let memToString insInfo addr mode builder = match mode with | LiteralMode offset -> - offsetToString insInfo addr mode offset builder acc + offsetToString insInfo addr mode offset builder | BaseMode off | PreIdxMode off | PostIdxMode off -> - builder AsmWordKind.String "[" acc - |> offsetToString insInfo addr mode off builder + builder.Accumulate AsmWordKind.String "[" + offsetToString insInfo addr mode off builder let optToString = function | SY -> "sy" @@ -782,77 +783,82 @@ let dcOprToString = function let sysOprToString = function | DCOpr dc -> dcOprToString dc -let oprToString i addr opr delim builder acc = +let oprToString i addr opr delim builder = match opr with - | OprRegister reg when isRET i && reg = R.X30 -> acc + | OprRegister reg when isRET i && reg = R.X30 -> () | OprRegister reg -> - prependDelimiter delim builder acc - |> builder AsmWordKind.Variable (Register.toString reg) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.Variable (Register.toString reg) | SIMDOpr simdOpr -> - prependDelimiter delim builder acc |> simdToString simdOpr builder + prependDelimiter delim builder + simdToString simdOpr builder | Immediate imm -> - prependDelimiter delim builder acc |> immToString imm builder + prependDelimiter delim builder + immToString imm builder | FPImmediate fp -> - prependDelimiter delim builder acc |> fpImmToString fp builder + prependDelimiter delim builder + fpImmToString fp builder | NZCV ui8 -> - prependDelimiter delim builder acc |> nzcvToString ui8 builder - | Shift s -> shiftToString s delim builder acc - | ExtReg None -> acc - | ExtReg (Some regOffset) -> regOffString regOffset delim builder acc + prependDelimiter delim builder + nzcvToString ui8 builder + | Shift s -> shiftToString s delim builder + | ExtReg None -> () + | ExtReg (Some regOffset) -> regOffString regOffset delim builder | Memory mode -> - prependDelimiter delim builder acc |> memToString i addr mode builder + prependDelimiter delim builder + memToString i addr mode builder | Option opt -> - prependDelimiter delim builder acc - |> builder AsmWordKind.Variable (optToString opt) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.Variable (optToString opt) | Pstate p -> - prependDelimiter delim builder acc - |> builder AsmWordKind.Variable (pStToString p) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.Variable (pStToString p) | PrfOp e1 -> - prependDelimiter delim builder acc - |> builder AsmWordKind.Variable (prfOpToString e1) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.Variable (prfOpToString e1) | Cond c -> - prependDelimiter delim builder acc - |> builder AsmWordKind.Variable (condToString (Some c)) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.Variable (condToString (Some c)) | Fbits ui8 -> - prependDelimiter delim builder acc - |> builder AsmWordKind.Variable (fBitsToString ui8) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.Variable (fBitsToString ui8) | LSB ui8 -> - prependDelimiter delim builder acc - |> builder AsmWordKind.Variable (lsbToString ui8) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.Variable (lsbToString ui8) | SysOpr sys -> - prependDelimiter delim builder acc - |> builder AsmWordKind.Variable (sysOprToString sys) + prependDelimiter delim builder + builder.Accumulate AsmWordKind.Variable (sysOprToString sys) -let inline buildOpcode ins builder acc = +let inline buildOpcode ins (builder: DisasmBuilder<_>) = let opcode = opCodeToString ins.Opcode + condToString ins.Condition - builder AsmWordKind.Mnemonic opcode acc + builder.Accumulate AsmWordKind.Mnemonic opcode -let buildOprs insInfo pc builder acc = +let buildOprs insInfo pc builder = match insInfo.Operands with - | NoOperand -> acc + | NoOperand -> () | OneOperand opr -> - oprToString insInfo pc opr (Some " ") builder acc + oprToString insInfo pc opr (Some " ") builder | TwoOperands (opr1, opr2) -> - oprToString insInfo pc opr1 (Some " ") builder acc - |> oprToString insInfo pc opr2 (Some ", ") builder + oprToString insInfo pc opr1 (Some " ") builder + oprToString insInfo pc opr2 (Some ", ") builder | ThreeOperands (opr1, opr2, opr3) -> - oprToString insInfo pc opr1 (Some " ") builder acc - |> oprToString insInfo pc opr2 (Some ", ") builder - |> oprToString insInfo pc opr3 (Some ", ") builder + oprToString insInfo pc opr1 (Some " ") builder + oprToString insInfo pc opr2 (Some ", ") builder + oprToString insInfo pc opr3 (Some ", ") builder | FourOperands (opr1, opr2, opr3, opr4) -> - oprToString insInfo pc opr1 (Some " ") builder acc - |> oprToString insInfo pc opr2 (Some ", ") builder - |> oprToString insInfo pc opr3 (Some ", ") builder - |> oprToString insInfo pc opr4 (Some ", ") builder + oprToString insInfo pc opr1 (Some " ") builder + oprToString insInfo pc opr2 (Some ", ") builder + oprToString insInfo pc opr3 (Some ", ") builder + oprToString insInfo pc opr4 (Some ", ") builder | FiveOperands (opr1, opr2, opr3, opr4, opr5) -> - oprToString insInfo pc opr1 (Some " ") builder acc - |> oprToString insInfo pc opr2 (Some ", ") builder - |> oprToString insInfo pc opr3 (Some ", ") builder - |> oprToString insInfo pc opr4 (Some ", ") builder - |> oprToString insInfo pc opr5 (Some ", ") builder + oprToString insInfo pc opr1 (Some " ") builder + oprToString insInfo pc opr2 (Some ", ") builder + oprToString insInfo pc opr3 (Some ", ") builder + oprToString insInfo pc opr4 (Some ", ") builder + oprToString insInfo pc opr5 (Some ", ") builder -let disasm showAddr ins builder acc = +let disasm ins (builder: DisasmBuilder<_>) = let pc = ins.Address - DisasmBuilder.addr pc WordSize.Bit64 showAddr builder acc - |> buildOpcode ins builder - |> buildOprs ins pc builder + if builder.ShowAddr then builder.AccumulateAddr () else () + buildOpcode ins builder + buildOprs ins pc builder diff --git a/src/FrontEnd/ARM64/ARM64Exceptions.fs b/src/FrontEnd/BinLifter/ARM64/ARM64Exceptions.fs similarity index 97% rename from src/FrontEnd/ARM64/ARM64Exceptions.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64Exceptions.fs index 4fb102aa..25db2911 100644 --- a/src/FrontEnd/ARM64/ARM64Exceptions.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64Exceptions.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM64 +namespace B2R2.FrontEnd.BinLifter.ARM64 /// This is a fatal error that happens when B2R2 tries to access non-existing /// register symbol. This exception should not happen in general. diff --git a/src/FrontEnd/ARM64/ARM64Instruction.fs b/src/FrontEnd/BinLifter/ARM64/ARM64Instruction.fs similarity index 63% rename from src/FrontEnd/ARM64/ARM64Instruction.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64Instruction.fs index 294c278a..a9ff1e2a 100644 --- a/src/FrontEnd/ARM64/ARM64Instruction.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64Instruction.fs @@ -22,26 +22,19 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM64 +namespace B2R2.FrontEnd.BinLifter.ARM64 open B2R2 -open B2R2.FrontEnd -open System.Text +open B2R2.FrontEnd.BinLifter /// The internal representation for an ARM64 instruction used by our /// disassembler and lifter. type ARM64Instruction (addr, numBytes, insInfo, wordSize) = inherit Instruction (addr, numBytes, wordSize) - let defaultCtxt = ParsingContext.Init () - /// Basic instruction information. member val Info: InsInfo = insInfo - override __.NextParsingContext with get() = defaultCtxt - - override __.AuxParsingContext with get() = None - override __.IsBranch () = match __.Info.Opcode with (* Conditional branch *) @@ -56,6 +49,8 @@ type ARM64Instruction (addr, numBytes, insInfo, wordSize) = -> true | _ -> false + override __.IsModeChanging () = false + member __.HasConcJmpTarget () = match __.Info.Operands with | OneOperand (Memory (LiteralMode _)) -> true @@ -90,28 +85,59 @@ type ARM64Instruction (addr, numBytes, insInfo, wordSize) = override __.IsRET () = __.Info.Opcode = Opcode.RET - override __.IsInterrupt () = Utils.futureFeature () + override __.IsInterrupt () = + match __.Info.Opcode with + | Opcode.SVC | Opcode.HVC | Opcode.SMC -> true + | _ -> false + + override __.IsExit () = Utils.futureFeature () - override __.IsExit () = // FIXME + override __.IsBBLEnd () = // FIXME __.IsDirectBranch () || - __.IsIndirectBranch () + __.IsIndirectBranch () || + __.IsInterrupt () override __.DirectBranchTarget (addr: byref) = if __.IsBranch () then match __.Info.Operands with | OneOperand (Memory (LiteralMode (ImmOffset (Lbl offset)))) -> - addr <- (int64 __.Address + offset) |> uint64 + addr <- (__.Address + uint64 offset) + true + | TwoOperands (_, Memory (LiteralMode (ImmOffset (Lbl offset)))) -> + addr <- (__.Address + uint64 offset) + true + | ThreeOperands (_, _, Memory (LiteralMode (ImmOffset (Lbl offset)))) -> + addr <- (__.Address + uint64 offset) true | _ -> false else false - override __.IndirectTrampolineAddr (addr: byref) = + override __.IndirectTrampolineAddr (_addr: byref) = if __.IsBranch () then Utils.futureFeature () else false + override __.Immediate (v: byref) = + match __.Info.Operands with + | OneOperand (Immediate c) + | TwoOperands (Immediate c, _) + | TwoOperands (_, Immediate c) + | ThreeOperands (Immediate c, _, _) + | ThreeOperands (_, Immediate c, _) + | ThreeOperands (_, _, Immediate c) + | FourOperands (Immediate c, _, _, _) + | FourOperands (_, Immediate c, _, _) + | FourOperands (_, _, Immediate c, _) + | FourOperands (_, _, _, Immediate c) + | FiveOperands (Immediate c, _, _, _, _) + | FiveOperands (_, Immediate c, _, _, _) + | FiveOperands (_, _, Immediate c, _, _) + | FiveOperands (_, _, _, Immediate c, _) + | FiveOperands (_, _, _, _, Immediate c) -> v <- c; true + | _ -> false + override __.GetNextInstrAddrs () = Utils.futureFeature () - override __.InterruptNum (num: byref) = Utils.futureFeature () + override __.InterruptNum (_num: byref) = Utils.futureFeature () override __.IsNop () = __.Info.Opcode = Opcode.NOP @@ -119,25 +145,27 @@ type ARM64Instruction (addr, numBytes, insInfo, wordSize) = override __.Translate ctxt = Lifter.translate __.Info ctxt - member private __.StrBuilder _ (str: string) (acc: StringBuilder) = - acc.Append (str) - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = - let acc = StringBuilder () - let acc = Disasm.disasm showAddr __.Info __.StrBuilder acc - acc.ToString () + let builder = + DisasmStringBuilder (showAddr, false, WordSize.Bit64, addr, numBytes) + Disasm.disasm __.Info builder + builder.Finalize () override __.Disasm () = - let acc = StringBuilder () - let acc = Disasm.disasm false __.Info __.StrBuilder acc - acc.ToString () + let builder = + DisasmStringBuilder (false, false, WordSize.Bit64, addr, numBytes) + Disasm.disasm __.Info builder + builder.Finalize () + + override __.Decompose (showAddr) = + let builder = + DisasmWordBuilder (showAddr, false, WordSize.Bit64, addr, numBytes, 8) + Disasm.disasm __.Info builder + builder.Finalize () - member private __.WordBuilder kind str (acc: AsmWordBuilder) = - acc.Append ({ AsmWordKind = kind; AsmWordValue = str }) + override __.IsInlinedAssembly () = false - override __.Decompose () = - AsmWordBuilder (8) - |> Disasm.disasm true __.Info __.WordBuilder - |> fun b -> b.Finish () + override __.Equals (_) = Utils.futureFeature () + override __.GetHashCode () = Utils.futureFeature () // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/ARM64/ARM64Lifter.fs b/src/FrontEnd/BinLifter/ARM64/ARM64Lifter.fs similarity index 61% rename from src/FrontEnd/ARM64/ARM64Lifter.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64Lifter.fs index 878e932f..595b5630 100644 --- a/src/FrontEnd/ARM64/ARM64Lifter.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64Lifter.fs @@ -22,14 +22,14 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.ARM64.Lifter +module internal B2R2.FrontEnd.BinLifter.ARM64.Lifter open B2R2 open B2R2.BinIR open B2R2.BinIR.LowUIR -open B2R2.BinIR.LowUIR.AST -open B2R2.FrontEnd -open B2R2.FrontEnd.ARM64 +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.ARM64 let inline getRegVar (ctxt: TranslationContext) name = Register.toRegID name |> ctxt.GetRegVar @@ -38,12 +38,12 @@ let getPC ctxt = getRegVar ctxt R.PC let ror src amount width = (src >> amount) .| (src << (width .- amount)) -let numI32 n t = BitVector.ofInt32 n t |> num // FIXME: exists in IntelLifter -let numI64 n t = BitVector.ofInt64 n t |> num +let numI32 n t = BitVector.ofInt32 n t |> AST.num // FIXME: exists in IntelLifter +let numI64 n t = BitVector.ofInt64 n t |> AST.num let oprSzToExpr oprSize = numI32 (RegType.toBitWidth oprSize) oprSize -let inline private ( result - let z = relop RelOpType.EQ result (num0 oSz) - let c = gt opr1 result - let o1 = extractHigh 1 opr1 - let o2 = extractHigh 1 opr2 - let r = extractHigh 1 result + let n = AST.xthi 1 result + let z = AST.relop RelOpType.EQ result (AST.num0 oSz) + let c = AST.gt opr1 result + let o1 = AST.xthi 1 opr1 + let o2 = AST.xthi 1 opr2 + let r = AST.xthi 1 result let v = (o1 == o2) .& (o1 <+> r) result, (n, z, c, v) @@ -79,7 +79,7 @@ let transShiftAmout ctxt oprSize = function // Extend() // ======== let extend reg oprSize isUnsigned = - if isUnsigned then zExt oprSize reg else sExt oprSize reg + if isUnsigned then AST.zext oprSize reg else AST.sext oprSize reg // aarch64/instrs/extendreg/ExtendReg // ExtendReg() @@ -102,7 +102,7 @@ let extendReg ctxt reg typ shift oprSize = | ExtUXTX -> true, 64 let len = min len ((RegType.toBitWidth oprSize) - shift) let rTyp = RegType.fromBitWidth len - extend ((extractLow rTyp reg) << numI32 shift rTyp) oprSize isUnsigned + extend ((AST.xtlo rTyp reg) << numI32 shift rTyp) oprSize isUnsigned let transSIMDRegToExpr ctxt = function | SIMDFPScalarReg reg -> getRegVar ctxt reg @@ -139,7 +139,7 @@ let transMemOffset ins ctxt addr = function transRegOffset ins ctxt (bReg, reg, regOffset) let transBaseMode ins ctxt addr offset = - transMemOffset ins ctxt addr offset |> loadLE 64 + transMemOffset ins ctxt addr offset |> AST.loadLE 64 let transMem ins ctxt addr = function | BaseMode offset -> transBaseMode ins ctxt addr offset @@ -151,9 +151,9 @@ let transOprToExpr ins ctxt addr = function | OprRegister reg -> getRegVar ctxt reg | Memory mem -> transMem ins ctxt addr mem | SIMDOpr simd -> transSIMD ctxt simd - | Immediate imm -> num <| BitVector.ofInt64 imm ins.OprSize - | NZCV nzcv -> num <| BitVector.ofInt64 (int64 nzcv) ins.OprSize - | LSB lsb -> num <| BitVector.ofInt64 (int64 lsb) ins.OprSize + | Immediate imm -> AST.num <| BitVector.ofInt64 imm ins.OprSize + | NZCV nzcv -> AST.num <| BitVector.ofInt64 (int64 nzcv) ins.OprSize + | LSB lsb -> AST.num <| BitVector.ofInt64 (int64 lsb) ins.OprSize | _ -> raise <| NotImplementedIRException "transOprToExpr" let transOneOpr ins ctxt addr = @@ -239,26 +239,26 @@ let getSIMDReg = function | _ -> raise <| NotImplementedIRException "getSIMDReg" | _ -> failwith "Invalid SIMD operand" -let transOprToExprOfADD ins ctxt addr (builder: StmtBuilder) = +let transOprToExprOfADD ins ctxt addr (ir: IRBuilder) = match ins.Operands with | ThreeOperands (o1, _, _) -> (* SIMD arithmetic *) let oSz = ins.OprSize let dst, s1, s2 = transThreeOprs ins ctxt addr let eNum, eSz = getElemNumAndSize oSz (getSIMDReg o1) - let s1Tmps = Array.init (int eNum) (fun _ -> tmpVar eSz) - let s2Tmps = Array.init (int eNum) (fun _ -> tmpVar eSz) - let resTmps = Array.init (int eNum) (fun _ -> tmpVar eSz) + let s1Tmps = Array.init (int eNum) (fun _ -> ir.NewTempVar eSz) + let s2Tmps = Array.init (int eNum) (fun _ -> ir.NewTempVar eSz) + let resTmps = Array.init (int eNum) (fun _ -> ir.NewTempVar eSz) let amt = RegType.toBitWidth eSz for i in 0 .. (int eNum) - 1 do - builder (* Arithmetic *) let dst, s1, s2 = transFourOprsWithBarrelShift ins ctxt addr - let result, _ = addWithCarry s1 s2 (num0 ins.OprSize) ins.OprSize - builder raise InvalidOperandException let transOprToExprOfADDS ins ctxt addr = @@ -426,10 +426,10 @@ let getIsWBackAndIsPostIndex = function let separateMemExpr expr = let getExpr = function - | Load (e, t, expr, _, _) -> expr + | Load (e, t, expr, _) -> expr.E | _ -> failwith "None" - match getExpr expr with - | BinOp (BinOpType.ADD, _, b, o, _, _) -> b, o + match getExpr expr.E with + | BinOp (BinOpType.ADD, _, b, o, _) -> b, o | _ -> failwith "None" let transOprToExprOfLDP ins ctxt addr = @@ -440,28 +440,28 @@ let transOprToExprOfLDP ins ctxt addr = transOprToExpr ins ctxt addr o3 |> separateMemExpr | _ -> raise InvalidOperandException -let transOprToExprOfLDR ins ctxt addr (builder: StmtBuilder) = +let transOprToExprOfLDR ins ctxt addr (ir: IRBuilder) = match ins.Operands with | TwoOperands (o1, Memory (LiteralMode o2)) -> (* LDR (literal) *) let dst = transOprToExpr ins ctxt addr o1 let offset = transOprToExpr ins ctxt addr (Memory (LiteralMode o2)) - let address = tmpVar 64 - let data = tmpVar ins.OprSize - builder + let data = ir.NewTempVar ins.OprSize + ir let dst = transOprToExpr ins ctxt addr o1 let bReg, offset = transOprToExpr ins ctxt addr o2 |> separateMemExpr let isWBack, isPostIndex = getIsWBackAndIsPostIndex ins.Operands - let address = tmpVar 64 - let data = tmpVar ins.OprSize - builder + let data = ir.NewTempVar ins.OprSize + ir raise InvalidOperandException let transOprToExprOfMADD ins ctxt addr = @@ -499,8 +499,9 @@ let transOprToExprOfORR ins ctxt addr = transBarrelShiftToExpr ins ctxt o3 o4 | _ -> raise InvalidOperandException -let unwrapReg = function - | Extract (e, 32, 0, _, _) -> e +let unwrapReg e = + match e.E with + | Extract (e, 32, 0, _) -> e | _ -> failwith "Invalid register" let transOprToExprOfSBFM ins ctxt addr = @@ -508,7 +509,7 @@ let transOprToExprOfSBFM ins ctxt addr = | TwoOperands (o1, o2) -> (* SXTW *) transOprToExpr ins ctxt addr o1, transOprToExpr ins ctxt addr o2 |> unwrapReg, - num0 ins.OprSize, + AST.num0 ins.OprSize, numI32 32 ins.OprSize | FourOperands (o1, o2, o3, Immediate o4) when ins.Opcode = Opcode.SBFIZ -> transOprToExpr ins ctxt addr o1, @@ -570,21 +571,21 @@ let transOprToExprOfSTUR ins ctxt addr = transOprToExpr ins ctxt addr o2 |> separateMemExpr | _ -> raise InvalidOperandException -let transOprToExprOfSUB ins ctxt addr builder = +let transOprToExprOfSUB ins ctxt addr ir = let oprSize = ins.OprSize match ins.Operands with | ThreeOperands (o1, o2, o3) -> (* NEG: Arithmetic *) let dst = transOprToExpr ins ctxt addr o1 let s1 = getRegVar ctxt (if oprSize = 64 then R.XZR else R.WZR) - let s2 = transBarrelShiftToExpr ins ctxt o2 o3 |> not - let result, _ = addWithCarry s1 s2 (num1 oprSize) oprSize - builder AST.not + let result, _ = addWithCarry s1 s2 (AST.num1 oprSize) oprSize + ir (* Arithmetic *) let dst = transOprToExpr ins ctxt addr o1 let s1 = transOprToExpr ins ctxt addr o2 - let s2 = transBarrelShiftToExpr ins ctxt o3 o4 |> not - let result, _ = addWithCarry s1 s2 (num1 oprSize) oprSize - builder AST.not + let result, _ = addWithCarry s1 s2 (AST.num1 oprSize) oprSize + ir raise InvalidOperandException let transOprToExprOfUMADDL ins ctxt addr = @@ -597,19 +598,19 @@ let transOprToExprOfUMADDL ins ctxt addr = | FourOperands (_, _, _, _) -> transFourOprs ins ctxt addr | _ -> raise InvalidOperandException -let transOprToExprOfSUBS ins ctxt addr builder = +let transOprToExprOfSUBS ins ctxt addr ir = let oprSize = ins.OprSize match ins.Operands with | FourOperands (o1, o2, o3, o4) -> let dst = transOprToExpr ins ctxt addr o1 let s1 = transOprToExpr ins ctxt addr o2 - let s2 = transBarrelShiftToExpr ins ctxt o3 o4 |> not - let result, (n, z, c, v) = addWithCarry s1 s2 (num1 oprSize) oprSize - builder AST.not + let result, (n, z, c, v) = addWithCarry s1 s2 (AST.num1 oprSize) oprSize + ir raise InvalidOperandException let transOprToExprOfUBFM ins ctxt addr = @@ -673,739 +674,740 @@ type BranchType = // Set program counter to a new address, which may include a tag in the top // eight bits, with a branch reason hint for possible use by hardware fetching // the next instruction. -let branchTo ins ctxt target brType i (builder: StmtBuilder) = - builder getRegVar ctxt R.Z == b1 - | NE -> getRegVar ctxt R.Z == b0 - | CS -> getRegVar ctxt R.C == b1 - | CC -> getRegVar ctxt R.C == b0 - | MI -> getRegVar ctxt R.N == b1 - | PL -> getRegVar ctxt R.N == b0 - | VS -> getRegVar ctxt R.V == b1 - | VC -> getRegVar ctxt R.V == b0 - | HI -> (getRegVar ctxt R.C == b1) .& (getRegVar ctxt R.Z == b0) - | LS -> not ((getRegVar ctxt R.C == b1) .& (getRegVar ctxt R.Z == b0)) + | EQ -> getRegVar ctxt R.Z == AST.b1 + | NE -> getRegVar ctxt R.Z == AST.b0 + | CS -> getRegVar ctxt R.C == AST.b1 + | CC -> getRegVar ctxt R.C == AST.b0 + | MI -> getRegVar ctxt R.N == AST.b1 + | PL -> getRegVar ctxt R.N == AST.b0 + | VS -> getRegVar ctxt R.V == AST.b1 + | VC -> getRegVar ctxt R.V == AST.b0 + | HI -> (getRegVar ctxt R.C == AST.b1) .& (getRegVar ctxt R.Z == AST.b0) + | LS -> AST.not ((getRegVar ctxt R.C == AST.b1) .& (getRegVar ctxt R.Z == AST.b0)) | GE -> getRegVar ctxt R.N == getRegVar ctxt R.V | LT -> getRegVar ctxt R.N != getRegVar ctxt R.V | GT -> (getRegVar ctxt R.N == getRegVar ctxt R.V) .& - (getRegVar ctxt R.Z == b0) - | LE -> not ((getRegVar ctxt R.N == getRegVar ctxt R.V) .& - (getRegVar ctxt R.Z == b0)) + (getRegVar ctxt R.Z == AST.b0) + | LE -> AST.not ((getRegVar ctxt R.N == getRegVar ctxt R.V) .& + (getRegVar ctxt R.Z == AST.b0)) /// Condition flag values in the set '111x' indicate always true - | AL | NV -> b1 + | AL | NV -> AST.b1 | _ -> failwith "Invalid condition" // shared/functions/common/HighestSetBit // HighestSetBit() // =============== -let highestSetBitForIR dst src width oprSz (builder: StmtBuilder) = - let lblLoop = lblSymbol "Loop" - let lblLoopCont = lblSymbol "LoopContinue" - let lblUpdateTmp = lblSymbol "UpdateTmp" - let lblEnd = lblSymbol "End" - let t = tmpVar oprSz +let highestSetBitForIR dst src width oprSz (ir: IRBuilder) = + let lblLoop = ir.NewSymbol "Loop" + let lblLoopCont = ir.NewSymbol "LoopContinue" + let lblUpdateTmp = ir.NewSymbol "UpdateTmp" + let lblEnd = ir.NewSymbol "End" + let t = ir.NewTempVar oprSz let width = numI32 (width - 1) oprSz - builder > t == num1 oprSz, Name lblEnd, Name lblLoopCont)) - builder > t == AST.num1 oprSz) + (AST.name lblEnd) (AST.name lblLoopCont)) + ir ) .+ lbl) - endMark ins addr builder + startMark ins ir + ir ) .+ lbl) + endMark ins ir let logAnd ins ctxt addr = (* AND *) - let builder = new StmtBuilder (4) + let ir = IRBuilder (4) let dst, src1, src2 = transOprToExprOfAND ins ctxt addr - startMark ins addr builder - builder then num1 oSz else num0 oSz - decodeBitMasksForIR wmask tmask immN imms immr (num0 oSz) oSz builder + let wmask, tmask = ir.NewTempVar oSz, ir.NewTempVar oSz + let immN = if ins.OprSize = 64 then AST.num1 oSz else AST.num0 oSz + decodeBitMasksForIR wmask tmask immN imms immr (AST.num0 oSz) oSz ir let width = oprSzToExpr ins.OprSize - let bot = tmpVar ins.OprSize - startMark ins addr builder - builder - builder 3))) - builder 2))) - builder 1))) - builder nzcv))) - endMark ins addr builder + let tCond = ir.NewTempVar 1 + ir 3))) + ir 2))) + ir 1))) + ir nzcv))) + endMark ins ir let ccmp ins ctxt addr = - let builder = new StmtBuilder (8) + let ir = IRBuilder (8) let src, imm, nzcv, cond = transOprToExprOfCCMP ins ctxt addr - startMark ins addr builder + startMark ins ir let tCond = conditionHolds ctxt cond let oSz = ins.OprSize - let _, (n, z, c, v) = addWithCarry src (not imm) (num1 oSz) oSz - builder 3))) - builder 2))) - builder 1))) - builder nzcv))) - endMark ins addr builder + let _, (n, z, c, v) = addWithCarry src (AST.not imm) (AST.num1 oSz) oSz + ir 3))) + ir 2))) + ir 1))) + ir nzcv))) + endMark ins ir let clz ins ctxt addr = - let builder = new StmtBuilder (16) + let ir = IRBuilder (16) let dst, src = transTwoOprs ins ctxt addr - startMark ins addr builder - countLeadingZeroBitsForIR dst src ins.OprSize builder - endMark ins addr builder + startMark ins ir + countLeadingZeroBitsForIR dst src ins.OprSize ir + endMark ins ir let cmp ins ctxt addr = - let builder = StmtBuilder (8) + let ir = IRBuilder (8) let src, imm = transOprToExprOfCMP ins ctxt addr let oSz = ins.OprSize let dst = getRegVar ctxt (if oSz = 64 then R.XZR else R.WZR) - let opr1 = tmpVar oSz - let opr2 = tmpVar oSz - startMark ins addr builder - let result, (n, z, c, v) = addWithCarry src (not imm) (num1 oSz) oSz - builder src2) - endMark ins addr builder + startMark ins ir + ir src2) + endMark ins ir let extr ins ctxt addr = - let builder = new StmtBuilder (4) + let ir = IRBuilder (4) let dst, src1, src2, lsb = transOprToExprOfEXTR ins ctxt addr let oSz = ins.OprSize let conSize = if oSz = 64 then 128 else 64 - let con = tmpVar conSize - let mask = num (BitVector.ofUBInt (RegType.getMask oSz) conSize) - startMark ins addr builder - builder > (zExt conSize lsb)) .& mask)) - endMark ins addr builder + let con = ir.NewTempVar conSize + let mask = AST.num (BitVector.ofBInt (RegType.getMask oSz) conSize) + startMark ins ir + ir > (AST.zext conSize lsb)) .& mask)) + endMark ins ir let ldp ins ctxt addr = - let builder = new StmtBuilder (8) + let ir = IRBuilder (8) let src1, src2, (bReg, offset) = transOprToExprOfLDP ins ctxt addr let isWBack, isPostIndex = getIsWBackAndIsPostIndex ins.Operands - let address = tmpVar 64 + let address = ir.NewTempVar 64 let dByte = numI32 (RegType.toBitWidth ins.OprSize) 64 - startMark ins addr builder - builder - let data = tmpVar 8 - startMark ins addr builder - builder address) - builder data) - if isWBack && isPostIndex then builder + let data = ir.NewTempVar 8 + startMark ins ir + ir address) + ir data) + if isWBack && isPostIndex then ir - let data = tmpVar 16 - startMark ins addr builder - builder address) - builder data) - if isWBack && isPostIndex then builder + let data = ir.NewTempVar 16 + startMark ins ir + ir address) + ir data) + if isWBack && isPostIndex then ir - let data = tmpVar 32 - startMark ins addr builder - builder address) - builder data) - if isWBack && isPostIndex then builder + let data = ir.NewTempVar 32 + startMark ins ir + ir address) + ir data) + if isWBack && isPostIndex then ir - let data = tmpVar ins.OprSize - startMark ins addr builder - builder + let data = ir.NewTempVar ins.OprSize + startMark ins ir + ir - let data = tmpVar 8 - startMark ins addr builder - builder address) - builder data) - endMark ins addr builder + let address = ir.NewTempVar 64 + let data = ir.NewTempVar 8 + startMark ins ir + ir address) + ir data) + endMark ins ir let lslv ins ctxt addr = - let builder = new StmtBuilder (4) + let ir = IRBuilder (4) let dst, src1, src2 = transThreeOprs ins ctxt addr let oprSz = ins.OprSize let dataSize = numI32 (RegType.toBitWidth ins.OprSize) oprSz - startMark ins addr builder - builder builder builder ir ir failwith "Invalid Move wide Opcode" - endMark ins addr builder + endMark ins ir let mrs ins ctxt addr = - let builder = new StmtBuilder (4) + let ir = IRBuilder (4) let dst, src = transTwoOprs ins ctxt addr - startMark ins addr builder - builder - startMark ins addr builder - builder + startMark ins ir + ir then num1 oprSz else num0 oprSz + let bot, top = ir.NewTempVar oprSz, ir.NewTempVar oprSz + let wmask, tmask = ir.NewTempVar oprSz, ir.NewTempVar oprSz + let immN = if oprSz = 64 then AST.num1 oprSz else AST.num0 oprSz let width = oprSzToExpr oprSz - startMark ins addr builder - decodeBitMasksForIR wmask tmask immN imms immr (num0 oprSz) oprSz builder - builder src1 .* sExt 64 src2)) - endMark ins addr builder + startMark ins ir + ir src1 .* AST.sext 64 src2)) + endMark ins ir let smulh ins ctxt addr = - let builder = new StmtBuilder (4) + let ir = IRBuilder (4) let dst, src1, src2 = transThreeOprs ins ctxt addr - let result = tmpVar 128 - startMark ins addr builder - builder src1 .* sExt 128 src2) - builder result) - endMark ins addr builder + let result = ir.NewTempVar 128 + startMark ins ir + ir src1 .* AST.sext 128 src2) + ir result) + endMark ins ir let stp ins ctxt addr = - let builder = new StmtBuilder (8) + let ir = IRBuilder (8) let src1, src2, (bReg, offset) = transOprToExprOfSTP ins ctxt addr let isWBack, isPostIndex = getIsWBackAndIsPostIndex ins.Operands - let address = tmpVar 64 + let address = ir.NewTempVar 64 let dByte = numI32 (RegType.toBitWidth ins.OprSize) 64 - startMark ins addr builder - builder - let data = tmpVar ins.OprSize - startMark ins addr builder - builder + let data = ir.NewTempVar ins.OprSize + startMark ins ir + ir - let data = tmpVar 8 - startMark ins addr builder - builder src) - builder address := data) - if isWBack && isPostIndex then builder + let data = ir.NewTempVar 8 + startMark ins ir + ir src) + ir address := data) + if isWBack && isPostIndex then ir - let data = tmpVar 16 - startMark ins addr builder - builder src) - builder address := data) - if isWBack && isPostIndex then builder + let data = ir.NewTempVar 16 + startMark ins ir + ir src) + ir address := data) + if isWBack && isPostIndex then ir - let data = tmpVar ins.OprSize - startMark ins addr builder - builder + let data = ir.NewTempVar ins.OprSize + startMark ins ir + ir - let data = tmpVar 8 - startMark ins addr builder - builder src) - builder address := data) - endMark ins addr builder + let address = ir.NewTempVar 64 + let data = ir.NewTempVar 8 + startMark ins ir + ir src) + ir address := data) + endMark ins ir let sturh ins ctxt addr = - let builder = new StmtBuilder (8) + let ir = IRBuilder (8) let src, (bReg, offset) = transOprToExprOfSTUR ins ctxt addr - let address = tmpVar 64 - let data = tmpVar 16 - startMark ins addr builder - builder src) - builder address := data) - endMark ins addr builder + let address = ir.NewTempVar 64 + let data = ir.NewTempVar 16 + startMark ins ir + ir src) + ir address := data) + endMark ins ir let sub ins ctxt addr = - let builder = new StmtBuilder (8) - startMark ins addr builder - transOprToExprOfSUB ins ctxt addr builder - endMark ins addr builder + let ir = IRBuilder (8) + startMark ins ir + transOprToExprOfSUB ins ctxt addr ir + endMark ins ir let subs ins ctxt addr = - let builder = new StmtBuilder (8) - startMark ins addr builder - transOprToExprOfSUBS ins ctxt addr builder - endMark ins addr builder + let ir = IRBuilder (8) + startMark ins ir + transOprToExprOfSUBS ins ctxt addr ir + endMark ins ir let tbnz ins ctxt addr = - let builder = new StmtBuilder (4) + let ir = IRBuilder (4) let test, imm, label = transThreeOprs ins ctxt addr let pc = getPC ctxt - let cond = (test >> imm .& num1 ins.OprSize) == num1 ins.OprSize - startMark ins addr builder - builder > imm .& AST.num1 ins.OprSize) == AST.num1 ins.OprSize + startMark ins ir + ir > imm .& num1 ins.OprSize) == num0 ins.OprSize - startMark ins addr builder - builder > imm .& AST.num1 ins.OprSize) == AST.num0 ins.OprSize + startMark ins ir + ir src1 .* zExt 64 src2)) - endMark ins addr builder + startMark ins ir + ir src1 .* AST.zext 64 src2)) + endMark ins ir let umulh ins ctxt addr = - let builder = new StmtBuilder (4) + let ir = IRBuilder (4) let dst, src1, src2 = transThreeOprs ins ctxt addr - let result = tmpVar 128 - startMark ins addr builder - builder src1 .* zExt 128 src2) - builder result) - endMark ins addr builder + let result = ir.NewTempVar 128 + startMark ins ir + ir src1 .* AST.zext 128 src2) + ir result) + endMark ins ir let ubfm ins ctxt addr = - let builder = new StmtBuilder (64) + let ir = IRBuilder (64) let dst, src, immr, imms = transOprToExprOfUBFM ins ctxt addr let oSz = ins.OprSize - let bot = tmpVar oSz - let wmask, tmask = tmpVar oSz, tmpVar oSz - let immN = if ins.OprSize = 64 then num1 oSz else num0 oSz - decodeBitMasksForIR wmask tmask immN imms immr (num0 oSz) oSz builder + let bot = ir.NewTempVar oSz + let wmask, tmask = ir.NewTempVar oSz, ir.NewTempVar oSz + let immN = if ins.OprSize = 64 then AST.num1 oSz else AST.num0 oSz + decodeBitMasksForIR wmask tmask immN imms immr (AST.num0 oSz) oSz ir let width = oprSzToExpr ins.OprSize - startMark ins addr builder - builder fun builder -> builder.ToStmts () + |> fun ir -> ir.ToStmts () // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/ARM64/ARM64OperandHelper.fs b/src/FrontEnd/BinLifter/ARM64/ARM64OperandHelper.fs similarity index 99% rename from src/FrontEnd/ARM64/ARM64OperandHelper.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64OperandHelper.fs index ce3e5574..c26429c4 100644 --- a/src/FrontEnd/ARM64/ARM64OperandHelper.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64OperandHelper.fs @@ -22,14 +22,14 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.ARM64.OperandHelper +module internal B2R2.FrontEnd.BinLifter.ARM64.OperandHelper open B2R2 -open B2R2.FrontEnd -open B2R2.FrontEnd.ARM64.Utils +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.ARM64.Utils open System.Runtime.CompilerServices -[] +[] do () let memBaseImm offset = Memory (BaseMode (ImmOffset (BaseOffset offset))) diff --git a/src/FrontEnd/ARM64/ARM64Parser.fs b/src/FrontEnd/BinLifter/ARM64/ARM64Parser.fs similarity index 99% rename from src/FrontEnd/ARM64/ARM64Parser.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64Parser.fs index 9c183991..e6e36a17 100644 --- a/src/FrontEnd/ARM64/ARM64Parser.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64Parser.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module B2R2.FrontEnd.ARM64.Parser +module B2R2.FrontEnd.BinLifter.ARM64.Parser open B2R2 -open B2R2.FrontEnd.ARM64.Utils -open B2R2.FrontEnd.ARM64.OperandHelper +open B2R2.FrontEnd.BinLifter.ARM64.Utils +open B2R2.FrontEnd.BinLifter.ARM64.OperandHelper /// Opcode functions let getOpcodeByQ bin op1 op2 = if valQ bin = 0u then op1 else op2 diff --git a/src/FrontEnd/ARM64/ARM64Parser.fsi b/src/FrontEnd/BinLifter/ARM64/ARM64Parser.fsi similarity index 97% rename from src/FrontEnd/ARM64/ARM64Parser.fsi rename to src/FrontEnd/BinLifter/ARM64/ARM64Parser.fsi index e7baa98a..19e57dfd 100644 --- a/src/FrontEnd/ARM64/ARM64Parser.fsi +++ b/src/FrontEnd/BinLifter/ARM64/ARM64Parser.fsi @@ -23,7 +23,7 @@ *) /// ARMv8 instruction parser. -module B2R2.FrontEnd.ARM64.Parser +module B2R2.FrontEnd.BinLifter.ARM64.Parser open B2R2 diff --git a/src/FrontEnd/ARM64/ARM64RegExprs.fs b/src/FrontEnd/BinLifter/ARM64/ARM64RegExprs.fs similarity index 78% rename from src/FrontEnd/ARM64/ARM64RegExprs.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64RegExprs.fs index 85dca925..9dd0e80c 100644 --- a/src/FrontEnd/ARM64/ARM64RegExprs.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64RegExprs.fs @@ -22,11 +22,10 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM64 +namespace B2R2.FrontEnd.BinLifter.ARM64 open B2R2 open B2R2.BinIR.LowUIR -open B2R2.BinIR.LowUIR.AST type internal RegExprs () = let var sz t name = AST.var sz t name (ARM64RegisterSet.singleton t) @@ -65,41 +64,41 @@ type internal RegExprs () = let r30 = var 64 (Register.toRegID Register.X30) "X30" let xzr = var 64 (Register.toRegID Register.XZR) "XZR" let sp = var 64 (Register.toRegID Register.SP) "SP" - let pc = pcVar 64 "PC" + let pc = AST.pcvar 64 "PC" - let w0 = extractLow 32 r0 - let w1 = extractLow 32 r1 - let w2 = extractLow 32 r2 - let w3 = extractLow 32 r3 - let w4 = extractLow 32 r4 - let w5 = extractLow 32 r5 - let w6 = extractLow 32 r6 - let w7 = extractLow 32 r7 - let w8 = extractLow 32 r8 - let w9 = extractLow 32 r9 - let w10 = extractLow 32 r10 - let w11 = extractLow 32 r11 - let w12 = extractLow 32 r12 - let w13 = extractLow 32 r13 - let w14 = extractLow 32 r14 - let w15 = extractLow 32 r15 - let w16 = extractLow 32 r16 - let w17 = extractLow 32 r17 - let w18 = extractLow 32 r18 - let w19 = extractLow 32 r19 - let w20 = extractLow 32 r20 - let w21 = extractLow 32 r21 - let w22 = extractLow 32 r22 - let w23 = extractLow 32 r23 - let w24 = extractLow 32 r24 - let w25 = extractLow 32 r25 - let w26 = extractLow 32 r26 - let w27 = extractLow 32 r27 - let w28 = extractLow 32 r28 - let w29 = extractLow 32 r29 - let w30 = extractLow 32 r30 - let wzr = extractLow 32 xzr - let wsp = extractLow 32 sp + let w0 = AST.xtlo 32 r0 + let w1 = AST.xtlo 32 r1 + let w2 = AST.xtlo 32 r2 + let w3 = AST.xtlo 32 r3 + let w4 = AST.xtlo 32 r4 + let w5 = AST.xtlo 32 r5 + let w6 = AST.xtlo 32 r6 + let w7 = AST.xtlo 32 r7 + let w8 = AST.xtlo 32 r8 + let w9 = AST.xtlo 32 r9 + let w10 = AST.xtlo 32 r10 + let w11 = AST.xtlo 32 r11 + let w12 = AST.xtlo 32 r12 + let w13 = AST.xtlo 32 r13 + let w14 = AST.xtlo 32 r14 + let w15 = AST.xtlo 32 r15 + let w16 = AST.xtlo 32 r16 + let w17 = AST.xtlo 32 r17 + let w18 = AST.xtlo 32 r18 + let w19 = AST.xtlo 32 r19 + let w20 = AST.xtlo 32 r20 + let w21 = AST.xtlo 32 r21 + let w22 = AST.xtlo 32 r22 + let w23 = AST.xtlo 32 r23 + let w24 = AST.xtlo 32 r24 + let w25 = AST.xtlo 32 r25 + let w26 = AST.xtlo 32 r26 + let w27 = AST.xtlo 32 r27 + let w28 = AST.xtlo 32 r28 + let w29 = AST.xtlo 32 r29 + let w30 = AST.xtlo 32 r30 + let wzr = AST.xtlo 32 xzr + let wsp = AST.xtlo 32 sp let v0 = var 128 (Register.toRegID Register.V0) "V0" let v1 = var 128 (Register.toRegID Register.V1) "V1" @@ -134,137 +133,137 @@ type internal RegExprs () = let v30 = var 128 (Register.toRegID Register.V30) "V30" let v31 = var 128 (Register.toRegID Register.V31) "V31" - let d0 = extractLow 64 v0 - let d1 = extractLow 64 v1 - let d2 = extractLow 64 v2 - let d3 = extractLow 64 v3 - let d4 = extractLow 64 v4 - let d5 = extractLow 64 v5 - let d6 = extractLow 64 v6 - let d7 = extractLow 64 v7 - let d8 = extractLow 64 v8 - let d9 = extractLow 64 v9 - let d10 = extractLow 64 v10 - let d11 = extractLow 64 v11 - let d12 = extractLow 64 v12 - let d13 = extractLow 64 v13 - let d14 = extractLow 64 v14 - let d15 = extractLow 64 v15 - let d16 = extractLow 64 v16 - let d17 = extractLow 64 v17 - let d18 = extractLow 64 v18 - let d19 = extractLow 64 v19 - let d20 = extractLow 64 v20 - let d21 = extractLow 64 v21 - let d22 = extractLow 64 v22 - let d23 = extractLow 64 v23 - let d24 = extractLow 64 v24 - let d25 = extractLow 64 v25 - let d26 = extractLow 64 v26 - let d27 = extractLow 64 v27 - let d28 = extractLow 64 v28 - let d29 = extractLow 64 v29 - let d30 = extractLow 64 v30 - let d31 = extractLow 64 v31 + let d0 = AST.xtlo 64 v0 + let d1 = AST.xtlo 64 v1 + let d2 = AST.xtlo 64 v2 + let d3 = AST.xtlo 64 v3 + let d4 = AST.xtlo 64 v4 + let d5 = AST.xtlo 64 v5 + let d6 = AST.xtlo 64 v6 + let d7 = AST.xtlo 64 v7 + let d8 = AST.xtlo 64 v8 + let d9 = AST.xtlo 64 v9 + let d10 = AST.xtlo 64 v10 + let d11 = AST.xtlo 64 v11 + let d12 = AST.xtlo 64 v12 + let d13 = AST.xtlo 64 v13 + let d14 = AST.xtlo 64 v14 + let d15 = AST.xtlo 64 v15 + let d16 = AST.xtlo 64 v16 + let d17 = AST.xtlo 64 v17 + let d18 = AST.xtlo 64 v18 + let d19 = AST.xtlo 64 v19 + let d20 = AST.xtlo 64 v20 + let d21 = AST.xtlo 64 v21 + let d22 = AST.xtlo 64 v22 + let d23 = AST.xtlo 64 v23 + let d24 = AST.xtlo 64 v24 + let d25 = AST.xtlo 64 v25 + let d26 = AST.xtlo 64 v26 + let d27 = AST.xtlo 64 v27 + let d28 = AST.xtlo 64 v28 + let d29 = AST.xtlo 64 v29 + let d30 = AST.xtlo 64 v30 + let d31 = AST.xtlo 64 v31 - let s0 = extractLow 32 v0 - let s1 = extractLow 32 v1 - let s2 = extractLow 32 v2 - let s3 = extractLow 32 v3 - let s4 = extractLow 32 v4 - let s5 = extractLow 32 v5 - let s6 = extractLow 32 v6 - let s7 = extractLow 32 v7 - let s8 = extractLow 32 v8 - let s9 = extractLow 32 v9 - let s10 = extractLow 32 v10 - let s11 = extractLow 32 v11 - let s12 = extractLow 32 v12 - let s13 = extractLow 32 v13 - let s14 = extractLow 32 v14 - let s15 = extractLow 32 v15 - let s16 = extractLow 32 v16 - let s17 = extractLow 32 v17 - let s18 = extractLow 32 v18 - let s19 = extractLow 32 v19 - let s20 = extractLow 32 v20 - let s21 = extractLow 32 v21 - let s22 = extractLow 32 v22 - let s23 = extractLow 32 v23 - let s24 = extractLow 32 v24 - let s25 = extractLow 32 v25 - let s26 = extractLow 32 v26 - let s27 = extractLow 32 v27 - let s28 = extractLow 32 v28 - let s29 = extractLow 32 v29 - let s30 = extractLow 32 v30 - let s31 = extractLow 32 v31 + let s0 = AST.xtlo 32 v0 + let s1 = AST.xtlo 32 v1 + let s2 = AST.xtlo 32 v2 + let s3 = AST.xtlo 32 v3 + let s4 = AST.xtlo 32 v4 + let s5 = AST.xtlo 32 v5 + let s6 = AST.xtlo 32 v6 + let s7 = AST.xtlo 32 v7 + let s8 = AST.xtlo 32 v8 + let s9 = AST.xtlo 32 v9 + let s10 = AST.xtlo 32 v10 + let s11 = AST.xtlo 32 v11 + let s12 = AST.xtlo 32 v12 + let s13 = AST.xtlo 32 v13 + let s14 = AST.xtlo 32 v14 + let s15 = AST.xtlo 32 v15 + let s16 = AST.xtlo 32 v16 + let s17 = AST.xtlo 32 v17 + let s18 = AST.xtlo 32 v18 + let s19 = AST.xtlo 32 v19 + let s20 = AST.xtlo 32 v20 + let s21 = AST.xtlo 32 v21 + let s22 = AST.xtlo 32 v22 + let s23 = AST.xtlo 32 v23 + let s24 = AST.xtlo 32 v24 + let s25 = AST.xtlo 32 v25 + let s26 = AST.xtlo 32 v26 + let s27 = AST.xtlo 32 v27 + let s28 = AST.xtlo 32 v28 + let s29 = AST.xtlo 32 v29 + let s30 = AST.xtlo 32 v30 + let s31 = AST.xtlo 32 v31 - let h0 = extractLow 16 v0 - let h1 = extractLow 16 v1 - let h2 = extractLow 16 v2 - let h3 = extractLow 16 v3 - let h4 = extractLow 16 v4 - let h5 = extractLow 16 v5 - let h6 = extractLow 16 v6 - let h7 = extractLow 16 v7 - let h8 = extractLow 16 v8 - let h9 = extractLow 16 v9 - let h10 = extractLow 16 v10 - let h11 = extractLow 16 v11 - let h12 = extractLow 16 v12 - let h13 = extractLow 16 v13 - let h14 = extractLow 16 v14 - let h15 = extractLow 16 v15 - let h16 = extractLow 16 v16 - let h17 = extractLow 16 v17 - let h18 = extractLow 16 v18 - let h19 = extractLow 16 v19 - let h20 = extractLow 16 v20 - let h21 = extractLow 16 v21 - let h22 = extractLow 16 v22 - let h23 = extractLow 16 v23 - let h24 = extractLow 16 v24 - let h25 = extractLow 16 v25 - let h26 = extractLow 16 v26 - let h27 = extractLow 16 v27 - let h28 = extractLow 16 v28 - let h29 = extractLow 16 v29 - let h30 = extractLow 16 v30 - let h31 = extractLow 16 v31 + let h0 = AST.xtlo 16 v0 + let h1 = AST.xtlo 16 v1 + let h2 = AST.xtlo 16 v2 + let h3 = AST.xtlo 16 v3 + let h4 = AST.xtlo 16 v4 + let h5 = AST.xtlo 16 v5 + let h6 = AST.xtlo 16 v6 + let h7 = AST.xtlo 16 v7 + let h8 = AST.xtlo 16 v8 + let h9 = AST.xtlo 16 v9 + let h10 = AST.xtlo 16 v10 + let h11 = AST.xtlo 16 v11 + let h12 = AST.xtlo 16 v12 + let h13 = AST.xtlo 16 v13 + let h14 = AST.xtlo 16 v14 + let h15 = AST.xtlo 16 v15 + let h16 = AST.xtlo 16 v16 + let h17 = AST.xtlo 16 v17 + let h18 = AST.xtlo 16 v18 + let h19 = AST.xtlo 16 v19 + let h20 = AST.xtlo 16 v20 + let h21 = AST.xtlo 16 v21 + let h22 = AST.xtlo 16 v22 + let h23 = AST.xtlo 16 v23 + let h24 = AST.xtlo 16 v24 + let h25 = AST.xtlo 16 v25 + let h26 = AST.xtlo 16 v26 + let h27 = AST.xtlo 16 v27 + let h28 = AST.xtlo 16 v28 + let h29 = AST.xtlo 16 v29 + let h30 = AST.xtlo 16 v30 + let h31 = AST.xtlo 16 v31 - let b0 = extractLow 8 v0 - let b1 = extractLow 8 v1 - let b2 = extractLow 8 v2 - let b3 = extractLow 8 v3 - let b4 = extractLow 8 v4 - let b5 = extractLow 8 v5 - let b6 = extractLow 8 v6 - let b7 = extractLow 8 v7 - let b8 = extractLow 8 v8 - let b9 = extractLow 8 v9 - let b10 = extractLow 8 v10 - let b11 = extractLow 8 v11 - let b12 = extractLow 8 v12 - let b13 = extractLow 8 v13 - let b14 = extractLow 8 v14 - let b15 = extractLow 8 v15 - let b16 = extractLow 8 v16 - let b17 = extractLow 8 v17 - let b18 = extractLow 8 v18 - let b19 = extractLow 8 v19 - let b20 = extractLow 8 v20 - let b21 = extractLow 8 v21 - let b22 = extractLow 8 v22 - let b23 = extractLow 8 v23 - let b24 = extractLow 8 v24 - let b25 = extractLow 8 v25 - let b26 = extractLow 8 v26 - let b27 = extractLow 8 v27 - let b28 = extractLow 8 v28 - let b29 = extractLow 8 v29 - let b30 = extractLow 8 v30 - let b31 = extractLow 8 v31 + let b0 = AST.xtlo 8 v0 + let b1 = AST.xtlo 8 v1 + let b2 = AST.xtlo 8 v2 + let b3 = AST.xtlo 8 v3 + let b4 = AST.xtlo 8 v4 + let b5 = AST.xtlo 8 v5 + let b6 = AST.xtlo 8 v6 + let b7 = AST.xtlo 8 v7 + let b8 = AST.xtlo 8 v8 + let b9 = AST.xtlo 8 v9 + let b10 = AST.xtlo 8 v10 + let b11 = AST.xtlo 8 v11 + let b12 = AST.xtlo 8 v12 + let b13 = AST.xtlo 8 v13 + let b14 = AST.xtlo 8 v14 + let b15 = AST.xtlo 8 v15 + let b16 = AST.xtlo 8 v16 + let b17 = AST.xtlo 8 v17 + let b18 = AST.xtlo 8 v18 + let b19 = AST.xtlo 8 v19 + let b20 = AST.xtlo 8 v20 + let b21 = AST.xtlo 8 v21 + let b22 = AST.xtlo 8 v22 + let b23 = AST.xtlo 8 v23 + let b24 = AST.xtlo 8 v24 + let b25 = AST.xtlo 8 v25 + let b26 = AST.xtlo 8 v26 + let b27 = AST.xtlo 8 v27 + let b28 = AST.xtlo 8 v28 + let b29 = AST.xtlo 8 v29 + let b30 = AST.xtlo 8 v30 + let b31 = AST.xtlo 8 v31 (* General-purpose registers *) member val X0 = r0 with get @@ -825,6 +824,6 @@ type internal RegExprs () = | R.Z -> __.Z | R.C -> __.C | R.V -> __.V - | _ -> raise B2R2.FrontEnd.UnhandledRegExprException + | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/ARM64/ARM64Register.fs b/src/FrontEnd/BinLifter/ARM64/ARM64Register.fs similarity index 99% rename from src/FrontEnd/ARM64/ARM64Register.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64Register.fs index 6ae57a55..56037888 100644 --- a/src/FrontEnd/ARM64/ARM64Register.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64Register.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM64 +namespace B2R2.FrontEnd.BinLifter.ARM64 open B2R2 diff --git a/src/FrontEnd/ARM64/ARM64RegisterBay.fs b/src/FrontEnd/BinLifter/ARM64/ARM64RegisterBay.fs similarity index 97% rename from src/FrontEnd/ARM64/ARM64RegisterBay.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64RegisterBay.fs index ebcefe83..b7436127 100644 --- a/src/FrontEnd/ARM64/ARM64RegisterBay.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64RegisterBay.fs @@ -22,17 +22,15 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM64 +namespace B2R2.FrontEnd.BinLifter.ARM64 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type ARM64RegisterBay () = +type ARM64RegisterBay internal (R: RegExprs) = inherit RegisterBay () - let R = RegExprs () - override __.GetAllRegExprs () = [ R.X0; R.X1; R.X2; R.X3; R.X4; R.X5; R.X6; R.X7; R.X8; R.X9; R.X10; R.X11; R.X12; R.X13; R.X14; R.X15; R.X16; R.X17; R.X18; R.X19; R.X20; R.X21; @@ -72,11 +70,14 @@ type ARM64RegisterBay () = R.N; R.Z; R.C ] override __.RegIDFromRegExpr (e) = - match e with + match e.E with | Var (_,id, _,_) -> id | PCVar (_, _) -> Register.toRegID Register.PC | _ -> failwith "not a register expression" + override __.RegIDToRegExpr (id) = + Register.ofRegID id |> R.GetRegVar + override __.StrToRegExpr s = match s with | "X0" -> R.X0 diff --git a/src/FrontEnd/ARM64/ARM64RegisterSet.fs b/src/FrontEnd/BinLifter/ARM64/ARM64RegisterSet.fs similarity index 61% rename from src/FrontEnd/ARM64/ARM64RegisterSet.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64RegisterSet.fs index 519dd9dc..738239a9 100644 --- a/src/FrontEnd/ARM64/ARM64RegisterSet.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64RegisterSet.fs @@ -22,25 +22,28 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM64 +namespace B2R2.FrontEnd.BinLifter.ARM64 open B2R2 +module private RegisterSetLiteral = + let [] arrLen = 2 + +open RegisterSetLiteral + type ARM64RegisterSet (bitArray: uint64 [], s: Set) = inherit NonEmptyRegisterSet (bitArray, s) - static let defaultSize = 2 - static let emptyArr = Array.init defaultSize (fun _ -> 0UL) - static member EmptySet = - new ARM64RegisterSet (emptyArr, Set.empty) :> RegisterSet + new () = ARM64RegisterSet (RegisterSet.MakeInternalBitArray arrLen, Set.empty) override __.Tag = RegisterSetTag.ARM64 - override __.ArrSize = defaultSize + + override __.ArrSize = arrLen + override __.New x s = new ARM64RegisterSet (x, s) :> RegisterSet - override __.Empty = ARM64RegisterSet.EmptySet - override __.EmptyArr = emptyArr - override __.Project x = - match Register.ofRegID x with + + override __.RegIDToIndex rid = + match Register.ofRegID rid with | R.X0 -> 0 | R.X1 -> 1 | R.X2 -> 2 @@ -114,10 +117,86 @@ type ARM64RegisterSet (bitArray: uint64 [], s: Set) = | R.V -> 70 | _ -> -1 + override __.IndexToRegID index = + match index with + | 0 -> R.X0 + | 1 -> R.X1 + | 2 -> R.X2 + | 3 -> R.X3 + | 4 -> R.X4 + | 5 -> R.X5 + | 6 -> R.X6 + | 7 -> R.X7 + | 8 -> R.X8 + | 9 -> R.X9 + | 10 -> R.X10 + | 11 -> R.X11 + | 12 -> R.X12 + | 13 -> R.X13 + | 14 -> R.X14 + | 15 -> R.X15 + | 16 -> R.X16 + | 17 -> R.X17 + | 18 -> R.X18 + | 19 -> R.X19 + | 20 -> R.X20 + | 21 -> R.X21 + | 22 -> R.X22 + | 23 -> R.X23 + | 24 -> R.X24 + | 25 -> R.X25 + | 26 -> R.X26 + | 27 -> R.X27 + | 28 -> R.X28 + | 29 -> R.X29 + | 30 -> R.X30 + | 31 -> R.XZR + | 32 -> R.SP + | 33 -> R.V0 + | 34 -> R.V1 + | 35 -> R.V2 + | 36 -> R.V3 + | 37 -> R.V4 + | 38 -> R.V5 + | 39 -> R.V6 + | 40 -> R.V7 + | 41 -> R.V8 + | 42 -> R.V9 + | 43 -> R.V10 + | 44 -> R.V11 + | 45 -> R.V12 + | 46 -> R.V13 + | 47 -> R.V14 + | 48 -> R.V15 + | 49 -> R.V16 + | 50 -> R.V17 + | 51 -> R.V18 + | 52 -> R.V19 + | 53 -> R.V20 + | 54 -> R.V21 + | 55 -> R.V22 + | 56 -> R.V23 + | 57 -> R.V24 + | 58 -> R.V25 + | 59 -> R.V26 + | 60 -> R.V27 + | 61 -> R.V28 + | 62 -> R.V29 + | 63 -> R.V30 + | 64 -> R.V31 + | 65 -> R.FPCR + | 66 -> R.FPSR + | 67 -> R.N + | 68 -> R.Z + | 69 -> R.C + | 70 -> R.V + | _ -> Utils.impossible () + |> Register.toRegID + override __.ToString () = sprintf "ARM64RegisterSet<%x, %x>" __.BitArray.[0] __.BitArray.[1] [] module ARM64RegisterSet = - let singleton = RegisterSetBuilder.singletonBuilder ARM64RegisterSet.EmptySet - let empty = ARM64RegisterSet.EmptySet + let singleton rid = ARM64RegisterSet().Add(rid) + let empty = ARM64RegisterSet () :> RegisterSet diff --git a/src/FrontEnd/ARM64/ARM64SupportedOpcode.txt b/src/FrontEnd/BinLifter/ARM64/ARM64SupportedOpcode.txt similarity index 100% rename from src/FrontEnd/ARM64/ARM64SupportedOpcode.txt rename to src/FrontEnd/BinLifter/ARM64/ARM64SupportedOpcode.txt diff --git a/src/FrontEnd/ARM64/ARM64Types.fs b/src/FrontEnd/BinLifter/ARM64/ARM64Types.fs similarity index 99% rename from src/FrontEnd/ARM64/ARM64Types.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64Types.fs index b253406c..d1ebe123 100644 --- a/src/FrontEnd/ARM64/ARM64Types.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64Types.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM64 +namespace B2R2.FrontEnd.BinLifter.ARM64 open B2R2 open System.Runtime.CompilerServices -[] +[] do () /// diff --git a/src/FrontEnd/ARM64/ARM64Utils.fs b/src/FrontEnd/BinLifter/ARM64/ARM64Utils.fs similarity index 99% rename from src/FrontEnd/ARM64/ARM64Utils.fs rename to src/FrontEnd/BinLifter/ARM64/ARM64Utils.fs index 3038411e..1f7a1186 100644 --- a/src/FrontEnd/ARM64/ARM64Utils.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64Utils.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.ARM64.Utils +module internal B2R2.FrontEnd.BinLifter.ARM64.Utils open B2R2 -open B2R2.FrontEnd.ARM64 +open B2R2.FrontEnd.BinLifter.ARM64 let extract binary n1 n2 = let m, n = if max n1 n2 = n1 then n1, n2 else n2, n1 diff --git a/src/FrontEnd/BinLifter/ARM64/B2R2.FrontEnd.BinLifter.ARM64.fsproj b/src/FrontEnd/BinLifter/ARM64/B2R2.FrontEnd.BinLifter.ARM64.fsproj new file mode 100644 index 00000000..fcabdf4e --- /dev/null +++ b/src/FrontEnd/BinLifter/ARM64/B2R2.FrontEnd.BinLifter.ARM64.fsproj @@ -0,0 +1,37 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 ARM64 frontend. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FrontEnd/BinLifter/ARM64/README.md b/src/FrontEnd/BinLifter/ARM64/README.md new file mode 100644 index 00000000..cbaf432e --- /dev/null +++ b/src/FrontEnd/BinLifter/ARM64/README.md @@ -0,0 +1,11 @@ +# B2R2.FrontEnd.BinLifter.ARM64 + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.BinLifter.ARM64 Package? + +`B2R2.FrontEnd.BinLifter.ARM64` includes AARCH64 parsers and lifters. diff --git a/src/FrontEnd/BinLifter/AVR/AVR.fs b/src/FrontEnd/BinLifter/AVR/AVR.fs new file mode 100644 index 00000000..42206577 --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVR.fs @@ -0,0 +1,55 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.AVR + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for AVR instructions. +type AVRTranslationContext internal (isa, regexprs) = + inherit TranslationContext (isa) + /// Register expressions. + member val private RegExprs: RegExprs = regexprs + override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar + override __.GetPseudoRegVar _id _pos = failwith "Implement" + +/// Parser for AVR instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type AVRParser () = + inherit Parser () + override __.Parse binReader addr pos = + Parser.parse binReader addr pos :> Instruction + + override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () + +module Basis = + let init (isa: ISA) = + let regexprs = RegExprs (isa.WordSize) + struct ( + AVRTranslationContext (isa, regexprs) :> TranslationContext, + AVRRegisterBay () :> RegisterBay + ) + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/AVR/AVRDisasm.fs b/src/FrontEnd/BinLifter/AVR/AVRDisasm.fs new file mode 100644 index 00000000..28f56df2 --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVRDisasm.fs @@ -0,0 +1,244 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.BinLifter.AVR.Disasm + +open B2R2 +open B2R2.FrontEnd.BinLifter + +let opCodeToString = function + | Opcode.ADC -> "adc" + | Opcode.ADD -> "add" + | Opcode.ADIW -> "adiw" + | Opcode.AND -> "and" + | Opcode.ANDI -> "andi" + | Opcode.ASR -> "asr" + | Opcode.BCLR -> "bclr" + | Opcode.BLD -> "bld" + | Opcode.BRBC -> "brbc" + | Opcode.BRBS -> "brbs" + | Opcode.BRCC -> "brcc" + | Opcode.BRCS -> "brcs" + | Opcode.BREAK -> "break" + | Opcode.BREQ -> "breq" + | Opcode.BRGE -> "brge" + | Opcode.BRHC -> "brhc" + | Opcode.BRHS -> "brhs" + | Opcode.BRID -> "brid" + | Opcode.BRIE -> "brie" + | Opcode.BRLAO -> "brlao" + | Opcode.BRLT -> "brlt" + | Opcode.BRMI -> "brmi" + | Opcode.BRNE -> "brne" + | Opcode.BRPL -> "brpl" + | Opcode.BRSH -> "brsh" + | Opcode.BRTC -> "brtc" + | Opcode.BRTS -> "brts" + | Opcode.BRVC -> "brvc" + | Opcode.BRVS -> "brvs" + | Opcode.BSET -> "bset" + | Opcode.BST -> "bst" + | Opcode.CALL -> "call" + | Opcode.CBI -> "cbi" + | Opcode.CBR -> "cbr" + | Opcode.CLC -> "clc" + | Opcode.CLH -> "clh" + | Opcode.CLI -> "cli" + | Opcode.CLN -> "cln" + | Opcode.CLR -> "clr" + | Opcode.CLS -> "cls" + | Opcode.CLT -> "clt" + | Opcode.CLV -> "clv" + | Opcode.CLZ -> "clz" + | Opcode.COM -> "com" + | Opcode.CP -> "cp" + | Opcode.CPC -> "cpc" + | Opcode.CPI -> "cpi" + | Opcode.CPSE -> "cpse" + | Opcode.DEC -> "dec" + | Opcode.DES -> "des" + | Opcode.EICALL -> "eicall" + | Opcode.EIJMP -> "eijmp" + | Opcode.ELPM -> "elpm" + | Opcode.EOR -> "eor" + | Opcode.FMUL -> "fmul" + | Opcode.FMULS -> "fmuls" + | Opcode.FMULSU -> "fmulsu" + | Opcode.ICALL -> "icall" + | Opcode.IJMP -> "ijmp" + | Opcode.IN -> "in" + | Opcode.INC -> "inc" + | Opcode.JMP -> "jmp" + | Opcode.LAC -> "lac" + | Opcode.LAS -> "las" + | Opcode.LAT -> "lat" + | Opcode.LD -> "ld" + | Opcode.LDD -> "ldd" + | Opcode.LDI -> "ldi" + | Opcode.LDS -> "lds" + | Opcode.LPM -> "lpm" + | Opcode.LSL -> "lsl" + | Opcode.LSR -> "lsr" + | Opcode.MOV -> "mov" + | Opcode.MOVW -> "movw" + | Opcode.MUL -> "mul" + | Opcode.MULS -> "muls" + | Opcode.MULSU -> "mulsu" + | Opcode.NEG -> "neg" + | Opcode.NOP -> "nop" + | Opcode.OR -> "or" + | Opcode.ORI -> "ori" + | Opcode.OUT -> "out" + | Opcode.POP -> "pop" + | Opcode.PUSH -> "push" + | Opcode.RCALL -> "rcall" + | Opcode.RET -> "ret" + | Opcode.RETI -> "reti" + | Opcode.RJMP -> "rjmp" + | Opcode.ROL -> "rol" + | Opcode.ROR -> "ror" + | Opcode.SBC -> "sbc" + | Opcode.SBCI -> "sbci" + | Opcode.SBI -> "sbi" + | Opcode.SBIC -> "sbic" + | Opcode.SBIS -> "sbis" + | Opcode.SBIW -> "sbiw" + | Opcode.SBR -> "sbr" + | Opcode.SBRC -> "sbrc" + | Opcode.SBRS -> "sbrs" + | Opcode.SEC -> "sec" + | Opcode.SEH -> "seh" + | Opcode.SEI -> "sei" + | Opcode.SEN -> "sen" + | Opcode.SER -> "ser" + | Opcode.SES -> "ses" + | Opcode.SET -> "set" + | Opcode.SEV -> "sev" + | Opcode.SEZ -> "sez" + | Opcode.SLEEP -> "sleep" + | Opcode.SPM -> "spm" + | Opcode.STD -> "std" + | Opcode.ST -> "st" + | Opcode.STS -> "sts" + | Opcode.SUB -> "sub" + | Opcode.SUBI -> "subi" + | Opcode.SWAP -> "swap" + | Opcode.TST -> "tst" + | Opcode.WDR -> "wdr" + | Opcode.XCH -> "xch" + | Opcode.InvalidOp -> "(invalid)" + | _ -> Utils.impossible () + +let prependDelimiter delimiter (builder: DisasmBuilder<_>) = + match delimiter with + | None -> () + | Some delim -> builder.Accumulate AsmWordKind.String delim + +let immToString imm (builder: DisasmBuilder<_>) = + builder.Accumulate AsmWordKind.Value (String.i32ToHex imm) + +let addrToString shift addr (builder: DisasmBuilder<_>) = + let relAddr = int(addr) + shift + 2 + if shift>=0 then + builder.Accumulate AsmWordKind.String ".+" + builder.Accumulate AsmWordKind.Value (string shift) + builder.Accumulate AsmWordKind.String " ; " + builder.Accumulate AsmWordKind.Value (String.i32ToHex relAddr) + else + builder.Accumulate AsmWordKind.String "." + builder.Accumulate AsmWordKind.Value (string shift) + builder.Accumulate AsmWordKind.String " ; " + builder.Accumulate AsmWordKind.Value (String.i32ToHex relAddr) + +let memToString addrMode (builder: DisasmBuilder<_>) = + match addrMode with + | DispMode (reg,c) -> + let reg = Register.toString reg + builder.Accumulate AsmWordKind.Variable reg + builder.Accumulate AsmWordKind.String "+" + builder.Accumulate AsmWordKind.Value (string c) + | PreIdxMode reg -> + let reg = Register.toString reg + builder.Accumulate AsmWordKind.String "-" + builder.Accumulate AsmWordKind.Variable reg + | PostIdxMode reg -> + let reg = Register.toString reg + builder.Accumulate AsmWordKind.Variable reg + builder.Accumulate AsmWordKind.String "+" + | UnchMode reg -> + let reg = Register.toString reg + builder.Accumulate AsmWordKind.Variable reg + +let buildReg ins reg (builder: DisasmBuilder<_>) = + let reg = Register.toString reg + builder.Accumulate AsmWordKind.Variable reg + +let oprToString ins addr operand delim builder = + match operand with + | OprReg reg -> + prependDelimiter delim builder + buildReg ins reg builder + | OprImm k -> + prependDelimiter delim builder + immToString k builder + | OprAddr shift -> + prependDelimiter delim builder + addrToString shift addr builder + | OprMemory addrMode -> + prependDelimiter delim builder + memToString addrMode builder + +let buildComment opr1 opr2 (builder: DisasmBuilder<_>) = + match opr1, opr2 with + | OprImm imm, _ | _, OprImm imm -> + builder.Accumulate AsmWordKind.String " ; " + builder.Accumulate AsmWordKind.Value (string imm) + | OprMemory addrMode, _ | _, OprMemory addrMode -> + match addrMode with + | DispMode (reg, c) -> + builder.Accumulate AsmWordKind.String " ; " + builder.Accumulate AsmWordKind.Value (String.i32ToHex c) + | _ -> () + | _ -> () + +let buildOprs ins pc builder = + match ins.Operands with + | NoOperand -> () + | OneOperand opr -> + oprToString ins pc opr (Some " ") builder + | TwoOperands (opr1, opr2) -> + oprToString ins pc opr1 (Some " ") builder + oprToString ins pc opr2 (Some ", ") builder + buildComment opr1 opr2 builder + +let inline buildOpcode ins (builder: DisasmBuilder<_>) = + let str = opCodeToString ins.Opcode + builder.Accumulate AsmWordKind.Mnemonic str + +let disasm insInfo (builder: DisasmBuilder<_>) = + let pc = insInfo.Address + if builder.ShowAddr then builder.AccumulateAddr () else () + buildOpcode insInfo builder + buildOprs insInfo pc builder +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/AVR/AVRGeneralLifter.fs b/src/FrontEnd/BinLifter/AVR/AVRGeneralLifter.fs new file mode 100644 index 00000000..07506c22 --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVRGeneralLifter.fs @@ -0,0 +1,942 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.AVR.GeneralLifter + +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators +open B2R2.FrontEnd.BinLifter.AVR + +let inline numI32 n = BitVector.ofInt32 n 8 |> AST.num + +let inline numI32PC n = BitVector.ofInt32 n 16 |> AST.num + +let inline numI22 n = BitVector.ofInt32 n 22 |> AST.num + +let private cfOnAdd e1 e2 r = + let e1High = AST.xthi 1 e1 + let e2High = AST.xthi 1 e2 + let rHighComp = AST.neg (AST.xthi 1 r) + (e1High .& e2High) .| (e1High .& rHighComp) .| (e2High .& rHighComp) + +/// OF on add. +let private ofOnAdd e1 e2 r = + let e1High = AST.xthi 1 e1 + let e2High = AST.xthi 1 e2 + let rHigh = AST.xthi 1 r + (e1High .& e2High .& (AST.neg rHigh)) + .| ((AST.neg e1High) .& (AST.neg e2High) .& rHigh) + +let inline ( !. ) (ctxt: TranslationContext) name = + Register.toRegID name |> ctxt.GetRegVar + +let transOprToExpr ctxt = function +| OprReg reg -> !.ctxt reg +| OprImm imm -> numI32 imm +| OprAddr addr -> numI32PC addr +| _ -> Utils.impossible () + +let transMemOprToExpr ins ctxt = + match ins.Operands with + | TwoOperands(OprReg reg, OprMemory (PreIdxMode(reg1))) + -> (!.ctxt reg,!.ctxt reg1,-1) + | TwoOperands(OprReg reg,OprMemory (PostIdxMode(reg1))) + -> (!.ctxt reg, !.ctxt reg1, 1) + | TwoOperands(OprReg reg,OprMemory (UnchMode(reg1))) + -> (!.ctxt reg, !.ctxt reg1, 0) + | _ -> Utils.impossible () + +let transMemOprToExpr2 ins ctxt = + match ins.Operands with + | TwoOperands(OprMemory (PreIdxMode(reg1)), OprReg reg) + -> (!.ctxt reg1, !.ctxt reg, -1) + | TwoOperands(OprMemory (PostIdxMode(reg1)), OprReg reg) + -> (!.ctxt reg1, !.ctxt reg, 1) + | TwoOperands(OprMemory (UnchMode(reg1)), OprReg reg) + -> (!.ctxt reg1, !.ctxt reg, 0) + | _ -> Utils.impossible () + +let transMemOprToExpr1 ins ctxt= + match ins.Operands with + | TwoOperands(OprReg reg, OprMemory (DispMode (reg1, imm))) + -> (!.ctxt reg, !.ctxt reg1, numI32PC imm) + | _ -> Utils.impossible () + +let transMemOprToExpr3 ins ctxt= + match ins.Operands with + | TwoOperands(OprMemory (DispMode (reg1, imm)), OprReg reg) + -> (!.ctxt reg1,!.ctxt reg, numI32PC imm) + | _ -> Utils.impossible () + +let transOneOpr (ins: InsInfo) ctxt = + match ins.Operands with + | OneOperand o1 -> transOprToExpr ctxt o1 + | _ -> raise InvalidOperandException + +let transTwoOprs (ins: InsInfo) ctxt = + match ins.Operands with + | TwoOperands (o1, o2) -> + struct (transOprToExpr ctxt o1, + transOprToExpr ctxt o2) + | _ -> raise InvalidOperandException + +let inline tmpVars2 ir t = + struct (!*ir t, !*ir t) + +let inline tmpVars3 ir t = + struct (!*ir t, !*ir t, !*ir t) + +let sideEffects insLen name = + let ir = IRBuilder (4) + !ir insLen + +let getIndAdrReg ins ctxt= + match ins.Operands with + | TwoOperands (_, OprReg reg1) -> + let dst = reg1 |> !.ctxt + let dst1 = reg1 |> Register.toRegID |> int |> (fun n -> n+1) |> + RegisterID.create |> Register.ofRegID|> !.ctxt + (AST.concat dst1 dst) + | _ -> raise InvalidOperandException + +let adc ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let oprSize = 8 + let ir = IRBuilder (16) + let struct (t1, t2, t3) = tmpVars3 ir oprSize + ! (!.ctxt R.CF) ) + !!ir (dst := t3) + !!ir (!.ctxt R.HF := cfOnAdd (AST.extract t1 1 3) (AST.extract t2 1 3) + (AST.extract t3 1 3)) + !!ir (!.ctxt R.CF := cfOnAdd t1 t2 t3) + !!ir (!.ctxt R.VF := ofOnAdd t1 t2 t3) + !!ir (!.ctxt R.NF := AST.xthi 1 t3) + !!ir (!.ctxt R.ZF := t3 == (AST.num0 oprSize)) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let add ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let oprSize = 8 + let ir = IRBuilder (16) + let struct (t1, t2, t3) = tmpVars3 ir oprSize + ! 3) (AST.extract t2 1 3) + (AST.extract t3 1 3)) + !!ir (!.ctxt R.CF := cfOnAdd t1 t2 t3) + !!ir (!.ctxt R.VF := ofOnAdd t1 t2 t3) + !!ir (!.ctxt R.NF := AST.xthi 1 t3) + !!ir (!.ctxt R.ZF := t3 == (AST.num0 oprSize)) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let adiw ins len ctxt = + let ir = IRBuilder(8) + let struct (t1, t2) = tmpVars2 ir 8 + let t3 = !*ir 16 + let struct (dst, dst1, src) = + match ins.Operands with + | TwoOperands (OprReg reg1, OprImm imm) -> + let dst = reg1 |> !.ctxt + let dst1 = reg1 |> Register.toRegID |> int |> (fun n -> n+1) |> + RegisterID.create |> Register.ofRegID|> !.ctxt + let src = imm |> numI32 + struct (dst, dst1, src) + | _ -> raise InvalidOperandException + ! src) + !!ir (dst1 := AST.extract t3 8 8 ) + !!ir (dst := AST.extract t3 8 0) + !!ir (!.ctxt R.NF := AST.xthi 1 dst1) + !!ir (!.ctxt R.VF := (AST.neg (AST.xthi 1 t1)) .& AST.xthi 1 dst1) + !!ir (!.ctxt R.ZF := t3 == (AST.num0 16)) + !!ir (!.ctxt R.CF := (AST.neg (AST.xthi 1 dst1)) .& AST.xthi 1 t1) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let ``and`` ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let oprSize = 8 + let ir = IRBuilder (16) + let r = !*ir oprSize + ! r) + !!ir (!.ctxt R.ZF := r == (AST.num0 oprSize)) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let andi ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let oprSize = 8 + let ir = IRBuilder (16) + let r = !*ir oprSize + ! r) + !!ir (!.ctxt R.ZF := r == (AST.num0 oprSize)) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let ``asr`` ins len ctxt = + let dst = transOneOpr ins ctxt + let oprSize = 8 + let ir = IRBuilder (16) + let t1 = !*ir oprSize + !> AST.num1 oprSize) + !!ir (!.ctxt R.ZF := dst == (AST.num0 oprSize)) + !!ir (!.ctxt R.NF := AST.xthi 1 dst) + !!ir (!.ctxt R.CF := AST.xtlo 1 t1) + !!ir (!.ctxt R.VF := !.ctxt R.NF <+> !.ctxt R.CF) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let bld ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let imm = + match ins.Operands with + | TwoOperands (_, OprImm imm) -> imm + | _ -> Utils.impossible () + let ir = IRBuilder (16) + ! imm) := !.ctxt R.TF) + !>ir len + +let bst ins len ctxt = + let struct (dst, _) = transTwoOprs ins ctxt + let imm = + match ins.Operands with + | TwoOperands (_, OprImm imm) -> imm + | _ -> Utils.impossible () + let ir = IRBuilder (16) + let r = !*ir 1 + ! imm)) + !>ir len + +let call ins len ctxt = + let ir = IRBuilder (4) + let dst = transOneOpr ins ctxt + let sp = !.ctxt R.SP + let pc = !.ctxt R.PC + ! sp := pc .+ numI32PC 2) + !!ir (sp := sp .- numI32PC 2) + !>ir len + +let clc ins len ctxt = + let ir = IRBuilder (4) + !ir len + +let clh len ctxt = + let ir = IRBuilder (4) + !ir len + +let cli len ctxt = + let ir = IRBuilder (4) + !ir len + +let cln len ctxt = + let ir = IRBuilder (4) + !ir len + +let clr ins len ctxt = + let dst = transOneOpr ins ctxt + let ir = IRBuilder (8) + ! dst) + !!ir (!.ctxt R.SF := AST.b0) + !!ir (!.ctxt R.VF := AST.b0) + !!ir (!.ctxt R.NF := AST.b0) + !!ir (!.ctxt R.ZF := AST.b1) + !>ir len + +let cls len ctxt = + let ir = IRBuilder (4) + !ir len + +let clt len ctxt = + let ir = IRBuilder (4) + !ir len + +let clv len ctxt = + let ir = IRBuilder (4) + !ir len + +let clz len ctxt = + let ir = IRBuilder (4) + !ir len + +let com ins len ctxt = + let ir = IRBuilder(4) + let oprSize = 8 + let dst = transOneOpr ins ctxt + ! dst) + !!ir (!.ctxt R.ZF := dst == (AST.num0 oprSize)) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let cp ins len ctxt = + let ir = IRBuilder(4) + let oprSize = 8 + let struct (dst, src) = transTwoOprs ins ctxt + let struct (t1, t2, t3) = tmpVars3 ir oprSize + ! t3) + !!ir (!.ctxt R.ZF := t3 == (AST.num0 oprSize)) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let cpc ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let oprSize = 8 + let ir = IRBuilder (16) + let struct (t1, t2, t3) = tmpVars3 ir oprSize + ! (!.ctxt R.CF) ) + !!ir (dst := t3) + !!ir (!.ctxt R.HF := cfOnAdd t3 t2 t1) + !!ir (!.ctxt R.CF := cfOnAdd t3 t2 t1) + !!ir (!.ctxt R.VF := ofOnAdd t3 t2 t1) + !!ir (!.ctxt R.NF := AST.xthi 1 t3) + !!ir (!.ctxt R.ZF := (t3 == (AST.num0 oprSize)) .& !.ctxt R.ZF) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let cpi ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let oprSize = 8 + let ir = IRBuilder (16) + let struct (t1, t2, t3) = tmpVars3 ir oprSize + ! t3) + !!ir (!.ctxt R.ZF := t3 == (AST.num0 oprSize)) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let cpse ins len ctxt = + let struct(dst, src) = transTwoOprs ins ctxt + let ir = IRBuilder (4) + let pc = !.ctxt R.PC + !ir len + +let dec ins len ctxt = + let dst = transOneOpr ins ctxt + let oprSize = 8 + let ir = IRBuilder (16) + let t1 = !*ir oprSize + ! dst) + !!ir (!.ctxt R.ZF := dst == (AST.num0 oprSize)) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let fmul ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let oprSize = 16 + let ir = IRBuilder (16) + let struct (t1, t2, t3) = tmpVars3 ir oprSize + let t4 = !*ir 16 + ! 8)) + !!ir (!.ctxt R.R0 := (AST.extract t1 8 0)) + !!ir (!.ctxt R.CF := AST.extract t3 1 15) + !!ir (!.ctxt R.ZF := t4 == (AST.num0 oprSize)) + !>ir len + +let fmuls ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let oprSize = 16 + let ir = IRBuilder (16) + let struct (t1, t2, t3) = tmpVars3 ir oprSize + let t4 = !*ir 16 + ! 8)) + !!ir (!.ctxt R.R0 := (AST.extract t1 8 0)) + !!ir (!.ctxt R.CF := AST.extract t3 1 15) + !!ir (!.ctxt R.ZF := t4 == (AST.num0 oprSize)) + !>ir len + +let fmulsu ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let oprSize = 16 + let ir = IRBuilder (16) + let struct (t1, t2, t3) = tmpVars3 ir oprSize + let t4 = !*ir 16 + ! 8)) + !!ir (!.ctxt R.R0 := (AST.extract t1 8 0)) + !!ir (!.ctxt R.CF := AST.extract t3 1 15) + !!ir (!.ctxt R.ZF := t4 == (AST.num0 oprSize)) + !>ir len + +let eicall len = (*ADD ME*) + let ir = IRBuilder(4) + !ir len + +let eijmp len = (*ADD ME*) + let ir = IRBuilder(4) + !ir len + +let eor ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let oprSize = 8 + let ir = IRBuilder (16) + ! src) + !!ir (!.ctxt R.VF := AST.b0) + !!ir (!.ctxt R.NF := AST.xthi 1 dst) + !!ir (!.ctxt R.ZF := dst == AST.num0 oprSize) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let icall len ctxt = (* ADD 22bit PC *) + let ir = IRBuilder(4) + let pc = !.ctxt R.PC + let sp = !.ctxt R.SP + ! sp := pc .+ numI32PC 2) + !!ir (sp := sp .- numI32PC 2) + !>ir len + +let ijmp len ctxt = (* ADD 22bit PC *) + let ir = IRBuilder (4) + let pc = !.ctxt R.PC + !ir len + +let inc ins len ctxt = + let dst = transOneOpr ins ctxt + let oprSize = 8 + let ir = IRBuilder (16) + let t1 = !*ir oprSize + ! dst) + !!ir (!.ctxt R.ZF := dst == (AST.num0 oprSize)) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let ``lsr`` ins len ctxt = + let dst = transOneOpr ins ctxt + let oprSize = 8 + let ir = IRBuilder (16) + let t1 = !*ir oprSize + !> AST.num1 oprSize) + !!ir (!.ctxt R.ZF := dst == (AST.num0 oprSize)) + !!ir (!.ctxt R.NF := AST.b0) + !!ir (!.ctxt R.CF := AST.xtlo 1 t1) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !!ir (!.ctxt R.VF := !.ctxt R.NF <+> !.ctxt R.CF) + !>ir len + +let branch ins len ctxt = + let ir = IRBuilder (8) + let dst = transOneOpr ins ctxt + let pc = !.ctxt R.PC + let branchCond = + match ins.Opcode with + | Opcode.BRCC -> !.ctxt R.CF == AST.b0 + | Opcode.BRCS -> !.ctxt R.CF == AST.b1 + | Opcode.BREQ -> !.ctxt R.ZF == AST.b1 + | Opcode.BRGE -> !.ctxt R.SF == AST.b0 + | Opcode.BRHC -> !.ctxt R.HF == AST.b0 + | Opcode.BRHS -> !.ctxt R.HF == AST.b1 + | Opcode.BRID -> !.ctxt R.IF == AST.b0 + | Opcode.BRIE -> !.ctxt R.IF == AST.b1 + | Opcode.BRLT -> !.ctxt R.SF == AST.b1 + | Opcode.BRMI -> !.ctxt R.NF == AST.b1 + | Opcode.BRNE -> !.ctxt R.ZF == AST.b0 + | Opcode.BRPL -> !.ctxt R.NF == AST.b0 + | Opcode.BRTC -> !.ctxt R.TF == AST.b0 + | Opcode.BRTS -> !.ctxt R.TF == AST.b1 + | Opcode.BRVC -> !.ctxt R.VF == AST.b0 + | Opcode.BRVS -> !.ctxt R.VF == AST.b1 + | _ -> raise InvalidOpcodeException + ! dst .+ numI32PC 2 + !!ir (AST.intercjmp branchCond jumpTarget fallThrough) + !>ir len + +let jmp ins len ctxt = + let dst = transOneOpr ins ctxt + let ir = IRBuilder (4) + !ir len + +let mov ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let ir = IRBuilder (4) + !ir len + +let movw ins len ctxt = + let struct (dst, dst1, src, src1) = + match ins.Operands with + | TwoOperands (OprReg reg1, OprReg reg2) -> + let dst = reg1 |> !.ctxt + let dst1 = reg1 |> Register.toRegID |> int |> (fun n -> n+1) |> + RegisterID.create |> Register.ofRegID|> !.ctxt + let src = reg2 |> !.ctxt + let src1 = reg2 |> Register.toRegID |> int |> (fun n -> n+1) |> + RegisterID.create |> Register.ofRegID|> !.ctxt + struct (dst, dst1, src, src1) + | _ -> raise InvalidOperandException + let ir = IRBuilder (4) + !ir len + +let nop len = + let ir = IRBuilder (2) + !ir len + +let ``or`` ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let oprSize = 8 + let ir = IRBuilder (4) + ! dst) + !!ir (!.ctxt R.VF := AST.b0) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let rjmp ins len ctxt = + let ir = IRBuilder (4) + let dst = transOneOpr ins ctxt + !ir len + +let ror ins len ctxt = + let dst = transOneOpr ins ctxt + let ir = IRBuilder (16) + let oprSize = 8 + let t1 = !*ir oprSize + !> AST.num1 oprSize) + !!ir ( (AST.extract dst 1 7) := !.ctxt R.CF) + !!ir (!.ctxt R.ZF := dst == (AST.num0 oprSize)) + !!ir (!.ctxt R.CF := AST.xtlo 1 t1) + !!ir (!.ctxt R.NF := AST.xtlo 1 dst) + !!ir (!.ctxt R.VF := !.ctxt R.NF <+> !.ctxt R.CF) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let sbc ins len ctxt = + let struct(dst, src) = transTwoOprs ins ctxt + let ir = IRBuilder (8) + let oprSize = 8 + let struct (t1, t2, t3) = tmpVars3 ir oprSize + ! (!.ctxt R.CF)) + !!ir (!.ctxt R.HF := cfOnAdd (AST.extract t3 1 3) (AST.extract t2 1 3) + (AST.extract t1 1 3)) + !!ir (!.ctxt R.CF := cfOnAdd t3 t2 t1) + !!ir (!.ctxt R.VF := ofOnAdd t3 t2 t1) + !!ir (!.ctxt R.ZF := (dst == AST.num0 oprSize .& !.ctxt R.ZF)) + !!ir (!.ctxt R.NF := AST.xtlo 1 t3) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let sbiw ins len ctxt = + let ir = IRBuilder(8) + let struct (t1, t2) = tmpVars2 ir 8 + let t3 = !*ir 16 + let struct (dst, dst1, src) = + match ins.Operands with + | TwoOperands (OprReg reg1, OprImm imm) -> + let dst = reg1 |> !.ctxt + let dst1 = reg1 |> Register.toRegID |> int |> (fun n -> n+1) |> + RegisterID.create |> Register.ofRegID|> !.ctxt + let src = imm |> numI32 + struct (dst, dst1, src) + | _ -> raise InvalidOperandException + ! src) + !!ir (dst1 := AST.extract t3 8 8 ) + !!ir (dst := AST.extract t3 8 0) + !!ir (!.ctxt R.NF := AST.xthi 1 dst1) + !!ir (!.ctxt R.VF := (AST.neg (AST.xthi 1 t1)) .& AST.xthi 1 dst1) + !!ir (!.ctxt R.ZF := t3 == (AST.num0 16)) + !!ir (!.ctxt R.CF := (AST.neg (AST.xthi 1 dst1)) .& AST.xthi 1 t1) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let sf ins len ctxt = + let ir = IRBuilder(4) + let setFlag = + match ins.Opcode with + | Opcode.SEC -> !.ctxt R.CF := AST.b1 + | Opcode.SEH -> !.ctxt R.HF := AST.b1 + | Opcode.SEI -> !.ctxt R.IF := AST.b1 + | Opcode.SEN -> !.ctxt R.NF := AST.b1 + | Opcode.SES -> !.ctxt R.SF := AST.b1 + | Opcode.SET -> !.ctxt R.TF := AST.b1 + | Opcode.SEV -> !.ctxt R.VF := AST.b1 + | Opcode.SEZ -> !.ctxt R.ZF := AST.b1 + | _ -> raise InvalidOpcodeException + !ir len + +let sub ins len ctxt = + let struct(dst, src) = transTwoOprs ins ctxt + let ir = IRBuilder (8) + let oprSize = 8 + let struct (t1, t2, t3) = tmpVars3 ir oprSize + ! dst) + !!ir (!.ctxt R.HF := cfOnAdd t3 t2 t1) + !!ir (!.ctxt R.CF := cfOnAdd t3 t2 t1) + !!ir (!.ctxt R.VF := ofOnAdd t3 t2 t1) + !!ir (!.ctxt R.NF := AST.xthi 1 t3) + !!ir (!.ctxt R.ZF := t3 == (AST.num0 oprSize)) + !!ir (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) + !>ir len + +let swap ins len ctxt = + let dst = transOneOpr ins ctxt + let ir = IRBuilder (4) + let t1 = !*ir 8 + ! 4 := AST.extract dst 4 0) + !!ir (AST.extract t1 4 0 := AST.extract dst 4 4) + !!ir (dst := t1) + !>ir len + +let lac ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let ir = IRBuilder (4) + let t1 = !*ir 8 + ! dst) + !!ir (AST.loadLE 8 dst := (numI32 0xff .- src) .& AST.loadLE 8 dst) + !!ir (src := t1) + !>ir len + +let las ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let ir = IRBuilder (4) + let t1 = !*ir 8 + ! dst) + !!ir (AST.loadLE 8 dst := src .| AST.loadLE 8 dst) + !!ir (src := t1) + !>ir len + +let lat ins len ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let ir = IRBuilder (4) + let t1 = !*ir 8 + ! dst) + !!ir (AST.loadLE 8 dst := src <+> AST.loadLE 8 dst) + !!ir (src := t1) + !>ir len + +let ld ins len ctxt = + let ir = IRBuilder (8) + let (dst, src, mode) = transMemOprToExpr ins ctxt + ! !!ir (dst := AST.loadLE 8 src) + | 1 -> + !!ir (dst := AST.loadLE 8 src) + match src.E with + | BinOp (BinOpType.CONCAT, _, exp1, exp2, _) -> + !!ir (exp1 := AST.extract (src .+ numI32PC 1) 8 8) + !!ir (exp2 := AST.extract (src .+ numI32PC 1) 8 0) + | _ -> Utils.impossible () + | -1 -> + match src.E with + | BinOp (BinOpType.CONCAT, _, exp1, exp2, _) -> + !!ir (exp1 := AST.extract (src .- numI32PC 1) 8 8) + !!ir (exp2 := AST.extract (src .- numI32PC 1) 8 0) + | _ -> Utils.impossible () + !!ir (dst := AST.loadLE 8 src) + | _ -> Utils.impossible () + !>ir len + +let ldd ins len ctxt = + let (dst, src, src1) = transMemOprToExpr1 ins ctxt + let ir = IRBuilder (8) + ! (src .+ src1)) + !>ir len + +let pop ins len ctxt = + let dst = transOneOpr ins ctxt + let ir = IRBuilder (8) + let sp = !.ctxt R.SP + !) + !!ir (AST.loadLE 8 sp := dst) + !>ir len + +let push ins len ctxt = + let dst = transOneOpr ins ctxt + let ir = IRBuilder (8) + let sp = !.ctxt R.SP + ! sp := dst) + !!ir (sp := sp .- AST.num1 16) + !>ir len + +let ldi ins len ctxt = + let struct(dst, src) = transTwoOprs ins ctxt + let ir = IRBuilder (8) + !ir len + +let lds ins len ctxt = + let struct(dst, src) = transTwoOprs ins ctxt + let ir = IRBuilder (8) + ! src) + !>ir len + +let mul ins len ctxt = + let struct(dst, src) = transTwoOprs ins ctxt + let oprSize = 8 + let ir = IRBuilder (8) + let struct (t1, t2, t3) = tmpVars3 ir 16 + ! dst) + !!ir (t2 := AST.zext 16 src) + !!ir (t3 := t1 .* t2) + !!ir (!.ctxt R.R1 := AST.extract t3 8 8) + !!ir (!.ctxt R.R0 := AST.extract t3 8 0) + !!ir (!.ctxt R.CF := AST.extract t3 1 15) + !!ir (!.ctxt R.ZF := t3 == AST.num0 16) + !>ir len + +let muls ins len ctxt = + let struct(dst, src) = transTwoOprs ins ctxt + let oprSize = 8 + let ir = IRBuilder (8) + let struct (t1, t2, t3) = tmpVars3 ir 16 + ! dst) + !!ir (t2 := AST.sext 16 src) + !!ir (t3 := t1 .* t2) + !!ir (!.ctxt R.R1 := AST.extract t3 8 8) + !!ir (!.ctxt R.R0 := AST.extract t3 8 0) + !!ir (!.ctxt R.CF := AST.extract t3 1 15) + !!ir (!.ctxt R.ZF := t3 == AST.num0 16) + !>ir len + +let mulsu ins len ctxt = + let struct(dst, src) = transTwoOprs ins ctxt + let oprSize = 8 + let ir = IRBuilder (8) + let struct (t1, t2, t3) = tmpVars3 ir 16 + ! dst) + !!ir (t2 := AST.zext 16 src) + !!ir (t3 := t1 .* t2) + !!ir (!.ctxt R.R1 := AST.extract t3 8 8) + !!ir (!.ctxt R.R0 := AST.extract t3 8 0) + !!ir (!.ctxt R.CF := AST.extract t3 1 15) + !!ir (!.ctxt R.ZF := t3 == AST.num0 16) + !>ir len + +let ret len opr ctxt = + let sp = !.ctxt R.SP + let ir = IRBuilder(8) + ! sp) + if opr = Opcode.RETI then !!ir (!.ctxt R.IF := AST.b1) + !>ir len + +let rcall ins len ctxt = (* ADD 22bit PC *) + let ir = IRBuilder (4) + let dst = transOneOpr ins ctxt + let sp = !.ctxt R.SP + let pc = !.ctxt R.PC + ! sp := pc .+ numI32PC 2) + !!ir (sp := sp .- numI32PC 2) + !>ir len + +let st ins len ctxt = + let ir = IRBuilder (8) + let (dst, src, mode) = transMemOprToExpr2 ins ctxt + ! !!ir (AST.loadLE 8 dst := src) + | 1 -> + !!ir (AST.loadLE 8 dst := src) + match dst.E with + | BinOp (BinOpType.CONCAT, _, exp1, exp2, _) -> + !!ir (exp1 := AST.extract (dst .+ numI32PC 1) 8 8) + !!ir (exp2 := AST.extract (dst .+ numI32PC 1) 8 0) + | _ -> Utils.impossible () + | -1 -> + match dst.E with + | BinOp (BinOpType.CONCAT, _, exp1, exp2, _) -> + !!ir (exp1 := AST.extract (dst .- numI32PC 1) 8 8) + !!ir (exp2 := AST.extract (dst .- numI32PC 1) 8 0) + | _ -> Utils.impossible () + !!ir (AST.loadLE 8 dst := src) + | _ -> Utils.impossible () + !>ir len + +let std ins len ctxt = + let (dst, src, disp) = transMemOprToExpr3 ins ctxt + let ir = IRBuilder (8) + ! (dst .+ disp) := src) + !>ir len + +let sts ins len ctxt = + let struct(dst, src) = transTwoOprs ins ctxt + let ir = IRBuilder(4) + ! (dst) := src) + !>ir len + +let des ins len ctxt = + let ir = IRBuilder (4) + let dst = transOneOpr ins ctxt + !ir len + +let xch ins len ctxt = + let ir = IRBuilder (4) + let struct(dst, src) = transTwoOprs ins ctxt + let t1 = !*ir 8 + ! dst) + !!ir (AST.loadLE 8 dst := src) + !!ir (src := t1) + !>ir len diff --git a/src/FrontEnd/BinLifter/AVR/AVRInstruction.fs b/src/FrontEnd/BinLifter/AVR/AVRInstruction.fs new file mode 100644 index 00000000..26bbbd60 --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVRInstruction.fs @@ -0,0 +1,107 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.AVR + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// The internal representation for a AVR instruction used by our disassembler +/// and lifter. +type AVRInstruction (addr, numBytes, insInfo) = + inherit Instruction (addr, numBytes, WordSize.Bit8) + + /// Basic instruction information. + member val Info: InsInfo = insInfo + + override __.IsBranch () = + match __.Info.Opcode with + | _ -> false + + override __.IsModeChanging () = false + + member __.HasConcJmpTarget () = Utils.futureFeature () + + override __.IsDirectBranch () = + __.IsBranch () && __.HasConcJmpTarget () + + override __.IsIndirectBranch () = + __.IsBranch () && (not <| __.HasConcJmpTarget ()) + + override __.IsCondBranch () = Utils.futureFeature () + + override __.IsCJmpOnTrue () = Utils.futureFeature () + + override __.IsCall () = Utils.futureFeature () + + override __.IsRET () = Utils.futureFeature () + + override __.IsInterrupt () = Utils.futureFeature () + + override __.IsExit () = Utils.futureFeature () + + override __.IsBBLEnd () = + __.IsDirectBranch () || + __.IsIndirectBranch () + + override __.DirectBranchTarget (_addr: byref) = Utils.futureFeature () + + override __.IndirectTrampolineAddr (_addr: byref) = + Utils.futureFeature () + + override __.Immediate (_v: byref) = Utils.futureFeature () + + override __.GetNextInstrAddrs () = Utils.futureFeature () + + override __.InterruptNum (_num: byref) = Utils.futureFeature () + + override __.IsNop () = Utils.futureFeature () + + override __.Translate ctxt = + Lifter.translate __.Info numBytes ctxt + + override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = + let builder = + DisasmStringBuilder (showAddr, false, WordSize.Bit32, addr, numBytes) + Disasm.disasm __.Info builder + builder.Finalize () + + override __.Disasm () = + let builder = + DisasmStringBuilder (false, false, WordSize.Bit32, addr, numBytes) + Disasm.disasm __.Info builder + builder.Finalize () + + override __.Decompose (showAddr) = + let builder = + DisasmWordBuilder (showAddr, false, WordSize.Bit32, addr, numBytes, 8) + Disasm.disasm __.Info builder + builder.Finalize () + + override __.IsInlinedAssembly () = false + + override __.Equals (_) = Utils.futureFeature () + override __.GetHashCode () = Utils.futureFeature () + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/AVR/AVRLifter.fs b/src/FrontEnd/BinLifter/AVR/AVRLifter.fs new file mode 100644 index 00000000..6ba3e64a --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVRLifter.fs @@ -0,0 +1,115 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.AVR.Lifter + +open B2R2.BinIR +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.AVR +open B2R2.FrontEnd.BinLifter.AVR.GeneralLifter + +/// Translate IR. +let translate (ins: InsInfo) insLen (ctxt : TranslationContext) = + match ins.Opcode with + | Opcode.ADC -> adc ins insLen ctxt + | Opcode.ADD -> add ins insLen ctxt + | Opcode.ADIW -> adiw ins insLen ctxt + | Opcode.AND -> ``and`` ins insLen ctxt + | Opcode.ANDI -> andi ins insLen ctxt + | Opcode.ASR -> ``asr`` ins insLen ctxt + | Opcode.BLD -> bld ins insLen ctxt + | Opcode.BRCC| Opcode.BRCS| Opcode.BREQ| Opcode.BRGE| Opcode.BRHC| Opcode.BRHS + | Opcode.BRID| Opcode.BRIE| Opcode.BRLT| Opcode.BRMI| Opcode.BRNE| Opcode.BRPL + | Opcode.BRTC| Opcode.BRTS| Opcode.BRVC| Opcode.BRVS -> branch ins insLen ctxt + | Opcode.BREAK -> sideEffects insLen ProcessorID + | Opcode.BST -> bst ins insLen ctxt + | Opcode.CALL -> call ins insLen ctxt + | Opcode.CBI| Opcode.IN | Opcode.OUT | Opcode.SBI | Opcode.SBIC | Opcode.SBIS + | Opcode.ELPM | Opcode.SLEEP | Opcode.SPM -> + sideEffects insLen UnsupportedExtension + | Opcode.CLC -> clc ins insLen ctxt + | Opcode.CLH -> clh insLen ctxt + | Opcode.CLI -> cli insLen ctxt + | Opcode.CLN -> cln insLen ctxt + | Opcode.CLR -> clr ins insLen ctxt + | Opcode.CLS -> cls insLen ctxt + | Opcode.CLT -> clt insLen ctxt + | Opcode.CLV -> clv insLen ctxt + | Opcode.CLZ -> clz insLen ctxt + | Opcode.COM -> com ins insLen ctxt + | Opcode.CP -> cp ins insLen ctxt + | Opcode.CPC -> cpc ins insLen ctxt + | Opcode.CPI -> cpi ins insLen ctxt + | Opcode.CPSE -> cpse ins insLen ctxt + | Opcode.DEC -> dec ins insLen ctxt + | Opcode.DES -> des ins insLen ctxt + | Opcode.EICALL -> eicall insLen + | Opcode.EIJMP -> eijmp insLen + | Opcode.EOR -> eor ins insLen ctxt + | Opcode.FMUL -> fmul ins insLen ctxt + | Opcode.FMULS -> fmuls ins insLen ctxt + | Opcode.FMULSU -> fmulsu ins insLen ctxt + | Opcode.ICALL -> icall insLen ctxt + | Opcode.IJMP -> ijmp insLen ctxt + | Opcode.INC -> inc ins insLen ctxt + | Opcode.JMP -> jmp ins insLen ctxt + | Opcode.LAC -> lac ins insLen ctxt + | Opcode.LAS -> las ins insLen ctxt + | Opcode.LAT -> lat ins insLen ctxt + | Opcode.LD -> ld ins insLen ctxt + | Opcode.LDD -> ldd ins insLen ctxt + | Opcode.LDI -> ldi ins insLen ctxt + | Opcode.LDS -> lds ins insLen ctxt + | Opcode.LSR -> ``lsr`` ins insLen ctxt + | Opcode.MOV -> mov ins insLen ctxt + | Opcode.MOVW -> movw ins insLen ctxt + | Opcode.MUL -> mul ins insLen ctxt + | Opcode.MULS -> muls ins insLen ctxt + | Opcode.MULSU -> mulsu ins insLen ctxt + | Opcode.NOP -> nop insLen + | Opcode.OR | Opcode.ORI -> ``or`` ins insLen ctxt + | Opcode.POP -> pop ins insLen ctxt + | Opcode.PUSH -> push ins insLen ctxt + | Opcode.RCALL -> rcall ins insLen ctxt + | Opcode.RET | Opcode.RETI as opr -> ret insLen opr ctxt + | Opcode.RJMP -> rjmp ins insLen ctxt + | Opcode.ROR -> ror ins insLen ctxt + | Opcode.SBC | Opcode.SBCI -> sbc ins insLen ctxt + | Opcode.SBIW -> sbiw ins insLen ctxt + | Opcode.SEC | Opcode.SEH | Opcode.SEI | Opcode.SEN | Opcode.SES | Opcode.SET + | Opcode.SEV | Opcode.SEZ -> sf ins insLen ctxt + | Opcode.SUB | Opcode.SUBI -> sub ins insLen ctxt + | Opcode.ST -> st ins insLen ctxt + | Opcode.STD -> std ins insLen ctxt + | Opcode.STS -> sts ins insLen ctxt + | Opcode.SWAP -> swap ins insLen ctxt + | Opcode.WDR -> sideEffects insLen ClockCounter + | Opcode.XCH -> xch ins insLen ctxt + | Opcode.InvalidOp -> raise InvalidOpcodeException + | o -> + #if DEBUG + eprintfn "%A" o + #endif + raise <| NotImplementedIRException (Disasm.opCodeToString o) + |> fun ir -> ir.ToStmts () \ No newline at end of file diff --git a/src/FrontEnd/BinLifter/AVR/AVROperandHelper.fs b/src/FrontEnd/BinLifter/AVR/AVROperandHelper.fs new file mode 100644 index 00000000..70618184 --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVROperandHelper.fs @@ -0,0 +1,179 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.AVR.OperandHelper + +open B2R2.FrontEnd.BinLifter + +let getRegister = function + | 0x0uy -> R.R0 + | 0x1uy -> R.R1 + | 0x2uy -> R.R2 + | 0x3uy -> R.R3 + | 0x4uy -> R.R4 + | 0x5uy -> R.R5 + | 0x6uy -> R.R6 + | 0x7uy -> R.R7 + | 0x8uy -> R.R8 + | 0x9uy -> R.R9 + | 0xAuy -> R.R10 + | 0xBuy -> R.R11 + | 0xCuy -> R.R12 + | 0xDuy -> R.R13 + | 0xEuy -> R.R14 + | 0xFuy -> R.R15 + | 0x10uy -> R.R16 + | 0x11uy -> R.R17 + | 0x12uy -> R.R18 + | 0x13uy -> R.R19 + | 0x14uy -> R.R20 + | 0x15uy -> R.R21 + | 0x16uy -> R.R22 + | 0x17uy -> R.R23 + | 0x18uy -> R.R24 + | 0x19uy -> R.R25 + | 0x1Auy -> R.R26 + | 0x1Buy -> R.R27 + | 0x1Cuy -> R.R28 + | 0x1Duy -> R.R29 + | 0x1Euy -> R.R30 + | 0x1Fuy -> R.R31 + | 0x20uy -> R.X + | 0x21uy -> R.Y + | 0x22uy -> R.Z + | _ -> raise InvalidRegisterException + +let memPreIdx offset = OprMemory (PreIdxMode (offset)) + +let memPostIdx offset = OprMemory (PostIdxMode (offset)) + +let memDisp offset = OprMemory (DispMode (offset)) + +let memUnch offset = OprMemory (UnchMode (offset)) + +let extract binary n1 n2 = + let m, n = if max n1 n2 = n1 then n1, n2 else n2, n1 + let range = m - n + 1u + if range > 31u then failwith "invaild range" else () + let mask = pown 2 (int range) - 1 |> uint32 + binary >>> int n &&& mask + +let extract16 binary n1 n2 = + let m, n = if max n1 n2 = n1 then n1, n2 else n2, n1 + let range = m - n + 1us + if range > 31us then failwith "invaild range" else () + let mask = pown 2 (int range) - 1 |> uint16 + binary >>> int n &&& mask + +let pickBit binary (pos: uint32) = binary >>> int pos &&& 0b1u + +let concat (n1: uint32) (n2: uint32) shift = (n1 <<< shift) + n2 + +let parseOneOpr b op1 = OneOperand(op1 b) + +let parseTwoOpr b op1 op2 = TwoOperands(op1 b, op2 b) + +let getReg b s e = getRegister (extract b s e |> byte) + +let getRegD b = getReg b 8u 4u |> OprReg + +let getReg2D b = getRegister( 24u + 2u * (extract b 5u 4u) |> byte)|> OprReg + +let getReg3D b = getRegister( 16u + (extract b 6u 4u) |> byte)|> OprReg + +let getReg3DLast b = getRegister( 16u + (extract b 2u 0u) |> byte)|> OprReg + +let getReg4D b = getRegister (extract b 7u 4u + 16u |> byte ) |> OprReg + +let getRegEven4D b = getRegister(2u * (extract b 7u 4u) |> byte) |> OprReg + +let getRegEvenEnd4D b = getRegister(2u * (extract b 3u 0u) |> byte) |> OprReg + +let getRegR b = + getRegister (concat (pickBit b 9u) (b &&& 0b1111u) 4 |> byte ) |> OprReg + +let getRegD32 b = getReg b 24u 20u |> OprReg + +let getConst4K b = extract b 7u 4u |> int32 |> OprImm + +let getConst6K b = concat (extract b 7u 6u) (b &&& 0b1111u) 4 |> int32 |> OprImm + +let getConst8K b = concat (extract b 11u 8u) (b &&& 0b1111u) 4 |> int32 |> OprImm + +let getConst3b b = b &&& 0b111u |> int32 |> OprImm + +let getConst3bs b = extract b 6u 4u |> int32 |> OprImm + +let getConst22 b = + (2u * concat (extract b 24u 20u) (extract b 16u 0u) (17)) |> int32 |> OprAddr + +let getConst16 b = extract b 15u 0u |> int32 |> OprAddr + +let getIO5 b = extract b 7u 3u |> int32 |> OprImm + +let getIO6 b = concat (extract b 10u 9u) (b &&& 0b1111u) 4 |> int32 |> OprImm + +let getAddr7K b = ((extract b 9u 3u) <<< 25 |> int32 >>> 25) * 2 |> OprAddr + +let getAddr12 b = ((extract b 11u 0u) <<< 20 |> int32 >>> 20) * 2 |> OprAddr + +let getDisp b = + concat (concat (pickBit b 13u) (extract b 11u 10u) (2)) (b &&& 0b111u) 3 + |> int32 + +let getMemDispY b = + let disp = getDisp b + memDisp (R.Y, disp) + +let getMemDispZ b = + let disp = getDisp b + memDisp (R.Z, disp) + +let getMemLDD b = + match b &&& 0b1111u with + | 0b1100u -> memUnch (R.X) + | 0b1101u -> memPostIdx (R.X) + | 0b1110u -> memPreIdx (R.X) + | 0b1000u -> memUnch (R.Y) + | 0b1001u -> memPostIdx (R.Y) + | 0b1010u -> memPreIdx (R.Y) + | 0b0000u -> memUnch (R.Z) + | 0b0001u -> memPostIdx (R.Z) + | 0b0010u -> memPreIdx (R.Z) + | 0b0110u -> memUnch (R.Z) + | 0b0111u -> memPostIdx (R.Z) + | 0b0100u -> memUnch (R.Z) + | _ -> memPostIdx (R.Z) // 0101 + +let getMemST b = + match b &&& 0b1111u with + | 0b1100u -> memUnch (R.X) + | 0b1101u -> memPostIdx (R.X) + | 0b1110u -> memPreIdx (R.X) + | 0b1000u -> memUnch (R.Y) + | 0b1001u -> memPostIdx (R.Y) + | 0b1010u -> memPreIdx (R.Y) + | 0b0000u -> memUnch (R.Z) + | 0b0001u -> memPostIdx (R.Z) + | _ -> memPreIdx (R.Z) //0010 \ No newline at end of file diff --git a/src/FrontEnd/BinLifter/AVR/AVRParser.fs b/src/FrontEnd/BinLifter/AVR/AVRParser.fs new file mode 100644 index 00000000..d73e07b8 --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVRParser.fs @@ -0,0 +1,299 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.BinLifter.AVR.Parser + +open B2R2 +open B2R2.FrontEnd.BinLifter.AVR.OperandHelper + +let isTwoBytes b1 = + let b32 = b1 |> uint32 + match concat (b32 >>> 9) (b32 &&& 0b1111u) 4 with + | 0b10010101110u | 0b1001010111u -> false + | 0b10010101100u | 0b10010101101u -> false + | 0b10010000000u -> false + | 0b10010010000u -> false + | _ -> true + +/// 1001 000- ---- ---- +let parse1001000 b32 = + match b32 &&& 0b1111u with + | 0b1100u | 0b1101u | 0b1110u | 0b1001u | 0b1010u | 0b0001u | 0b0010u -> + Opcode.LD, parseTwoOpr b32 getRegD getMemLDD + | 0b1111u -> Opcode.POP, parseOneOpr b32 getRegD + | 0b0101u | 0b0100u -> Opcode.LPM, parseTwoOpr b32 getRegD getMemLDD + | 0b0110u | 0b0111u -> Opcode.ELPM, parseTwoOpr b32 getRegD getMemLDD + | _ -> Opcode.InvalidOp, NoOperand + +/// 1001 001- ---- ---- +let parse1001001 b32 = + match b32 &&& 0b1111u with + | 0b1100u | 0b1101u | 0b1110u | 0b1001u | 0b1010u | 0b0001u | 0b0010u -> + Opcode.ST, parseTwoOpr b32 getMemST getRegD + | 0b1111u -> Opcode.PUSH, parseOneOpr b32 getRegD + | 0b0110u -> Opcode.LAC, TwoOperands (OprReg R.Z, getRegD b32) + | 0b0101u -> Opcode.LAS, TwoOperands (OprReg R.Z, getRegD b32) + | 0b0111u -> Opcode.LAT, TwoOperands (OprReg R.Z, getRegD b32) + | 0b0100u -> Opcode.XCH, TwoOperands (OprReg R.Z, getRegD b32) + | _ -> Opcode.InvalidOp, NoOperand + +/// 0000 00-- ---- ---- +let parse000000 b32 = + match extract b32 9u 8u with + | 0b01u -> Opcode.MOVW, parseTwoOpr b32 getRegEven4D getRegEvenEnd4D + | 0b10u -> Opcode.MULS, parseTwoOpr b32 getRegEven4D getRegEvenEnd4D + | 0b11u -> + match concat (pickBit b32 7u) (pickBit b32 3u) 1 with + | 0b01u -> Opcode.FMUL, parseTwoOpr b32 getReg3D getReg3DLast + | 0b10u -> Opcode.FMULS, parseTwoOpr b32 getReg3D getReg3DLast + | 0b11u -> Opcode.FMULSU, parseTwoOpr b32 getReg3D getReg3DLast + | 0b00u -> Opcode.MULSU, parseTwoOpr b32 getReg3D getReg3DLast + | _ -> Opcode.InvalidOp, NoOperand + | 0b0u when b32 = 0u -> Opcode.NOP, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 1001 010- ---- 1000 with no operands +let parseNoOp1000 b32 = + match extract b32 8u 4u with + | 0b11001u -> Opcode.BREAK, NoOperand + | 0b01000u -> Opcode.CLC, NoOperand + | 0b01101u -> Opcode.CLH, NoOperand + | 0b01111u -> Opcode.CLI, NoOperand + | 0b01010u -> Opcode.CLN, NoOperand + | 0b01100u -> Opcode.CLS, NoOperand + | 0b01110u -> Opcode.CLT, NoOperand + | 0b01011u -> Opcode.CLV, NoOperand + | 0b01001u -> Opcode.CLZ, NoOperand + | 0b10000u -> Opcode.RET, NoOperand + | 0b10001u -> Opcode.RETI, NoOperand + | 0b00000u -> Opcode.SEC, NoOperand + | 0b00101u -> Opcode.SEH, NoOperand + | 0b00111u -> Opcode.SEI, NoOperand + | 0b00010u -> Opcode.SEN, NoOperand + | 0b00100u -> Opcode.SES, NoOperand + | 0b00110u -> Opcode.SET, NoOperand + | 0b00011u -> Opcode.SEV, NoOperand + | 0b00001u -> Opcode.SEZ, NoOperand + | 0b11000u -> Opcode.SLEEP, NoOperand + | 0b11110u -> Opcode.SPM, NoOperand + | 0b11010u -> Opcode.WDR, NoOperand + | 0b11100u -> Opcode.LPM, NoOperand + | 0b11101u -> Opcode.ELPM, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 1001 010- ---- 1001 with no operands +let parseNoOp1001 b32 = + match extract b32 8u 4u with + | 0b10001u -> Opcode.EICALL, NoOperand + | 0b00001u -> Opcode.EIJMP, NoOperand + | 0b10000u -> Opcode.ICALL, NoOperand + | 0b00000u -> Opcode.IJMP, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 1001 010- ---- ---- +let parse1001010 b32 = + match b32 >>> 9 with + | 0b1001010u -> + match b32 &&& 0b1111u with + | 0b0101u -> Opcode.ASR, parseOneOpr b32 getRegD + | 0b0000u -> Opcode.COM, parseOneOpr b32 getRegD + | 0b1010u -> Opcode.DEC, parseOneOpr b32 getRegD + | 0b0011u -> Opcode.INC, parseOneOpr b32 getRegD + | 0b0110u -> Opcode.LSR, parseOneOpr b32 getRegD + | 0b0001u -> Opcode.NEG, parseOneOpr b32 getRegD + | 0b0111u -> Opcode.ROR, parseOneOpr b32 getRegD + | 0b0010u -> Opcode.SWAP, parseOneOpr b32 getRegD + | 0b1011u when pickBit b32 8u = 0b0u -> + Opcode.DES, parseOneOpr b32 getConst4K + (* | 0b1000u when extract b32 8u 7u = 0b01u -> + Opcode.BCLR, parseOneOpr b32 getConst3bs + | 0b1000u when extract b32 8u 7u = 0b00u -> + Opcode.BSET, parseOneOpr b32 getConst3bs *) + | 0b1000u -> parseNoOp1000 b32 + | 0b1001u -> parseNoOp1001 b32 + | _ -> Opcode.InvalidOp, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 1111 1--d dddd 0bbb +let parse11111 b32 = + match concat (extract b32 10u 9u) (pickBit b32 3u) 1 with + | 0b000u -> Opcode.BLD, parseTwoOpr b32 getRegD getConst3b + | 0b010u -> Opcode.BST, parseTwoOpr b32 getRegD getConst3b + | 0b100u -> Opcode.SBRC, parseTwoOpr b32 getRegD getConst3b + | 0b110u -> Opcode.SBRS, parseTwoOpr b32 getRegD getConst3b + | _ -> Opcode.InvalidOp, NoOperand + +/// 1111 0- kk kkkk k--- +let parse11110 b32 = + match pickBit b32 10u with + | 0b0u -> + match b32 &&& 0b111u with + | 0b000u -> Opcode.BRCS, parseOneOpr b32 getAddr7K + | 0b001u -> Opcode.BREQ, parseOneOpr b32 getAddr7K + | 0b101u -> Opcode.BRHS, parseOneOpr b32 getAddr7K + | 0b111u -> Opcode.BRIE, parseOneOpr b32 getAddr7K + (* | 0b000u -> Opcode.BRLO, parseOneOpr b getAddr7K *) + | 0b100u -> Opcode.BRLT, parseOneOpr b32 getAddr7K + | 0b010u -> Opcode.BRMI, parseOneOpr b32 getAddr7K + | 0b110u -> Opcode.BRTS, parseOneOpr b32 getAddr7K + | 0b011u -> Opcode.BRVS, parseOneOpr b32 getAddr7K + | _ -> Opcode.InvalidOp, NoOperand + | 0b1u -> + match b32 &&& 0b111u with + | 0b000u -> Opcode.BRCC, parseOneOpr b32 getAddr7K + | 0b001u -> Opcode.BRNE, parseOneOpr b32 getAddr7K + | 0b101u -> Opcode.BRHC, parseOneOpr b32 getAddr7K + | 0b111u -> Opcode.BRID, parseOneOpr b32 getAddr7K + (* | 0b000u -> Opcode.BRSH, parseOneOpr b getAddr7K *) + | 0b100u -> Opcode.BRGE, parseOneOpr b32 getAddr7K + | 0b010u -> Opcode.BRPL, parseOneOpr b32 getAddr7K + | 0b110u -> Opcode.BRTC, parseOneOpr b32 getAddr7K + | 0b011u -> Opcode.BRVC, parseOneOpr b32 getAddr7K + | _ -> Opcode.InvalidOp, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +let parse1111 b32 = + match pickBit b32 11u with + | 0b0u -> parse11110 b32 + | 0b1u -> parse11111 b32 + | _ -> Opcode.InvalidOp, NoOperand + +let parse1001 b32 = + match extract b32 11u 8u with + | 0b0100u | 0b0101u -> parse1001010 b32 + | 0b0010u | 0b0011u -> parse1001001 b32 + | 0b0000u | 0b0001u -> parse1001000 b32 + | 0b0110u -> Opcode.ADIW, parseTwoOpr b32 getReg2D getConst6K + | 0b1000u -> Opcode.CBI, parseTwoOpr b32 getIO5 getConst3b + | 0b1010u -> Opcode.SBI, parseTwoOpr b32 getIO5 getConst3b + | 0b1001u -> Opcode.SBIC, parseTwoOpr b32 getIO5 getConst3b + | 0b1011u -> Opcode.SBIS, parseTwoOpr b32 getIO5 getConst3b + | 0b0111u -> Opcode.SBIW, parseTwoOpr b32 getReg2D getConst6K + | op when op &&& 0b1100u = 0b1100u -> + Opcode.MUL, parseTwoOpr b32 getRegD getRegR + | _ -> Opcode.InvalidOp, NoOperand + +let parse1000 b32 = + let isDispZero = getDisp b32 = 0 + match concat (pickBit b32 9u)(pickBit b32 3u) 1 with + | 0b11u -> + if isDispZero then Opcode.ST, parseTwoOpr b32 getMemST getRegD + else Opcode.STD, parseTwoOpr b32 getMemDispY getRegD + | 0b10u -> + if isDispZero then Opcode.ST, parseTwoOpr b32 getMemST getRegD + else Opcode.STD, parseTwoOpr b32 getMemDispZ getRegD + | 0b01u -> + if isDispZero then Opcode.LD, parseTwoOpr b32 getRegD getMemLDD + else Opcode.LDD, parseTwoOpr b32 getRegD getMemDispY + | 0b00u -> + if isDispZero then Opcode.LD, parseTwoOpr b32 getRegD getMemLDD + else Opcode.LDD, parseTwoOpr b32 getRegD getMemDispZ + | _ -> Opcode.InvalidOp, NoOperand + +let parse1010 b32 = + match concat (pickBit b32 9u)(pickBit b32 3u) 1 with + | 0b00u -> Opcode.LDD, parseTwoOpr b32 getRegD getMemDispZ + | 0b01u -> Opcode.LDD, parseTwoOpr b32 getRegD getMemDispY + | 0b10u -> Opcode.STD, parseTwoOpr b32 getMemDispZ getRegD + | 0b11u -> Opcode.STD, parseTwoOpr b32 getMemDispY getRegD + | _ -> Opcode.InvalidOp, NoOperand + +/// Parse the instruction using only the first 6 bits +let parseSixBits b32 = + match b32 >>> 10 with + | 0b000111u -> Opcode.ADC, parseTwoOpr b32 getRegD getRegR + | 0b000011u -> Opcode.ADD, parseTwoOpr b32 getRegD getRegR + | 0b001000u -> Opcode.AND, parseTwoOpr b32 getRegD getRegR + (* | 0b111101u -> Opcode.BRBC + | 0b111100u -> Opcode.BRBS + | 0b001001u -> Opcode.CLR // Same with EOR *) + | 0b000101u -> Opcode.CP, parseTwoOpr b32 getRegD getRegR + | 0b000001u -> Opcode.CPC, parseTwoOpr b32 getRegD getRegR + | 0b000100u -> Opcode.CPSE, parseTwoOpr b32 getRegD getRegR + | 0b001001u -> Opcode.EOR, parseTwoOpr b32 getRegD getRegR + (* | 0b000011u -> Opcode.LSL // Logical shift left *) + | 0b001011u -> Opcode.MOV, parseTwoOpr b32 getRegD getRegR + | 0b000110u -> Opcode.SUB, parseTwoOpr b32 getRegD getRegR + | 0b100111u -> Opcode.MUL, parseTwoOpr b32 getRegD getRegR + | 0b001010u -> Opcode.OR, parseTwoOpr b32 getRegD getRegR + (* | 0b000111u -> Opcode.ROL // Rotate Left through Carry *) + | 0b000010u -> Opcode.SBC, parseTwoOpr b32 getRegD getRegR + (* | 0b001000u -> Opcode.TST *) + | _ -> Opcode.InvalidOp, NoOperand + +/// Parse the instruction using only the first 4 bits +let parseFourBits b32 = + match b32 >>> 12 with + | 0b0111u -> Opcode.ANDI, parseTwoOpr b32 getReg4D getConst8K + | 0b0011u -> Opcode.CPI, parseTwoOpr b32 getReg4D getConst8K + | 0b1110u -> Opcode.LDI, parseTwoOpr b32 getReg4D getConst8K + | 0b0110u -> Opcode.ORI, parseTwoOpr b32 getReg4D getConst8K + | 0b1101u -> Opcode.RCALL, parseOneOpr b32 getAddr12 + | 0b1100u -> Opcode.RJMP, parseOneOpr b32 getAddr12 + | 0b0100u -> Opcode.SBCI, parseTwoOpr b32 getReg4D getConst8K + (* | 0x0110u -> Opcode.SBR, parseTwoOpr b32 getReg4D getConst8K *) + | 0b0101u -> Opcode.SUBI, parseTwoOpr b32 getReg4D getConst8K + | 0b1011u when (pickBit b32 11u) = 0b0u -> + Opcode.IN, parseTwoOpr b32 getRegD getIO6 + | 0b1011u when (pickBit b32 11u) = 0b1u -> + Opcode.OUT, parseTwoOpr b32 getIO6 getRegD + | _ -> parseSixBits b32 + +let parseTwoBytes bin = + match bin >>> 12 with + | 0b0000u when extract bin 11u 10u = 0b0u -> parse000000 bin + | 0b1001u -> parse1001 bin + | 0b1111u -> parse1111 bin + | 0b1000u -> parse1000 bin + | 0b1010u -> parse1010 bin + | _ -> parseFourBits bin + +let parseFourBytes b1= + match concat (b1 >>> 25) ((b1 >>> 16) &&& 0b1111u) 4 with + | 0b10010101110u | 0b10010101111u -> Opcode.CALL, parseOneOpr b1 getConst22 + | 0b10010101100u | 0b10010101101u -> Opcode.JMP, parseOneOpr b1 getConst22 + | 0b10010000000u -> Opcode.LDS, parseTwoOpr b1 getRegD32 getConst16 + | 0b10010010000u -> Opcode.STS, parseTwoOpr b1 getConst16 getRegD32 + | _ -> Opcode.InvalidOp, NoOperand + +let parse (reader: BinReader) addr pos = + let struct (bin, nextPos) = reader.ReadUInt16 pos + let struct ((op, operands), nextPos) = + match isTwoBytes bin with + | true -> + let bin = uint32 bin + struct (bin |> parseTwoBytes, nextPos) + | false -> + let struct (b2, nextPos) = reader.ReadUInt16 nextPos + let bin = ((uint32 bin) <<< 16) + (uint32 b2) + struct (bin |> parseFourBytes, nextPos) + let instrLen = nextPos - pos |> uint32 + let insInfo = + { Address = addr + NumBytes = instrLen + Opcode = op + Operands = operands } + AVRInstruction (addr, instrLen, insInfo) + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/AVR/AVRRegExprs.fs b/src/FrontEnd/BinLifter/AVR/AVRRegExprs.fs new file mode 100644 index 00000000..2503a82b --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVRRegExprs.fs @@ -0,0 +1,142 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.AVR + +open B2R2 +open B2R2.BinIR.LowUIR + +type internal RegExprs (wordSize) = + let var sz t name = AST.var sz t name (AVRRegisterSet.singleton t) + + (* Registers *) + let regType = WordSize.toRegType wordSize + + let reg16 reg1 reg2= + AST.concat reg1 reg2 + + let r26 = var regType (Register.toRegID Register.R26) "R26" + let r27 = var regType (Register.toRegID Register.R27) "R27" + let r28 = var regType (Register.toRegID Register.R28) "R28" + let r29 = var regType (Register.toRegID Register.R29) "R29" + let r30 = var regType (Register.toRegID Register.R30) "R30" + let r31 = var regType (Register.toRegID Register.R31) "R31" + + + member val R0= var regType (Register.toRegID Register.R0) "R0" with get + member val R1 = var regType (Register.toRegID Register.R1) "R1" with get + member val R2 = var regType (Register.toRegID Register.R2) "R2" with get + member val R3 = var regType (Register.toRegID Register.R3) "R3" with get + member val R4 = var regType (Register.toRegID Register.R4) "R4" with get + member val R5 = var regType (Register.toRegID Register.R5) "R5" with get + member val R6 = var regType (Register.toRegID Register.R6) "R6" with get + member val R7 = var regType (Register.toRegID Register.R7) "R7" with get + member val R8 = var regType (Register.toRegID Register.R8) "R8" with get + member val R9 = var regType (Register.toRegID Register.R9) "R9" with get + member val R10 = var regType (Register.toRegID Register.R10) "R10" with get + member val R11 = var regType (Register.toRegID Register.R11) "R11" with get + member val R12 = var regType (Register.toRegID Register.R12) "R12" with get + member val R13 = var regType (Register.toRegID Register.R13) "R13" with get + member val R14 = var regType (Register.toRegID Register.R14) "R14" with get + member val R15 = var regType (Register.toRegID Register.R15) "R15" with get + member val R16 = var regType (Register.toRegID Register.R16) "R16" with get + member val R17 = var regType (Register.toRegID Register.R17) "R17" with get + member val R18 = var regType (Register.toRegID Register.R18) "R18" with get + member val R19 = var regType (Register.toRegID Register.R19) "R19" with get + member val R20 = var regType (Register.toRegID Register.R20) "R20" with get + member val R21 = var regType (Register.toRegID Register.R21) "R21" with get + member val R22 = var regType (Register.toRegID Register.R22) "R22" with get + member val R23 = var regType (Register.toRegID Register.R23) "R23" with get + member val R24 = var regType (Register.toRegID Register.R24) "R24" with get + member val R25 = var regType (Register.toRegID Register.R25) "R25" with get + member val R26 = r26 with get + member val R27 = r27 with get + member val R28 = r28 with get + member val R29 = r29 with get + member val R30 = r30 with get + member val R31 = r31 with get + member val X = reg16 r27 r26 with get + member val Y = reg16 r29 r28 with get + member val Z = reg16 r31 r30 with get + member val IF = var 1 (Register.toRegID Register.IF) "IF" with get + member val TF = var 1 (Register.toRegID Register.TF) "TF" with get + member val HF = var 1 (Register.toRegID Register.HF) "HF" with get + member val SF = var 1 (Register.toRegID Register.SF) "SF" with get + member val VF = var 1 (Register.toRegID Register.VF) "VF" with get + member val NF = var 1 (Register.toRegID Register.NF) "NF" with get + member val ZF = var 1 (Register.toRegID Register.ZF) "ZF" with get + member val CF = var 1 (Register.toRegID Register.CF) "CF" with get + member val PC = AST.pcvar 16 "PC" + member val SP = var 16 (Register.toRegID Register.SP) "SP" with get + + member __.GetRegVar (name) = + match name with + | R.R0 -> __.R0 + | R.R1 -> __.R1 + | R.R2 -> __.R2 + | R.R3 -> __.R3 + | R.R4 -> __.R4 + | R.R5 -> __.R5 + | R.R6 -> __.R6 + | R.R7 -> __.R7 + | R.R8 -> __.R8 + | R.R9 -> __.R9 + | R.R10 -> __.R10 + | R.R11 -> __.R11 + | R.R12 -> __.R12 + | R.R13 -> __.R13 + | R.R14 -> __.R14 + | R.R15 -> __.R15 + | R.R16 -> __.R16 + | R.R17 -> __.R17 + | R.R18 -> __.R18 + | R.R19 -> __.R19 + | R.R20 -> __.R20 + | R.R21 -> __.R21 + | R.R22 -> __.R22 + | R.R23 -> __.R23 + | R.R24 -> __.R24 + | R.R25 -> __.R25 + | R.R26 -> __.R26 + | R.R27 -> __.R27 + | R.R28 -> __.R28 + | R.R29 -> __.R29 + | R.R30 -> __.R30 + | R.R31 -> __.R31 + | R.X -> __.X + | R.Y -> __.Y + | R.Z -> __.Z + | R.IF -> __.IF + | R.TF -> __.TF + | R.HF -> __.HF + | R.SF -> __.SF + | R.VF -> __.VF + | R.NF -> __.NF + | R.ZF -> __.ZF + | R.CF -> __.CF + | R.PC -> __.PC + | R.SP -> __.SP + | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/AVR/AVRRegister.fs b/src/FrontEnd/BinLifter/AVR/AVRRegister.fs new file mode 100644 index 00000000..3d98a609 --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVRRegister.fs @@ -0,0 +1,173 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.AVR + +open B2R2 + +type Register = + | R0 = 0x0 + | R1 = 0x1 + | R2 = 0x2 + | R3 = 0x3 + | R4 = 0x4 + | R5 = 0x5 + | R6 = 0x6 + | R7 = 0x7 + | R8 = 0x8 + | R9 = 0x9 + | R10 = 0xA + | R11 = 0xB + | R12 = 0xC + | R13 = 0xD + | R14 = 0xE + | R15 = 0xF + | R16 = 0x10 + | R17 = 0x11 + | R18 = 0x12 + | R19 = 0x13 + | R20 = 0x14 + | R21 = 0x15 + | R22 = 0x16 + | R23 = 0x17 + | R24 = 0x18 + | R25 = 0x19 + | R26 = 0x1A + | R27 = 0x1B + | R28 = 0x1C + | R29 = 0x1D + | R30 = 0x1E + | R31 = 0x1F + | X = 0x20 + | Y = 0x21 + | Z = 0x22 + | IF = 0x23 + | TF = 0x24 + | HF = 0x25 + | SF = 0x26 + | VF = 0x27 + | NF = 0x28 + | ZF = 0x29 + | CF = 0x2A + | PC = 0x2B + | SP = 0x2C + +/// Shortcut for Register type. +type internal R = Register + +/// This module exposes several useful functions to handle AVR registers. +[] +module Register = + let inline ofRegID (n: RegisterID): Register = + int n |> LanguagePrimitives.EnumOfValue + + let inline toRegID (reg: Register) = + LanguagePrimitives.EnumToValue (reg) |> RegisterID.create + + let ofString (str: string) = + match str.ToLower () with + | "r1" -> R.R0 + | "r2" -> R.R1 + | "r3" -> R.R2 + | "r4" -> R.R3 + | "r5" -> R.R4 + | "r6" -> R.R5 + | "r7" -> R.R6 + | "r8" -> R.R7 + | "r9" -> R.R8 + | "r10" -> R.R9 + | "r11" -> R.R10 + | "r12" -> R.R11 + | "r13" -> R.R12 + | "r14" -> R.R13 + | "r15" -> R.R14 + | "r16" -> R.R15 + | "r17" -> R.R16 + | "r18" -> R.R17 + | "r19" -> R.R18 + | "r20" -> R.R19 + | "r21" -> R.R20 + | "r22" -> R.R21 + | "r23" -> R.R22 + | "r24" -> R.R23 + | "r25" -> R.R24 + | "r26" -> R.R25 + | "r27" -> R.R26 + | "r28" -> R.R27 + | "r29" -> R.R28 + | "r30" -> R.R29 + | "r31" -> R.R30 + | "r32" -> R.R31 + | "IF" -> R.IF + | "TF" -> R.TF + | "HF" -> R.HF + | "SF" -> R.SF + | "VF" -> R.VF + | "NF" -> R.NF + | "ZF" -> R.ZF + | "CF" -> R.CF + | "PC" -> R.PC + | "SP" -> R.SP + | _ -> Utils.impossible () + + let toString = function + | R.R0 -> "r0" + | R.R1 -> "r1" + | R.R2 -> "r2" + | R.R3 -> "r3" + | R.R4 -> "r4" + | R.R5 -> "r5" + | R.R6 -> "r6" + | R.R7 -> "r7" + | R.R8 -> "r8" + | R.R9 -> "r9" + | R.R10 -> "r10" + | R.R11 -> "r11" + | R.R12 -> "r12" + | R.R13 -> "r13" + | R.R14 -> "r14" + | R.R15 -> "r15" + | R.R16 -> "r16" + | R.R17 -> "r17" + | R.R18 -> "r18" + | R.R19 -> "r19" + | R.R20 -> "r20" + | R.R21 -> "r21" + | R.R22 -> "r22" + | R.R23 -> "r23" + | R.R24 -> "r24" + | R.R25 -> "r25" + | R.R26 -> "r26" + | R.R27 -> "r27" + | R.R28 -> "r28" + | R.R29 -> "r29" + | R.R30 -> "r30" + | R.R31 -> "r31" + | R.X -> "X" + | R.Y -> "Y" + | R.Z -> "Z" + | R.PC -> "pc" + | R.SP -> "sp" + | _ -> Utils.impossible () + diff --git a/src/FrontEnd/EVM/EVMRegisterBay.fs b/src/FrontEnd/BinLifter/AVR/AVRRegisterBay.fs similarity index 78% rename from src/FrontEnd/EVM/EVMRegisterBay.fs rename to src/FrontEnd/BinLifter/AVR/AVRRegisterBay.fs index 8bf476fd..619da576 100644 --- a/src/FrontEnd/EVM/EVMRegisterBay.fs +++ b/src/FrontEnd/BinLifter/AVR/AVRRegisterBay.fs @@ -22,29 +22,27 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.EVM +namespace B2R2.FrontEnd.BinLifter.AVR open B2R2 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type EVMRegisterBay () = +type AVRRegisterBay () = inherit RegisterBay () override __.GetAllRegExprs () = Utils.futureFeature () - - override __.GetAllRegNames () = [] - + override __.GetAllRegNames () = Utils.futureFeature () override __.GetGeneralRegExprs () = Utils.futureFeature () override __.RegIDFromRegExpr (e) = - match e with - | Var (_, id, _ ,_) -> id - | PCVar (_, _) -> Register.toRegID Register.PC + match e.E with + | Var (_, id, _ ,_) -> id (* TODO *) | _ -> failwith "not a register expression" - override __.StrToRegExpr _s = Utils.impossible () + override __.RegIDToRegExpr (id) = Utils.futureFeature () + override __.StrToRegExpr _s = Utils.futureFeature () override __.RegIDFromString _s = Utils.futureFeature () override __.RegIDToString _ = Utils.futureFeature () override __.RegIDToRegType _ = Utils.futureFeature () @@ -52,6 +50,6 @@ type EVMRegisterBay () = override __.ProgramCounter = Utils.futureFeature () override __.StackPointer = Utils.futureFeature () override __.FramePointer = Utils.futureFeature () - override __.IsProgramCounter _ = false - override __.IsStackPointer _ = false - override __.IsFramePointer _ = false + override __.IsProgramCounter _ = Utils.futureFeature () + override __.IsStackPointer _ = Utils.futureFeature () + override __.IsFramePointer _ = Utils.futureFeature () diff --git a/src/FrontEnd/BinLifter/AVR/AVRRegisterSet.fs b/src/FrontEnd/BinLifter/AVR/AVRRegisterSet.fs new file mode 100644 index 00000000..55320db9 --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVRRegisterSet.fs @@ -0,0 +1,151 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.AVR + +open B2R2 + +module private RegisterSetLiteral = + let [] arrLen = 2 + +open RegisterSetLiteral + +type AVRRegisterSet (bitArray: uint64 [], s: Set) = + inherit NonEmptyRegisterSet (bitArray, s) + + new () = + AVRRegisterSet (RegisterSet.MakeInternalBitArray arrLen, Set.empty) + + override __.Tag = RegisterSetTag.AVR + + override __.ArrSize = arrLen + + override __.New arr s = new AVRRegisterSet (arr, s) :> RegisterSet + + override __.RegIDToIndex rid = + match Register.ofRegID rid with + | R.R0 -> 0 + | R.R1 -> 1 + | R.R2 -> 2 + | R.R3 -> 3 + | R.R4 -> 4 + | R.R5 -> 5 + | R.R6 -> 6 + | R.R7 -> 7 + | R.R8 -> 8 + | R.R9 -> 9 + | R.R10 -> 10 + | R.R11 -> 11 + | R.R12 -> 12 + | R.R13 -> 13 + | R.R14 -> 14 + | R.R15 -> 15 + | R.R16 -> 16 + | R.R17 -> 17 + | R.R18 -> 18 + | R.R19 -> 19 + | R.R20 -> 20 + | R.R21 -> 21 + | R.R22 -> 22 + | R.R23 -> 23 + | R.R24 -> 24 + | R.R25 -> 25 + | R.R26 -> 26 + | R.R27 -> 27 + | R.R28 -> 28 + | R.R29 -> 29 + | R.R30 -> 30 + | R.R31 -> 31 + | R.X -> 32 + | R.Y -> 33 + | R.Z -> 34 + | R.IF -> 35 + | R.TF -> 36 + | R.HF -> 37 + | R.SF -> 38 + | R.VF -> 39 + | R.NF -> 40 + | R.ZF -> 41 + | R.CF -> 42 + | R.PC -> 43 + | R.SP -> 44 + | _ -> -1 + + override __.IndexToRegID index = + match index with + | 0 -> R.R0 + | 1 -> R.R1 + | 2 -> R.R2 + | 3 -> R.R3 + | 4 -> R.R4 + | 5 -> R.R5 + | 6 -> R.R6 + | 7 -> R.R7 + | 8 -> R.R8 + | 9 -> R.R9 + | 10 -> R.R10 + | 11 -> R.R11 + | 12 -> R.R12 + | 13 -> R.R13 + | 14 -> R.R14 + | 15 -> R.R15 + | 16 -> R.R16 + | 17 -> R.R17 + | 18 -> R.R18 + | 19 -> R.R19 + | 20 -> R.R20 + | 21 -> R.R21 + | 22 -> R.R22 + | 23 -> R.R23 + | 24 -> R.R24 + | 25 -> R.R25 + | 26 -> R.R26 + | 27 -> R.R27 + | 28 -> R.R28 + | 29 -> R.R29 + | 30 -> R.R30 + | 31 -> R.R31 + | 32 -> R.X + | 33 -> R.Y + | 34 -> R.Z + | 35 -> R.IF + | 36 -> R.TF + | 37 -> R.HF + | 38 -> R.SF + | 39 -> R.VF + | 40 -> R.NF + | 41 -> R.ZF + | 42 -> R.CF + | 43 -> R.PC + | 44 -> R.SP + | _ -> Utils.impossible () + |> Register.toRegID + + override __.ToString () = + sprintf "AVRRegisterSet<%x, %x>" __.BitArray.[0] __.BitArray.[1] + +[] +module AVRRegisterSet = + let singleton rid = AVRRegisterSet().Add(rid) + let empty = AVRRegisterSet () :> RegisterSet diff --git a/src/FrontEnd/BinLifter/AVR/AVRTypes.fs b/src/FrontEnd/BinLifter/AVR/AVRTypes.fs new file mode 100644 index 00000000..06dacc10 --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVRTypes.fs @@ -0,0 +1,319 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.AVR + +open B2R2 +open System.Runtime.CompilerServices + +[] +do () + +type Opcode = + /// Add with Carry + | ADC = 0 + /// Add without Carry + | ADD = 1 + /// Add immediate to Word + | ADIW = 2 + /// Logical AND + | AND = 3 + /// Logical AND with Immediate + | ANDI = 4 + /// Arithmetic Shift Right + | ASR = 5 + /// Bit Clear in SREG + | BCLR = 6 + /// Bit Load from the T Flag in SREG to a Bit in Register + | BLD = 7 + /// Branch if Bit in SREG is Cleared + | BRBC = 8 + /// Branch if Bit in SREG is Set + | BRBS = 9 + /// Branch if Carry Cleared + | BRCC = 10 + /// Branch if Carry Se + | BRCS = 11 + /// Break + | BREAK = 12 + /// Branch if Equal + | BREQ = 13 + /// Branch if Greater or Equal (Signed) + | BRGE = 14 + /// Branch if Half Carry Flag is Cleared + | BRHC = 15 + /// Branch if Half Carry Flag is Set + | BRHS = 16 + /// Branch if GLobal Interrupt is Disabled + | BRID = 17 + /// Branch if Global Interrupt is Enabled + | BRIE = 18 + /// Branch is Lower (Unsigned) + | BRLAO = 19 + /// Branch if Less Than (Signed) + | BRLT = 20 + /// Branch if Minus + | BRMI = 21 + /// Branch if Not Equal + | BRNE = 22 + /// Branch if Plus + | BRPL = 23 + /// Branch if Same or Higher (Unsigned) + | BRSH = 24 + /// Branch if the T Flag is Cleared + | BRTC = 25 + /// Branch if the T Flag is Set + | BRTS = 26 + /// Branch if Overflow Cleared + | BRVC = 27 + /// Branch if Overflow Set + | BRVS = 28 + /// Bit Set in SREG + | BSET = 29 + /// Bit Store from Bit in Register to T Flag in SREG + | BST = 30 + /// Long Call to a Subroutine + | CALL = 31 + /// Clear Bit in I/O Register + | CBI = 32 + /// Clear Bits in Register + | CBR = 33 + /// Clear Carry Flag + | CLC = 34 + /// Clear Half Carry Flag + | CLH = 35 + /// Clear Global Interrup Flag + | CLI = 36 + /// Clear Negative Flag + | CLN = 37 + /// Clear Register + | CLR = 38 + /// Clear Signed Flag + | CLS = 39 + /// Clear T Flag + | CLT = 40 + /// Clear Overflow Flag + | CLV = 41 + /// Clear Zero Flag + | CLZ = 42 + /// One's Complement + | COM = 43 + /// Compare + | CP = 44 + /// Compare with Carry + | CPC = 45 + /// Compare with Immediate + | CPI = 46 + /// Compare Skip if Equal + | CPSE = 47 + /// Decrement + | DEC = 48 + /// Data Encryption Standard + | DES = 49 + /// Extended Indirect Call to Subroutine + | EICALL = 50 + /// Extended Indirect Jump + | EIJMP = 51 + /// Extended Load Program Memory + | ELPM = 52 + /// Exclusive OR + | EOR = 53 + /// Fractional Multiply Unsigned + | FMUL = 54 + /// Fractional Multiply Signed + | FMULS = 55 + /// Fractional Multiply SIgned with Unsigned + | FMULSU = 56 + /// Indirect Call to Subroutine + | ICALL = 57 + /// Indirect Jump + | IJMP = 58 + /// Load an I/O Location to Register + | IN = 59 + /// Increment + | INC = 60 + /// Jump + | JMP = 61 + /// Load and Clear + | LAC = 62 + /// Load and Set + | LAS = 63 + /// Load and Toggle + | LAT = 64 + /// Load Indirect from Data Space to Register using Index Y and Index Z + | LDD = 65 + /// Load Immediate + | LDI = 66 + /// Load Direct from Data Space + | LDS = 67 + /// Load Program Memory + | LPM = 68 + /// Logical Shift Left + | LSL = 69 + /// Logical Shift Right + | LSR = 70 + /// Copy Register + | MOV = 71 + /// Copy Register Word + | MOVW = 72 + /// Multiply Unsigned + | MUL = 73 + /// Multiply Signed + | MULS = 74 + /// Multiple Signed with Unsigned + | MULSU = 75 + /// Two's Complement + | NEG = 76 + /// No Operation + | NOP = 77 + /// Logical OR + | OR = 78 + /// Logical OR with Immediate + | ORI = 79 + /// Store Register to I/O Location + | OUT = 80 + /// Pop Register from Stack + | POP = 81 + /// Push Register on Stack + | PUSH = 82 + /// Relative Call to Subroutine + | RCALL = 83 + /// Return from Subroutine + | RET = 84 + /// Return from Interrupt + | RETI = 85 + /// Relative Jump + | RJMP = 86 + /// Rotate Left through Carry + | ROL = 87 + /// Roatate Right through Carry + | ROR = 88 + /// Subtract with Carry + | SBC = 89 + /// Subtract Immediate with Carry SBI - Set Bit in I/O Register + | SBCI = 90 + /// Set Bit in I/O Register + | SBI = 91 + /// Skip if Bit in I/O Register is Cleared + | SBIC = 92 + /// Skip if Bit in I/O Register is Set + | SBIS = 93 + /// Subtract Immediate from Word + | SBIW = 94 + /// Set Bits in Register + | SBR = 95 + /// Skip if Bit in Register is Cleared + | SBRC = 96 + /// Skip if Bit in Register is Set + | SBRS = 97 + /// Set Carry Flag + | SEC = 98 + /// Set Half Carry Flag + | SEH = 99 + /// Set Global Interrupt Flag + | SEI = 100 + /// Set Negative Flag + | SEN = 101 + /// Set all Bits in Register + | SER = 102 + /// Set Signed Flag + | SES = 103 + /// Set T Flag + | SET = 104 + /// Set Overflow Flag + | SEV = 105 + /// Set Zero Flag + | SEZ = 106 + /// Sets the circuit in sleep mode + | SLEEP = 107 + /// Store Program Memory *** + | SPM = 108 + /// Store Indirect From Register to Data Space using Index Y and Index Z *** + | STD = 109 + /// Store Direct to Data Space *** + | STS = 110 + /// Subtract without Carry + | SUB = 111 + /// Subtract Immediate + | SUBI = 112 + /// Swap Nibbles + | SWAP = 113 + /// Test for Zero or Minus + | TST = 114 + /// Watchdog Reset + | WDR = 115 + /// Exchange + | XCH = 116 + /// Load Indirect from Data Space to Register using Index X + | LD = 117 + /// Store Indirect From Register to Data Space using Index X + | ST = 118 + /// Invalid Op code + | InvalidOp = 119 + +type Const = int32 + +type AddressingMode = + | DispMode of Register * Const + | PreIdxMode of Register + | PostIdxMode of Register + | UnchMode of Register + +type Operand = + | OprReg of Register + | OprImm of Const + | OprAddr of Const + | OprMemory of AddressingMode + +type Operands = + | NoOperand + | OneOperand of Operand + | TwoOperands of Operand * Operand + +/// Basic information obtained by parsing a AVR instruction. +[] +type InsInfo = { + /// Address. + Address: Addr + /// Instruction length. + NumBytes: uint32 + /// Opcode. + Opcode: Opcode + /// Operands + Operands: Operands +} +with + override __.GetHashCode () = + hash (__.Address, + __.NumBytes, + __.Opcode) + override __.Equals (i) = + match i with + | :? InsInfo as i -> + i.Address = __.Address + && i.NumBytes = __.NumBytes + && i.Opcode = __.Opcode + | _ -> false + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/AVR/B2R2.FrontEnd.BinLifter.AVR.fsproj b/src/FrontEnd/BinLifter/AVR/B2R2.FrontEnd.BinLifter.AVR.fsproj new file mode 100644 index 00000000..16ca057b --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/B2R2.FrontEnd.BinLifter.AVR.fsproj @@ -0,0 +1,35 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 AVR frontend. + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FrontEnd/BinLifter/AVR/README.md b/src/FrontEnd/BinLifter/AVR/README.md new file mode 100644 index 00000000..feda1f9c --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/README.md @@ -0,0 +1,11 @@ +# B2R2.FrontEnd.BinLifter.AVR + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.BinLifter.AVR Package? + +`B2R2.FrontEnd.BinLifter.AVR` includes AVR parsers and lifters. diff --git a/src/FrontEnd/BinLifter/CIL/B2R2.FrontEnd.BinLifter.CIL.fsproj b/src/FrontEnd/BinLifter/CIL/B2R2.FrontEnd.BinLifter.CIL.fsproj new file mode 100644 index 00000000..a5b92ce8 --- /dev/null +++ b/src/FrontEnd/BinLifter/CIL/B2R2.FrontEnd.BinLifter.CIL.fsproj @@ -0,0 +1,29 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 CIL frontend. + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FrontEnd/ARM32/ARM32.fs b/src/FrontEnd/BinLifter/CIL/CIL.fs similarity index 67% rename from src/FrontEnd/ARM32/ARM32.fs rename to src/FrontEnd/BinLifter/CIL/CIL.fs index d9cf814c..105a7637 100644 --- a/src/FrontEnd/ARM32/ARM32.fs +++ b/src/FrontEnd/BinLifter/CIL/CIL.fs @@ -22,23 +22,32 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.ARM32 +namespace B2R2.FrontEnd.BinLifter.CIL -open B2R2.FrontEnd +open B2R2 +open B2R2.FrontEnd.BinLifter -/// Translation context for 32-bit ARM instructions. -type ARM32TranslationContext (isa) = +type CILTranslationContext internal (isa, regexprs) = inherit TranslationContext (isa) - member val private RegExprs: RegExprs = RegExprs () + + /// Register expressions. + member val private RegExprs: RegExprs = regexprs + override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar - override __.GetPseudoRegVar _id _pos = failwith "Implement" // XXX -/// Parser for 32-bit ARM instructions. Parser will return a platform-agnostic -/// instruction type (Instruction). -type ARM32Parser (arch) = - inherit Parser () - override __.Parse reader ctxt addr pos = - Parser.parse reader ctxt arch addr pos - :> Instruction + override __.GetPseudoRegVar _id _pos = Utils.impossible () -// vim: set tw=80 sts=2 sw=2: +type CILParser () = + inherit Parser () + override __.Parse binReader addr pos = + Utils.futureFeature () + + override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () + +module Basis = + let init isa = + let regexprs = RegExprs () + struct ( + CILTranslationContext (isa, regexprs) :> TranslationContext, + CILRegisterBay () :> RegisterBay + ) diff --git a/src/FrontEnd/BinLifter/CIL/CILInstruction.fs b/src/FrontEnd/BinLifter/CIL/CILInstruction.fs new file mode 100644 index 00000000..2379c267 --- /dev/null +++ b/src/FrontEnd/BinLifter/CIL/CILInstruction.fs @@ -0,0 +1,59 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.CIL + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// The internal representation for a CIL instruction used by our disassembler +/// and lifter. +type CILInstruction (addr, numBytes, wordSize) = + inherit Instruction (addr, numBytes, wordSize) + + override __.IsBranch () = Utils.futureFeature () + override __.IsModeChanging () = false + override __.IsDirectBranch () = Utils.futureFeature () + override __.IsIndirectBranch () = Utils.futureFeature () + override __.IsCondBranch () = Utils.futureFeature () + override __.IsCJmpOnTrue () = Utils.futureFeature () + override __.IsCall () = Utils.futureFeature () + override __.IsRET () = Utils.futureFeature () + override __.IsInterrupt () = Utils.futureFeature () + override __.IsExit () = Utils.futureFeature () + override __.IsBBLEnd () = Utils.futureFeature () + override __.DirectBranchTarget (_) = Utils.futureFeature () + override __.IndirectTrampolineAddr (_) = Utils.futureFeature () + override __.Immediate (_) = Utils.futureFeature () + override __.GetNextInstrAddrs () = Utils.futureFeature () + override __.InterruptNum (_) = Utils.futureFeature () + override __.IsNop () = Utils.futureFeature () + override __.Translate (_) = Utils.futureFeature () + override __.Disasm (_, _, _) = Utils.futureFeature () + override __.Disasm () = Utils.futureFeature () + override __.Decompose (_) = Utils.futureFeature () + override __.IsInlinedAssembly () = false + + override __.Equals (_) = Utils.futureFeature () + override __.GetHashCode () = Utils.futureFeature () diff --git a/src/ConcEval/Labels.fs b/src/FrontEnd/BinLifter/CIL/CILRegExprs.fs similarity index 71% rename from src/ConcEval/Labels.fs rename to src/FrontEnd/BinLifter/CIL/CILRegExprs.fs index d6f407c4..125ec1a2 100644 --- a/src/ConcEval/Labels.fs +++ b/src/FrontEnd/BinLifter/CIL/CILRegExprs.fs @@ -22,21 +22,19 @@ SOFTWARE. *) -namespace B2R2.ConcEval +namespace B2R2.FrontEnd.BinLifter.CIL -open B2R2.BinIR +open B2R2 open B2R2.BinIR.LowUIR -open System.Collections.Generic -/// Store labels of LowUIR statements. -type Labels () = - let lbls = Dictionary () +type internal RegExprs () = + let var sz t name = AST.var sz t name (CILRegisterSet.singleton t) - member __.Update (stmts) = - lbls.Clear () - for i = 0 to Array.length stmts - 1 do - match stmts.[i] with - | LMark s -> lbls.Add (s, i) - | _ -> () + member val PC = var 256 (Register.toRegID Register.PC) "PC" with get + member val SP = var 256 (Register.toRegID Register.SP) "SP" with get - member __.Index (sym) = lbls.[sym] + member __.GetRegVar (name) = + match name with + | Register.PC -> __.PC + | Register.SP -> __.SP + | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException diff --git a/src/FrontEnd/BinLifter/CIL/CILRegisterBay.fs b/src/FrontEnd/BinLifter/CIL/CILRegisterBay.fs new file mode 100644 index 00000000..5cba2e53 --- /dev/null +++ b/src/FrontEnd/BinLifter/CIL/CILRegisterBay.fs @@ -0,0 +1,76 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.CIL + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR.LowUIR + +type CILRegisterBay () = + + inherit RegisterBay () + + override __.GetAllRegExprs () = Utils.futureFeature () + + override __.GetAllRegNames () = [] + + override __.GetGeneralRegExprs () = Utils.futureFeature () + + override __.RegIDFromRegExpr (e) = + match e.E with + | Var (_, id, _ ,_) -> id + | PCVar (_, _) -> Register.toRegID Register.PC + | _ -> failwith "not a register expression" + + override __.RegIDToRegExpr (id) = Utils.impossible () + + override __.StrToRegExpr _s = Utils.impossible () + + override __.RegIDFromString str = + Register.ofString str |> Register.toRegID + + override __.RegIDToString rid = + Register.ofRegID rid |> Register.toString + + override __.RegIDToRegType rid = + Register.ofRegID rid |> Register.toRegType + + override __.GetRegisterAliases _ = Utils.futureFeature () + + override __.ProgramCounter = + Register.PC |> Register.toRegID + + override __.StackPointer = + Register.SP |> Register.toRegID |> Some + + override __.FramePointer = Utils.futureFeature () + + override __.IsProgramCounter regid = + __.ProgramCounter = regid + + override __.IsStackPointer regid = + (__.StackPointer |> Option.get) = regid + + override __.IsFramePointer _ = false diff --git a/src/BinEssence/VisualBlock.fs b/src/FrontEnd/BinLifter/CIL/CILRegisterSet.fs similarity index 60% rename from src/BinEssence/VisualBlock.fs rename to src/FrontEnd/BinLifter/CIL/CILRegisterSet.fs index 4bcbb9b9..17e1f98a 100644 --- a/src/BinEssence/VisualBlock.fs +++ b/src/FrontEnd/BinLifter/CIL/CILRegisterSet.fs @@ -22,27 +22,31 @@ SOFTWARE. *) -namespace B2R2.BinEssence +namespace B2R2.FrontEnd.BinLifter.CIL open B2R2 -open B2R2.FrontEnd -/// A visual line of a basic block. -type VisualLine = AsmWord [] +type CILRegisterSet (bitArray: uint64 [], s: Set) = + inherit NonEmptyRegisterSet (bitArray, s) -module VisualLine = - [] - let lineWidth terms = - terms |> Array.fold (fun width term -> width + AsmWord.Width term) 0 + new () = CILRegisterSet (RegisterSet.MakeInternalBitArray 2, Set.empty) - [] - let toString terms = - terms |> Array.map AsmWord.ToString |> String.concat " " + override __.Tag = RegisterSetTag.CIL -/// A visual representation of a basic block. -type VisualBlock = VisualLine [] + override __.ArrSize = 2 -module VisualBlock = - let empty (addr: Addr): VisualBlock = - [| [|{ AsmWordKind = AsmWordKind.String - AsmWordValue = "# fake block @ " + (addr.ToString ("X")) }|] |] + override __.New arr s = new CILRegisterSet (arr, s) :> RegisterSet + + override __.RegIDToIndex rid = + Register.ofRegID rid |> int + + override __.IndexToRegID index = + LanguagePrimitives.Int32WithMeasure index + + override __.ToString () = + sprintf "CILReisterSet<%x, %x>" __.BitArray.[0] __.BitArray.[1] + +[] +module CILRegisterSet = + let singleton rid = CILRegisterSet().Add(rid) + let empty = CILRegisterSet () :> RegisterSet diff --git a/src/Core/RegisterSet.fsi b/src/FrontEnd/BinLifter/CIL/CILTypes.fs similarity index 57% rename from src/Core/RegisterSet.fsi rename to src/FrontEnd/BinLifter/CIL/CILTypes.fs index bb3a9992..aece7faf 100644 --- a/src/Core/RegisterSet.fsi +++ b/src/FrontEnd/BinLifter/CIL/CILTypes.fs @@ -22,33 +22,40 @@ SOFTWARE. *) -namespace B2R2 +namespace B2R2.FrontEnd.BinLifter.CIL open B2R2 -/// RegisterSet is an efficient representation for managing a set of registers. -[] -[] -module RegisterSet = - - /// Returns an empty RegisterSet. - val empty : RegisterSet - - /// Make a union of two register sets. - val inline union : RegisterSet -> RegisterSet -> RegisterSet - - /// Make an intersection of two register sets. - val inline intersect : RegisterSet -> RegisterSet -> RegisterSet - - /// Remove a register from the register set. - val inline remove : RegisterID -> RegisterSet -> RegisterSet - - /// Add a register from the register set. - val inline add : RegisterID -> RegisterSet -> RegisterSet - - /// Check the existence of a register in the register set. - val inline exist : RegisterID -> RegisterSet -> bool - - /// Is the register set empty? - val inline isEmpty : RegisterSet -> bool +type Register = + /// Program counter. + | PC = 0x0 + /// Stack pointer. + | SP = 0x1 +/// This module exposes several useful functions to handle CIL registers. +[] +module Register = + let inline ofRegID (n: RegisterID): Register = + int n |> LanguagePrimitives.EnumOfValue + + let inline toRegID (reg: Register) = + LanguagePrimitives.EnumToValue (reg) |> RegisterID.create + + let ofString (str: string) = + match str.ToLower () with + | "pc" -> Register.PC + | "sp" -> Register.SP + | _ -> Utils.impossible () + + let toString = function + | Register.PC -> "PC" + | Register.SP -> "SP" + | _ -> Utils.impossible () + + let toRegType = function + | Register.PC -> 64 + | Register.SP -> 64 + | _ -> Utils.impossible () + +/// Shortcut for Register type. +type internal R = Register diff --git a/src/FrontEnd/BinLifter/CIL/README.md b/src/FrontEnd/BinLifter/CIL/README.md new file mode 100644 index 00000000..7daf01b8 --- /dev/null +++ b/src/FrontEnd/BinLifter/CIL/README.md @@ -0,0 +1,11 @@ +# B2R2.FrontEnd.BinLifter.CIL + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.BinLifter.CIL Package? + +`B2R2.FrontEnd.BinLifter.CIL` includes CIL parsers and lifters. diff --git a/src/FrontEnd/Core/AsmWord.fs b/src/FrontEnd/BinLifter/Core/AsmWord.fs similarity index 98% rename from src/FrontEnd/Core/AsmWord.fs rename to src/FrontEnd/BinLifter/Core/AsmWord.fs index 38488dd9..44e73e6b 100644 --- a/src/FrontEnd/Core/AsmWord.fs +++ b/src/FrontEnd/BinLifter/Core/AsmWord.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd +namespace B2R2.FrontEnd.BinLifter open System.Collections diff --git a/src/FrontEnd/BinLifter/Core/B2R2.FrontEnd.BinLifter.Core.fsproj b/src/FrontEnd/BinLifter/Core/B2R2.FrontEnd.BinLifter.Core.fsproj new file mode 100644 index 00000000..5a63b48c --- /dev/null +++ b/src/FrontEnd/BinLifter/Core/B2R2.FrontEnd.BinLifter.Core.fsproj @@ -0,0 +1,32 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 frontend core. + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FrontEnd/BinLifter/Core/DisasmHelper.fs b/src/FrontEnd/BinLifter/Core/DisasmHelper.fs new file mode 100644 index 00000000..7aac11c7 --- /dev/null +++ b/src/FrontEnd/BinLifter/Core/DisasmHelper.fs @@ -0,0 +1,77 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter + +open System.Text +open B2R2 + +type DisasmHelper (?fn: Addr -> Result) = + let helper = + match fn with + | Some fn -> fn + | None -> fun _ -> Error ErrorCase.SymbolNotFound + + member __.FindFunctionSymbol (addr: Addr) = helper addr + +[] +type DisasmBuilder<'Result> (showAddr, resolveSymb, wordSz, addr, len) = + abstract member Accumulate: AsmWordKind -> string -> unit + abstract member AccumulateAddr: unit -> unit + abstract member Finalize: unit -> 'Result + member __.ShowAddr with get(): bool = showAddr + member __.ResolveSymbol with get(): bool = resolveSymb + member __.WordSize with get(): WordSize = wordSz + member __.Address with get(): Addr = addr + member __.InsLength with get(): uint32 = len + +type DisasmStringBuilder (showAddr, resolveSymb, wordSz, addr, len) = + inherit DisasmBuilder (showAddr, resolveSymb, wordSz, addr, len) + + let sb = StringBuilder () + + override __.Accumulate _kind s = + sb.Append (s) |> ignore + + override __.AccumulateAddr () = + sb.Append (Addr.toString wordSz addr) |> ignore + sb.Append (": ") |> ignore + + override __.Finalize () = sb.ToString () + +type DisasmWordBuilder (showAddr, resolveSymb, wordSz, addr, len, n) = + inherit DisasmBuilder (showAddr, resolveSymb, wordSz, addr, len) + + let ab = AsmWordBuilder (n) + + override __.Accumulate kind s = + ab.Append ({ AsmWordKind = kind; AsmWordValue = s }) |> ignore + + override __.AccumulateAddr () = + ab.Append ({ AsmWordKind = AsmWordKind.Address + AsmWordValue = Addr.toString wordSz addr }) |> ignore + ab.Append ({ AsmWordKind = AsmWordKind.String + AsmWordValue = ": " }) |> ignore + + override __.Finalize () = ab.Finish () diff --git a/src/FrontEnd/Core/Exceptions.fs b/src/FrontEnd/BinLifter/Core/Exceptions.fs similarity index 98% rename from src/FrontEnd/Core/Exceptions.fs rename to src/FrontEnd/BinLifter/Core/Exceptions.fs index 247d5b4f..1dd1bc3d 100644 --- a/src/FrontEnd/Core/Exceptions.fs +++ b/src/FrontEnd/BinLifter/Core/Exceptions.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd +namespace B2R2.FrontEnd.BinLifter /// The IR is not implemented yet. exception NotImplementedIRException of string diff --git a/src/FrontEnd/Core/StmtBuilder.fs b/src/FrontEnd/BinLifter/Core/IRBuilder.fs similarity index 73% rename from src/FrontEnd/Core/StmtBuilder.fs rename to src/FrontEnd/BinLifter/Core/IRBuilder.fs index 1d75371c..b9452f00 100644 --- a/src/FrontEnd/Core/StmtBuilder.fs +++ b/src/FrontEnd/BinLifter/Core/IRBuilder.fs @@ -22,21 +22,41 @@ SOFTWARE. *) -namespace B2R2.FrontEnd +namespace B2R2.FrontEnd.BinLifter open System.Collections open B2R2.BinIR.LowUIR -/// StmtBuilder accumulates IR statements while lifting, and emits them into an +/// IRBuilder accumulates IR statements while lifting, and emits them into an /// array of statements at the end of a lifting process. -type StmtBuilder = +type IRBuilder = inherit Generic.List + val mutable TempVarCount: int + val mutable LabelCount: int + /// /// Initialize an IR statement builder of internal buffer size n. /// /// The size of the internal buffer. - new (n: int) = { inherit Generic.List(n) } + new (n: int) = + { inherit Generic.List(n) + TempVarCount = 0 + LabelCount = 0 } + + /// + /// Create a new temporary variable of RegType (rt). + /// + member inline __.NewTempVar rt = + __.TempVarCount <- __.TempVarCount + 1 + AST.tmpvar rt __.TempVarCount + + /// + /// Create a new symbol for a label. + /// + member inline __.NewSymbol name = + __.LabelCount <- __.LabelCount + 1 + AST.symbol name __.LabelCount /// /// Append a new IR statement to the builder. diff --git a/src/FrontEnd/Core/Instruction.fs b/src/FrontEnd/BinLifter/Core/Instruction.fs similarity index 83% rename from src/FrontEnd/Core/Instruction.fs rename to src/FrontEnd/BinLifter/Core/Instruction.fs index bcc3f65f..146d8888 100644 --- a/src/FrontEnd/Core/Instruction.fs +++ b/src/FrontEnd/BinLifter/Core/Instruction.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd +namespace B2R2.FrontEnd.BinLifter open B2R2 open B2R2.BinIR.LowUIR @@ -34,7 +34,7 @@ open System.Runtime.InteropServices /// useful information about the instruction. /// [] -type Instruction (addr, numBytes, wordSize) = +type Instruction (addr, len, wordSize) = /// /// The address of this instruction. /// @@ -43,7 +43,7 @@ type Instruction (addr, numBytes, wordSize) = /// /// The length of this instruction in bytes. /// - member val Length: uint32 = numBytes + member val Length: uint32 = len /// /// The word size used for translating this instruction. Some architectures @@ -54,28 +54,6 @@ type Instruction (addr, numBytes, wordSize) = /// member val WordSize: WordSize = wordSize - /// - /// Parsing context of the next instruction. Sometimes the way we parse a - /// binary instruction chanages based on prior instructions we observed so - /// far. We propagate such information through Instructions. The next - /// instruction here means either the fall-through instruction or the jump - /// target instruction. That is, we always follow the control flow and refer - /// to the previous instruction from the control flow to decide the parsing - /// behavior. - /// - abstract member NextParsingContext: ParsingContext - - /// - /// Auxiliary parsing context that can be used to parse the next - /// instruction. This is particularly useful when an instruction has two - /// different parsing context depending on the jump target. For example, BLX - /// instruction of ARM produces two CFG edges, and each edge should have - /// different ArchOperationMode (one is Thumb and the other is ARM). In this - /// case, AuxParsingContext contains the parsing context when we follow the - /// fall-through edge. - /// - abstract member AuxParsingContext: ParsingContext option - /// /// Is this a branch instruction? A branch instruction includes any kinds of /// jump instructions, such as CALL/RET instructions, indirect/direct jump @@ -86,6 +64,15 @@ type Instruction (addr, numBytes, wordSize) = /// abstract member IsBranch: unit -> bool + /// + /// Is this a mode-changing instruction? In ARMv7, BLX is such an + /// instruction. + /// + /// + /// Returns true if this is a mode-changing instruction. + /// + abstract member IsModeChanging: unit -> bool + /// /// Is this a direct branch instruction? A direct branch instruction is a /// branch instruction with a concrete jump target, which is inscribed in @@ -152,9 +139,10 @@ type Instruction (addr, numBytes, wordSize) = abstract member IsInterrupt: unit -> bool /// - /// Does this instruction exit a basic block? For example, this function - /// returns true for the HLT instruction of Intel. We also consider - /// system call instructions as an exit instruction. + /// Does this instruction exits the program execution? For example, this + /// function returns true for the HLT instruction of Intel. We also + /// consider returning from kernel mode to user mode (e.g. SYSEXIT + /// instruction of Intel) as an exit. /// /// /// Returns true if this instruction should be at the end of the @@ -162,6 +150,17 @@ type Instruction (addr, numBytes, wordSize) = /// abstract member IsExit: unit -> bool + /// + /// Does this instruction end a basic block? For example, this function + /// returns true for branch instructions and exit instructions. We also + /// consider system call instructions as an end of basic blocks. + /// + /// + /// Returns true if this instruction should be at the end of the + /// corresponding basic block. + /// + abstract member IsBBLEnd: unit -> bool + /// /// Is this a NO-OP instruction? /// @@ -190,6 +189,15 @@ type Instruction (addr, numBytes, wordSize) = /// abstract member IndirectTrampolineAddr: [] addr: byref -> bool + /// + /// Return an integer immediate value of the instruction if there is one. + /// This function will ignore floating-point immediate values. + /// + /// + /// Returns true if an immediate exists. Otherwise, returns false. + /// + abstract member Immediate: [] v: byref -> bool + /// /// Return a sequence of possible next instruction addresses along with /// their ArchOperationMode. For branch instructions, the returned sequence @@ -225,8 +233,8 @@ type Instruction (addr, numBytes, wordSize) = /// show the target function name if this parameter is true, and the symbol /// information exists. /// - /// - /// File information that this instruction resides in. + /// + /// The helper allows our disassembler to resolve symbols. /// /// /// Returns a disassembled string. @@ -234,7 +242,7 @@ type Instruction (addr, numBytes, wordSize) = abstract member Disasm: showAddr: bool * resolveSymbol: bool - * fileInfo: BinFile.FileInfo + * disasmHelper: DisasmHelper -> string /// @@ -251,6 +259,8 @@ type Instruction (addr, numBytes, wordSize) = /// /// Returns an array of AsmWords. /// - abstract member Decompose: unit -> AsmWord [] + abstract member Decompose: bool -> AsmWord [] + + abstract member IsInlinedAssembly: unit -> bool // vim: set tw=80 sts=2 sw=2: diff --git a/src/DataFlow/Utils.fs b/src/FrontEnd/BinLifter/Core/LiftingOperators.fs similarity index 51% rename from src/DataFlow/Utils.fs rename to src/FrontEnd/BinLifter/Core/LiftingOperators.fs index afe10797..bf8562a5 100644 --- a/src/DataFlow/Utils.fs +++ b/src/FrontEnd/BinLifter/Core/LiftingOperators.fs @@ -22,38 +22,33 @@ SOFTWARE. *) -module B2R2.DataFlow.Utils +module B2R2.FrontEnd.BinLifter.LiftingOperators open B2R2.BinIR.LowUIR -let rec private extractUseFromExpr = function - | Var (_, id, _, _) -> [ Regular id ] - | TempVar (_, n) -> [ Temporary n ] - | UnOp (_, e, _, _) -> extractUseFromExpr e - | BinOp (_, _, e1, e2, _, _) -> extractUseFromExpr e1 @ extractUseFromExpr e2 - | RelOp (_, e1, e2, _, _) -> extractUseFromExpr e1 @ extractUseFromExpr e2 - | Load (_, _, e, _, _) -> extractUseFromExpr e - | Ite (c, e1, e2, _, _) -> - extractUseFromExpr c @ extractUseFromExpr e1 @ extractUseFromExpr e2 - | Cast (_, _, e, _, _) -> extractUseFromExpr e - | Extract (e, _, _, _, _) -> extractUseFromExpr e - | _ -> [] - -let private extractUseFromStmt = function - | Put (_, e) - | Store (_, _, e) - | Jmp (e) - | CJmp (e, _, _) - | InterJmp (_, e, _) -> extractUseFromExpr e - | InterCJmp (c, _, e1, e2) -> - extractUseFromExpr c @ extractUseFromExpr e1 @ extractUseFromExpr e2 - | _ -> [] - -let extractUses stmt = - extractUseFromStmt stmt - |> Set.ofList - -let filterRegularVars vars = - vars |> Set.filter (function - | Regular _ -> true - | _ -> false) +/// This is the special operator that we use for writing a lifter. There are +/// several major operators we use including this one. This one simply appends a +/// statement to the IRBuilder. We always put a IRBuilder variable immediately +/// after each operator without any space to make it visually distinct. For +/// example, for a builder variable "ir", we write a lifting logic as follows: +/// !ir insAddr insLen +let inline ( !! ) (ir: IRBuilder) (s) = ir.Append s + +/// The special operator for creating a temporary variable. +let inline ( !* ) (ir: IRBuilder) rt = ir.NewTempVar rt + +/// The special operator for starting an instruction (ISMark). +let inline ( !< ) (ir: IRBuilder) insLen = + ir.Append (AST.ismark insLen) + +/// The special operator for finishing an instruction (IEMark). +let inline ( !> ) (ir: IRBuilder) (insLen: uint32) = + ir.Append (AST.iemark insLen) + ir + +/// The special operator for applying a function with a IRBuilder as input. +let inline ( !? ) (ir: IRBuilder) fn = + fn ir diff --git a/src/FrontEnd/Core/ParseUtils.fs b/src/FrontEnd/BinLifter/Core/ParseUtils.fs similarity index 97% rename from src/FrontEnd/Core/ParseUtils.fs rename to src/FrontEnd/BinLifter/Core/ParseUtils.fs index 95804c92..48559d57 100644 --- a/src/FrontEnd/Core/ParseUtils.fs +++ b/src/FrontEnd/BinLifter/Core/ParseUtils.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd +namespace B2R2.FrontEnd.BinLifter /// 32-bit binary representation. type BitData32 = uint32 diff --git a/src/FrontEnd/Core/Parser.fs b/src/FrontEnd/BinLifter/Core/Parser.fs similarity index 86% rename from src/FrontEnd/Core/Parser.fs rename to src/FrontEnd/BinLifter/Core/Parser.fs index 506f086b..ff4b8d50 100644 --- a/src/FrontEnd/Core/Parser.fs +++ b/src/FrontEnd/BinLifter/Core/Parser.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd +namespace B2R2.FrontEnd.BinLifter open B2R2 @@ -30,10 +30,13 @@ open B2R2 [] type Parser () = /// Parse one instruction. - abstract member Parse : BinReader - -> ParsingContext + abstract member Parse: BinReader -> Addr -> int -> Instruction + /// The current operation mode of the Parser. This is only useful for ARMv7 + /// parsers. + abstract member OperationMode: ArchOperationMode with get, set + // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Core/README.md b/src/FrontEnd/BinLifter/Core/README.md new file mode 100644 index 00000000..dfea0bde --- /dev/null +++ b/src/FrontEnd/BinLifter/Core/README.md @@ -0,0 +1,11 @@ +# B2R2.FrontEnd.BinLifter.Core + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.BinLifter.Core Package? + +`B2R2.FrontEnd.BinLifter.Core` declares basic types used by parsers and lifters. diff --git a/src/FrontEnd/Core/RegisterBay.fs b/src/FrontEnd/BinLifter/Core/RegisterBay.fs similarity index 86% rename from src/FrontEnd/Core/RegisterBay.fs rename to src/FrontEnd/BinLifter/Core/RegisterBay.fs index 066e22e5..849fcd46 100644 --- a/src/FrontEnd/Core/RegisterBay.fs +++ b/src/FrontEnd/BinLifter/Core/RegisterBay.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd +namespace B2R2.FrontEnd.BinLifter open B2R2 open B2R2.BinIR.LowUIR @@ -43,7 +43,7 @@ type RegisterBay () = /// Return RegType from a given RegExpr. member __.RegTypeFromRegExpr (e: Expr) = - match e with + match e.E with | Var (rt, _, _ ,_) | PCVar (rt, _) -> rt | _ -> raise InvalidRegisterException @@ -51,19 +51,22 @@ type RegisterBay () = /// Return RegID from a given RegExpr. abstract member RegIDFromRegExpr: Expr -> RegisterID + /// Return RegExpr from a given RegID. + abstract member RegIDToRegExpr: RegisterID -> Expr + /// Return RegExpr from a string. abstract member StrToRegExpr: string -> Expr /// /// Return RegisterID from a given register string. Depending on the - /// underlying architecture of the BinHandler, we may have different + /// underlying architecture of the BinHandle, we may have different /// RegisterID. /// abstract member RegIDFromString: string -> RegisterID /// /// Return a register string from a given RegisterID. Depending on the - /// underlying architecture of the BinHandler, we may have a different string + /// underlying architecture of the BinHandle, we may have a different string /// result. /// abstract member RegIDToString: RegisterID -> string @@ -75,22 +78,22 @@ type RegisterBay () = /// /// Return an array of aliases of a given register based on the current - /// architecture of BinHandler. + /// architecture of BinHandle. /// abstract member GetRegisterAliases: RegisterID -> RegisterID [] /// - /// Return a program counter register for a given BinHandler. + /// Return a program counter register for a given BinHandle. /// abstract member ProgramCounter: RegisterID /// - /// Return a stack pointer register for a given BinHandler. + /// Return a stack pointer register for a given BinHandle. /// abstract member StackPointer: RegisterID option /// - /// Return a frame pointer register for a given BinHandler. + /// Return a frame pointer register for a given BinHandle. /// abstract member FramePointer: RegisterID option diff --git a/src/FrontEnd/Core/Context.fs b/src/FrontEnd/BinLifter/Core/TranslationContext.fs similarity index 56% rename from src/FrontEnd/Core/Context.fs rename to src/FrontEnd/BinLifter/Core/TranslationContext.fs index 65ad54f1..94bda62b 100644 --- a/src/FrontEnd/Core/Context.fs +++ b/src/FrontEnd/BinLifter/Core/TranslationContext.fs @@ -22,52 +22,11 @@ SOFTWARE. *) -namespace B2R2.FrontEnd +namespace B2R2.FrontEnd.BinLifter open B2R2 open B2R2.BinIR.LowUIR -/// A high-level interface for the parsing context, which stores several states -/// for parsing machine instructions. -type ParsingContext private (archMode, itstate, offset, inParallel) = - /// Target architecture mode (e.g., ARM/thumb mode). - member __.ArchOperationMode with get(): ArchOperationMode = archMode - - /// ITState for ARM. - member __.ITState with get(): byte list = itstate - - /// Indicate the address offset of the code. This is used in several - /// architectures, such as EVM, to correctly resolve jump offsets in a - /// dynamically generated code snippet. - member __.CodeOffset with get(): uint64 = offset - - /// Indicate whether the next instruction should be executed in parallel. - /// This is used by DSP architectures. - member __.InParallel with get(): bool = inParallel - - static member Init () = - ParsingContext (ArchOperationMode.NoMode, [], 0UL, false) - - static member Init (mode) = - ParsingContext (mode, [], 0UL, false) - - static member InitThumb (archMode, itstate) = - ParsingContext (archMode, itstate, 0UL, false) - - static member InitDSP (ctxt: ParsingContext, flag) = - ParsingContext (ctxt.ArchOperationMode, ctxt.ITState, ctxt.CodeOffset, flag) - - static member InitEVM (offset) = - ParsingContext (ArchOperationMode.NoMode, [], offset, false) - - static member ARMSwitchOperationMode (ctxt: ParsingContext) = - match ctxt.ArchOperationMode with - | ArchOperationMode.ARMMode -> - ParsingContext.Init (ArchOperationMode.ThumbMode) - | ArchOperationMode.ThumbMode -> - ParsingContext.Init (ArchOperationMode.ARMMode) - | _ -> Utils.impossible () - /// A high-level interface for the translation context, which stores several /// states for translating/lifting instructions. [] diff --git a/src/FrontEnd/BinLifter/EVM/B2R2.FrontEnd.BinLifter.EVM.fsproj b/src/FrontEnd/BinLifter/EVM/B2R2.FrontEnd.BinLifter.EVM.fsproj new file mode 100644 index 00000000..c53cb267 --- /dev/null +++ b/src/FrontEnd/BinLifter/EVM/B2R2.FrontEnd.BinLifter.EVM.fsproj @@ -0,0 +1,32 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 EVM frontend. + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FrontEnd/EVM/EVM.fs b/src/FrontEnd/BinLifter/EVM/EVM.fs similarity index 70% rename from src/FrontEnd/EVM/EVM.fs rename to src/FrontEnd/BinLifter/EVM/EVM.fs index 2e989466..81fedadc 100644 --- a/src/FrontEnd/EVM/EVM.fs +++ b/src/FrontEnd/BinLifter/EVM/EVM.fs @@ -22,16 +22,17 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.EVM +namespace B2R2.FrontEnd.BinLifter.EVM -open B2R2.FrontEnd +open B2R2 +open B2R2.FrontEnd.BinLifter /// Translation context for Ethereum Virtual Machine (EVM) instructions. -type EVMTranslationContext (isa) = +type EVMTranslationContext internal (isa, regexprs) = inherit TranslationContext (isa) /// Register expressions. - member val private RegExprs: RegExprs = RegExprs () + member val private RegExprs: RegExprs = regexprs override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar @@ -41,7 +42,21 @@ type EVMTranslationContext (isa) = /// instruction type (Instruction). type EVMParser (wordSize) = inherit Parser () - override __.Parse binReader ctxt addr pos = - Parser.parse binReader ctxt wordSize addr pos :> Instruction + let mutable codeOffset: Addr = 0UL + + member __.CodeOffset with get() = codeOffset and set(o) = codeOffset <- o + + override __.Parse binReader addr pos = + Parser.parse binReader codeOffset wordSize addr pos :> Instruction + + override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () + +module Basis = + let init isa = + let regexprs = RegExprs () + struct ( + EVMTranslationContext (isa, regexprs) :> TranslationContext, + EVMRegisterBay () :> RegisterBay + ) // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/EVM/EVMDisasm.fs b/src/FrontEnd/BinLifter/EVM/EVMDisasm.fs new file mode 100644 index 00000000..bf140632 --- /dev/null +++ b/src/FrontEnd/BinLifter/EVM/EVMDisasm.fs @@ -0,0 +1,184 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.EVM.Disasm + +open B2R2 +open B2R2.FrontEnd.BinLifter + +let opcodeToStrings = function + | STOP -> struct ("stop", None) + | ADD -> struct("add", None) + | MUL -> struct("mul", None) + | SUB -> struct("sub", None) + | DIV -> struct("div", None) + | SDIV -> struct("sdiv", None) + | MOD -> struct("mod", None) + | SMOD -> struct("smod", None) + | ADDMOD -> struct("addmod", None) + | MULMOD -> struct("mulmod", None) + | EXP -> struct("exp", None) + | SIGNEXTEND -> struct("signextend", None) + | LT -> struct("lt", None) + | GT -> struct("gt", None) + | SLT -> struct("slt", None) + | SGT -> struct("sgt", None) + | EQ -> struct("eq", None) + | ISZERO -> struct("iszero", None) + | AND -> struct("and", None) + | OR -> struct("or", None) + | XOR -> struct("xor", None) + | NOT -> struct("not", None) + | BYTE -> struct("byte", None) + | SHL -> struct("shl", None) + | SHR -> struct("shr", None) + | SAR -> struct("sar", None) + | SHA3 -> struct("sha3", None) + | ADDRESS -> struct("address", None) + | BALANCE -> struct("balance", None) + | ORIGIN -> struct("origin", None) + | CALLER -> struct("caller", None) + | CALLVALUE -> struct("callvalue", None) + | CALLDATALOAD -> struct("calldataload", None) + | CALLDATASIZE -> struct("calldatasize", None) + | CALLDATACOPY -> struct("calldatacopy", None) + | CODESIZE -> struct("codesize", None) + | CODECOPY -> struct("codecopy", None) + | GASPRICE -> struct("gasprice", None) + | EXTCODESIZE -> struct("extcodesize", None) + | EXTCODECOPY -> struct("extcodecopy", None) + | RETURNDATASIZE -> struct("returndatasize", None) + | RETURNDATACOPY -> struct("returndatacopy", None) + | BLOCKHASH -> struct("blockhash", None) + | COINBASE -> struct("coinbase", None) + | TIMESTAMP -> struct("timestamp", None) + | NUMBER -> struct("number", None) + | DIFFICULTY -> struct("difficulty", None) + | GASLIMIT -> struct("gaslimit", None) + | POP -> struct("pop", None) + | MLOAD -> struct("mload", None) + | MSTORE -> struct("mstore", None) + | MSTORE8 -> struct("mstore8", None) + | SLOAD -> struct("sload", None) + | SSTORE -> struct("sstore", None) + | JUMP -> struct("jump", None) + | JUMPI -> struct("jumpi", None) + | GETPC -> struct("getpc", None) + | MSIZE -> struct("msize", None) + | GAS -> struct("gas", None) + | JUMPDEST -> struct("jumpdest", None) + | PUSH1 imm -> struct("push1", BitVector.valToString imm |> Some) + | PUSH2 imm -> struct("push2", BitVector.valToString imm |> Some) + | PUSH3 imm -> struct("push3", BitVector.valToString imm |> Some) + | PUSH4 imm -> struct("push4", BitVector.valToString imm |> Some) + | PUSH5 imm -> struct("push5", BitVector.valToString imm |> Some) + | PUSH6 imm -> struct("push6", BitVector.valToString imm |> Some) + | PUSH7 imm -> struct("push7", BitVector.valToString imm |> Some) + | PUSH8 imm -> struct("push8", BitVector.valToString imm |> Some) + | PUSH9 imm -> struct("push9", BitVector.valToString imm |> Some) + | PUSH10 imm -> struct("push10", BitVector.valToString imm |> Some) + | PUSH11 imm -> struct("push11", BitVector.valToString imm |> Some) + | PUSH12 imm -> struct("push12", BitVector.valToString imm |> Some) + | PUSH13 imm -> struct("push13", BitVector.valToString imm |> Some) + | PUSH14 imm -> struct("push14", BitVector.valToString imm |> Some) + | PUSH15 imm -> struct("push15", BitVector.valToString imm |> Some) + | PUSH16 imm -> struct("push16", BitVector.valToString imm |> Some) + | PUSH17 imm -> struct("push17", BitVector.valToString imm |> Some) + | PUSH18 imm -> struct("push18", BitVector.valToString imm |> Some) + | PUSH19 imm -> struct("push19", BitVector.valToString imm |> Some) + | PUSH20 imm -> struct("push20", BitVector.valToString imm |> Some) + | PUSH21 imm -> struct("push21", BitVector.valToString imm |> Some) + | PUSH22 imm -> struct("push22", BitVector.valToString imm |> Some) + | PUSH23 imm -> struct("push23", BitVector.valToString imm |> Some) + | PUSH24 imm -> struct("push24", BitVector.valToString imm |> Some) + | PUSH25 imm -> struct("push25", BitVector.valToString imm |> Some) + | PUSH26 imm -> struct("push26", BitVector.valToString imm |> Some) + | PUSH27 imm -> struct("push27", BitVector.valToString imm |> Some) + | PUSH28 imm -> struct("push28", BitVector.valToString imm |> Some) + | PUSH29 imm -> struct("push29", BitVector.valToString imm |> Some) + | PUSH30 imm -> struct("push30", BitVector.valToString imm |> Some) + | PUSH31 imm -> struct("push31", BitVector.valToString imm |> Some) + | PUSH32 imm -> struct("push32", BitVector.valToString imm |> Some) + | DUP1 -> struct("dup1", None) + | DUP2 -> struct("dup2", None) + | DUP3 -> struct("dup3", None) + | DUP4 -> struct("dup4", None) + | DUP5 -> struct("dup5", None) + | DUP6 -> struct("dup6", None) + | DUP7 -> struct("dup7", None) + | DUP8 -> struct("dup8", None) + | DUP9 -> struct("dup9", None) + | DUP10 -> struct("dup10", None) + | DUP11 -> struct("dup11", None) + | DUP12 -> struct("dup12", None) + | DUP13 -> struct("dup13", None) + | DUP14 -> struct("dup14", None) + | DUP15 -> struct("dup15", None) + | DUP16 -> struct("dup16", None) + | SWAP1 -> struct("swap1", None) + | SWAP2 -> struct("swap2", None) + | SWAP3 -> struct("swap3", None) + | SWAP4 -> struct("swap4", None) + | SWAP5 -> struct("swap5", None) + | SWAP6 -> struct("swap6", None) + | SWAP7 -> struct("swap7", None) + | SWAP8 -> struct("swap8", None) + | SWAP9 -> struct("swap9", None) + | SWAP10 -> struct("swap10", None) + | SWAP11 -> struct("swap11", None) + | SWAP12 -> struct("swap12", None) + | SWAP13 -> struct("swap13", None) + | SWAP14 -> struct("swap14", None) + | SWAP15 -> struct("swap15", None) + | SWAP16 -> struct("swap16", None) + | LOG0 -> struct("log0", None) + | LOG1 -> struct("log1", None) + | LOG2 -> struct("log2", None) + | LOG3 -> struct("log3", None) + | LOG4 -> struct("log4", None) + | CREATE -> struct("create", None) + | CALL -> struct("call", None) + | CALLCODE -> struct("callcode", None) + | RETURN -> struct("return", None) + | DELEGATECALL -> struct("delegatecall", None) + | CREATE2 -> struct("create2", None) + | STATICCALL -> struct("staticcall", None) + | REVERT -> struct("revert", None) + | INVALID -> struct("invalid", None) + | SELFDESTRUCT -> struct("selfdestruct", None) + +let inline buildOpcode insInfo (builder: DisasmBuilder<_>) = + let struct (opcode, extra) = opcodeToStrings insInfo.Opcode + match extra with + | None -> builder.Accumulate AsmWordKind.Mnemonic opcode + | Some extra -> + builder.Accumulate AsmWordKind.Mnemonic opcode + builder.Accumulate AsmWordKind.String " " + builder.Accumulate AsmWordKind.Value extra + +let disasm insInfo (builder: DisasmBuilder<_>) = + if builder.ShowAddr then builder.AccumulateAddr () else () + buildOpcode insInfo builder + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/EVM/EVMInstruction.fs b/src/FrontEnd/BinLifter/EVM/EVMInstruction.fs similarity index 73% rename from src/FrontEnd/EVM/EVMInstruction.fs rename to src/FrontEnd/BinLifter/EVM/EVMInstruction.fs index 26660f13..82792120 100644 --- a/src/FrontEnd/EVM/EVMInstruction.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMInstruction.fs @@ -22,32 +22,27 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.EVM +namespace B2R2.FrontEnd.BinLifter.EVM open B2R2 -open B2R2.FrontEnd -open System.Text +open B2R2.FrontEnd.BinLifter /// The internal representation for a EVM instruction used by our /// disassembler and lifter. type EVMInstruction (addr, numBytes, insInfo, wordSize) = inherit Instruction (addr, numBytes, wordSize) - let defaultCtxt = ParsingContext.Init () - /// Basic instruction information. member val Info: InsInfo = insInfo - override __.NextParsingContext = defaultCtxt - - override __.AuxParsingContext with get() = None - override __.IsBranch () = match __.Info.Opcode with | Opcode.JUMP | Opcode.JUMPI -> true | _ -> false + override __.IsModeChanging () = false + member __.HasConcJmpTarget () = false override __.IsDirectBranch () = @@ -76,58 +71,64 @@ type EVMInstruction (addr, numBytes, insInfo, wordSize) = override __.IsInterrupt () = Utils.futureFeature () - member private __.IsHaltingInstruction () = + override __.IsExit () = __.Info.Opcode = Opcode.REVERT || __.Info.Opcode = Opcode.RETURN || __.Info.Opcode = Opcode.SELFDESTRUCT || __.Info.Opcode = Opcode.INVALID + || __.Info.Opcode = Opcode.STOP - override __.IsExit () = + override __.IsBBLEnd () = __.IsDirectBranch () || __.IsIndirectBranch () || __.Info.Opcode = Opcode.REVERT || __.Info.Opcode = Opcode.RETURN || __.Info.Opcode = Opcode.SELFDESTRUCT || __.Info.Opcode = Opcode.INVALID + || __.Info.Opcode = Opcode.STOP - override __.DirectBranchTarget (addr: byref) = false + override __.DirectBranchTarget (_addr: byref) = false - override __.IndirectTrampolineAddr (addr: byref) = + override __.IndirectTrampolineAddr (_addr: byref) = // FIXME false + override __.Immediate (_) = false + override __.GetNextInstrAddrs () = let fallthrough = __.Address + uint64 __.Length let acc = Seq.singleton (fallthrough, ArchOperationMode.NoMode) - if __.IsHaltingInstruction () then Seq.empty + if __.IsExit () then Seq.empty else acc - override __.InterruptNum (num: byref) = Utils.futureFeature () + override __.InterruptNum (_num: byref) = Utils.futureFeature () override __.IsNop () = false override __.Translate ctxt = Lifter.translate __.Info ctxt - member private __.StrBuilder _ (str: string) (acc: StringBuilder) = - acc.Append (str) - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = - StringBuilder () - |> Disasm.disasm showAddr __.Info __.StrBuilder - |> fun acc -> acc.ToString () + let builder = + DisasmStringBuilder (showAddr, false, WordSize.Bit256, addr, numBytes) + Disasm.disasm __.Info builder + builder.Finalize () override __.Disasm () = - StringBuilder () - |> Disasm.disasm false __.Info __.StrBuilder - |> fun acc -> acc.ToString () + let builder = + DisasmStringBuilder (false, false, WordSize.Bit256, addr, numBytes) + Disasm.disasm __.Info builder + builder.Finalize () + + override __.Decompose (showAddr) = + let builder = + DisasmWordBuilder (showAddr, false, WordSize.Bit256, addr, numBytes, 8) + Disasm.disasm __.Info builder + builder.Finalize () - member private __.WordBuilder kind str (acc: AsmWordBuilder) = - acc.Append ({ AsmWordKind = kind; AsmWordValue = str }) + override __.IsInlinedAssembly () = false - override __.Decompose () = - AsmWordBuilder (8) - |> Disasm.disasm true __.Info __.WordBuilder - |> fun b -> b.Finish () + override __.Equals (_) = Utils.futureFeature () + override __.GetHashCode () = Utils.futureFeature () // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/EVM/EVMLifter.fs b/src/FrontEnd/BinLifter/EVM/EVMLifter.fs similarity index 53% rename from src/FrontEnd/EVM/EVMLifter.fs rename to src/FrontEnd/BinLifter/EVM/EVMLifter.fs index c4648276..9a5f0318 100644 --- a/src/FrontEnd/EVM/EVMLifter.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMLifter.fs @@ -22,82 +22,84 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.EVM.Lifter +module internal B2R2.FrontEnd.BinLifter.EVM.Lifter open B2R2 open B2R2.BinIR open B2R2.BinIR.LowUIR -open B2R2.BinIR.LowUIR.AST -open B2R2.FrontEnd -open B2R2.FrontEnd.EVM +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.EVM let inline private getRegVar (ctxt: TranslationContext) name = Register.toRegID name |> ctxt.GetRegVar -let inline private ( num -let inline private numU64 n t = BitVector.ofUInt64 n t |> num +let inline private numI32 n t = BitVector.ofInt32 n t |> AST.num +let inline private numU64 n t = BitVector.ofUInt64 n t |> AST.num let inline private updateGas ctxt gas builder = let gasReg = getRegVar ctxt R.GAS builder ) let sideEffects insInfo name = - let builder = new StmtBuilder (4) + let builder = new IRBuilder (4) startMark insInfo builder - builder /// Pushes an element to stack. -let private pushToStack (ctxt: TranslationContext) expr builder = +let private pushToStack (ctxt: TranslationContext) expr (builder: IRBuilder) = let spReg = getRegVar ctxt R.SP - let tmp = tmpVar (typeOf expr) + let expr = if OperationSize.regType = TypeCheck.typeOf expr then expr + else AST.zext OperationSize.regType expr builder >) let sar insInfo ctxt = basicOperation insInfo ctxt (?>>) let addmod insInfo ctxt = - let builder = new StmtBuilder (12) + let builder = new IRBuilder (12) startMark insInfo builder let src1 = popFromStack ctxt builder let src2 = popFromStack ctxt builder @@ -136,7 +138,7 @@ let addmod insInfo ctxt = endMark insInfo builder let mulmod insInfo ctxt = - let builder = new StmtBuilder (12) + let builder = new IRBuilder (12) startMark insInfo builder let src1 = popFromStack ctxt builder let src2 = popFromStack ctxt builder @@ -147,39 +149,40 @@ let mulmod insInfo ctxt = endMark insInfo builder let private makeNum i = - num <| BitVector.ofInt32 i OperationSize.regType + AST.num <| BitVector.ofInt32 i OperationSize.regType let signextend insInfo ctxt = - let builder = new StmtBuilder (12) + let builder = new IRBuilder (12) startMark insInfo builder let b = popFromStack ctxt builder let x = popFromStack ctxt builder let expr = x .& (makeNum 1 << ((b .+ makeNum 1) .* makeNum 8) .- makeNum 1) - let sext = sExt 256 expr + let sext = AST.sext 256 expr pushToStack ctxt sext builder updateGas ctxt insInfo.GAS builder endMark insInfo builder let iszero insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = new IRBuilder (8) startMark insInfo builder let cond = popFromStack ctxt builder - let expr = zExt OperationSize.regType (cond == num0 OperationSize.regType) + let rt = OperationSize.regType + let expr = AST.zext rt (cond == AST.num0 rt) pushToStack ctxt expr builder updateGas ctxt insInfo.GAS builder endMark insInfo builder let not insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = new IRBuilder (8) startMark insInfo builder let e = popFromStack ctxt builder - let expr = zExt OperationSize.regType (not e) + let expr = AST.zext OperationSize.regType (AST.not e) pushToStack ctxt expr builder updateGas ctxt insInfo.GAS builder endMark insInfo builder let byte insInfo ctxt = - let builder = new StmtBuilder (12) + let builder = new IRBuilder (12) startMark insInfo builder let n = popFromStack ctxt builder let x = popFromStack ctxt builder @@ -189,91 +192,90 @@ let byte insInfo ctxt = endMark insInfo builder let pop insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = new IRBuilder (8) startMark insInfo builder popFromStack ctxt builder |> ignore updateGas ctxt insInfo.GAS builder endMark insInfo builder let mload insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = new IRBuilder (8) startMark insInfo builder let addr = popFromStack ctxt builder - let expr = loadLE OperationSize.regType addr + let expr = AST.loadBE OperationSize.regType addr pushToStack ctxt expr builder updateGas ctxt insInfo.GAS builder endMark insInfo builder let mstore insInfo ctxt = - let builder = new StmtBuilder (12) + let builder = new IRBuilder (8) startMark insInfo builder let addr = popFromStack ctxt builder let value = popFromStack ctxt builder + builder 0 + builder addr := value .& makeNum 0xff) endMark insInfo builder let jump insInfo ctxt = - let builder = new StmtBuilder (8) - let pc = getRegVar ctxt R.PC + let builder = new IRBuilder (8) try startMark insInfo builder let dst = popFromStack ctxt builder - let dstAddr = dst .+ (BitVector.ofUInt64 insInfo.Offset 256 |> num) + let dstAddr = dst .+ (BitVector.ofUInt64 insInfo.Offset 256 |> AST.num) updateGas ctxt insInfo.GAS builder - builder (* Special case: terminate func. *) - sideEffects insInfo Halt + sideEffects insInfo Terminate let jumpi insInfo ctxt = - let builder = new StmtBuilder (12) + let builder = new IRBuilder (12) startMark insInfo builder - let pc = getRegVar ctxt R.PC let dst = popFromStack ctxt builder - let dstAddr = dst .+ (BitVector.ofUInt64 insInfo.Offset 256 |> num) + let dstAddr = dst .+ (BitVector.ofUInt64 insInfo.Offset 256 |> AST.num) let cond = popFromStack ctxt builder let fall = numU64 (insInfo.Address + 1UL) 64 updateGas ctxt insInfo.GAS builder - builder cond, pc, dstAddr, fall) + builder cond) dstAddr fall endMark insInfo builder let getpc insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = new IRBuilder (8) startMark insInfo builder - let expr = getRegVar ctxt R.PC |> zExt OperationSize.regType + let expr = getRegVar ctxt R.PC |> AST.zext OperationSize.regType pushToStack ctxt expr builder updateGas ctxt insInfo.GAS builder endMark insInfo builder let gas insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = new IRBuilder (8) startMark insInfo builder - let expr = zExt OperationSize.regType (getRegVar ctxt R.GAS) + let expr = AST.zext OperationSize.regType (getRegVar ctxt R.GAS) pushToStack ctxt expr builder updateGas ctxt insInfo.GAS builder endMark insInfo builder let push insInfo ctxt imm = - let builder = new StmtBuilder (8) + let builder = new IRBuilder (8) startMark insInfo builder - let expr = BitVector.ofBv imm 256 |> num + let expr = BitVector.cast imm 256 |> AST.num pushToStack ctxt expr builder updateGas ctxt insInfo.GAS builder endMark insInfo builder let dup insInfo ctxt pos = - let builder = new StmtBuilder (8) + let builder = new IRBuilder (8) startMark insInfo builder let src = peekStack ctxt pos builder pushToStack ctxt src builder @@ -281,130 +283,24 @@ let dup insInfo ctxt pos = endMark insInfo builder let swap insInfo ctxt pos = - let builder = new StmtBuilder (12) + let builder = new IRBuilder (12) startMark insInfo builder swapStack ctxt pos builder updateGas ctxt insInfo.GAS builder endMark insInfo builder -let obtainInfo insInfo ctxt name = - let builder = new StmtBuilder (8) +let callExternFunc insInfo ctxt name argCount doesRet = + let builder = new IRBuilder (15) startMark insInfo builder - let expr = app name [] OperationSize.regType - pushToStack ctxt expr builder - updateGas ctxt insInfo.GAS builder - endMark insInfo builder - -let address insInfo ctxt = - let builder = new StmtBuilder (8) - startMark insInfo builder - let pc = BitVector.ofUInt64 insInfo.Address OperationSize.regType |> num - pushToStack ctxt pc builder - updateGas ctxt insInfo.GAS builder - endMark insInfo builder - -let balance insInfo ctxt = - let builder = new StmtBuilder (8) - startMark insInfo builder - let addr = popFromStack ctxt builder - let expr = app "balance" [ addr ] OperationSize.regType - pushToStack ctxt expr builder - updateGas ctxt insInfo.GAS builder - endMark insInfo builder - -let calldataload insInfo ctxt = - let builder = new StmtBuilder (12) - startMark insInfo builder - let i = popFromStack ctxt builder - let length = num1 OperationSize.regType - let expr = app "msg.data" [ i; length ] OperationSize.regType - pushToStack ctxt expr builder - updateGas ctxt insInfo.GAS builder - endMark insInfo builder - -let calldatacopy insInfo ctxt = - let builder = new StmtBuilder (12) - startMark insInfo builder - let dstOffset = popFromStack ctxt builder - let offset = popFromStack ctxt builder - let length = popFromStack ctxt builder - let src = app "msg.data" [ offset; length ] OperationSize.regType - builder extractLow 64 - let offset = popFromStack ctxt builder - let length = popFromStack ctxt builder - let src = app "code" [ offset; length ] OperationSize.regType - builder popFromStack ctxt builder) + let expr = AST.app name args OperationSize.regType + if doesRet then pushToStack ctxt expr builder + else builder ignore popFromStack ctxt builder |> ignore - sideEffects insInfo Halt + sideEffects insInfo Terminate let selfdestruct insInfo ctxt = - let builder = new StmtBuilder (8) + let builder = new IRBuilder (8) popFromStack ctxt builder |> ignore - sideEffects insInfo Halt + sideEffects insInfo Terminate let translate insInfo (ctxt: TranslationContext) = match insInfo.Opcode with - | STOP -> sideEffects insInfo Halt + | STOP -> sideEffects insInfo Terminate | ADD -> add insInfo ctxt | MUL -> mul insInfo ctxt | SUB -> sub insInfo ctxt @@ -471,7 +338,7 @@ let translate insInfo (ctxt: TranslationContext) = | SMOD -> smod insInfo ctxt | ADDMOD -> addmod insInfo ctxt | MULMOD -> mulmod insInfo ctxt - | EXP -> exp insInfo ctxt + | EXP -> callExternFunc insInfo ctxt "exp" 2 true | SIGNEXTEND -> signextend insInfo ctxt | LT -> lt insInfo ctxt | GT -> gt insInfo ctxt @@ -487,38 +354,38 @@ let translate insInfo (ctxt: TranslationContext) = | SHL -> shl insInfo ctxt | SHR -> shr insInfo ctxt | SAR -> sar insInfo ctxt - | SHA3 -> sha3 insInfo ctxt - | CALLER -> obtainInfo insInfo ctxt "msg.caller" - | CALLVALUE -> obtainInfo insInfo ctxt "msg.value" - | ADDRESS -> address insInfo ctxt - | BALANCE -> balance insInfo ctxt - | ORIGIN -> obtainInfo insInfo ctxt "tx.origin" - | CALLDATALOAD -> calldataload insInfo ctxt - | CALLDATASIZE -> obtainInfo insInfo ctxt "msg.data.size" - | COINBASE -> obtainInfo insInfo ctxt "block.coinbase" - | TIMESTAMP -> obtainInfo insInfo ctxt "block.timestamp" - | NUMBER -> obtainInfo insInfo ctxt "block.number" - | DIFFICULTY -> obtainInfo insInfo ctxt "block.difficulty" - | CALLDATACOPY -> calldatacopy insInfo ctxt - | CODECOPY -> codecopy insInfo ctxt - | GASPRICE -> obtainInfo insInfo ctxt "tx.gasprice" - | CODESIZE -> codesize insInfo ctxt - | EXTCODESIZE -> extcodesize insInfo ctxt - | EXTCODECOPY -> extcodecopy insInfo ctxt - | RETURNDATASIZE -> obtainInfo insInfo ctxt "returndatasize" - | RETURNDATACOPY -> returndatacopy insInfo ctxt - | BLOCKHASH -> blockhash insInfo ctxt - | GASLIMIT -> obtainInfo insInfo ctxt "block.gaslimit" + | SHA3 -> callExternFunc insInfo ctxt "keccak256" 2 true + | ADDRESS -> callExternFunc insInfo ctxt "address" 0 true + | BALANCE -> callExternFunc insInfo ctxt "balance" 1 true + | ORIGIN -> callExternFunc insInfo ctxt "tx.origin" 0 true + | CALLER -> callExternFunc insInfo ctxt "msg.caller" 0 true + | CALLVALUE -> callExternFunc insInfo ctxt "msg.value" 0 true + | CALLDATALOAD -> callExternFunc insInfo ctxt "msg.data" 1 true + | CALLDATASIZE -> callExternFunc insInfo ctxt "msg.data.size" 0 true + | CALLDATACOPY -> callExternFunc insInfo ctxt "calldatacopy" 3 false + | CODESIZE -> callExternFunc insInfo ctxt "codesize" 0 true + | CODECOPY -> callExternFunc insInfo ctxt "codecopy" 3 false + | GASPRICE -> callExternFunc insInfo ctxt "tx.gasprice" 0 true + | EXTCODESIZE -> callExternFunc insInfo ctxt "extcodesize" 1 true + | EXTCODECOPY -> callExternFunc insInfo ctxt "extcodecopy" 4 false + | RETURNDATASIZE -> callExternFunc insInfo ctxt "returndatasize" 0 true + | RETURNDATACOPY -> callExternFunc insInfo ctxt "returndatacopy" 3 false + | BLOCKHASH -> callExternFunc insInfo ctxt "blockhash" 1 true + | COINBASE -> callExternFunc insInfo ctxt "block.coinbase" 0 true + | TIMESTAMP -> callExternFunc insInfo ctxt "block.timestamp" 0 true + | NUMBER -> callExternFunc insInfo ctxt "block.number" 0 true + | DIFFICULTY -> callExternFunc insInfo ctxt "block.difficulty" 0 true + | GASLIMIT -> callExternFunc insInfo ctxt "block.gaslimit" 0 true | POP -> pop insInfo ctxt | MLOAD -> mload insInfo ctxt | MSTORE -> mstore insInfo ctxt | MSTORE8 -> mstore8 insInfo ctxt - | SLOAD -> sload insInfo ctxt - | SSTORE -> sstore insInfo ctxt + | SLOAD -> callExternFunc insInfo ctxt "sload" 1 true + | SSTORE -> callExternFunc insInfo ctxt "sstore" 2 false | JUMP -> jump insInfo ctxt | JUMPI -> jumpi insInfo ctxt | GETPC -> getpc insInfo ctxt - | MSIZE -> obtainInfo insInfo ctxt "msize" + | MSIZE -> callExternFunc insInfo ctxt "msize" 0 true | GAS -> gas insInfo ctxt | JUMPDEST -> nop insInfo | PUSH1 imm -> push insInfo ctxt imm @@ -585,32 +452,18 @@ let translate insInfo (ctxt: TranslationContext) = | SWAP14 -> swap insInfo ctxt 14 | SWAP15 -> swap insInfo ctxt 15 | SWAP16 -> swap insInfo ctxt 16 - | RETURN - | REVERT -> ret insInfo ctxt - | CALL -> call insInfo ctxt "call.gas" - | CALLCODE -> call insInfo ctxt "callcode.gas" - | LOG0 - | LOG1 - | LOG2 - | LOG3 - | LOG4 - | JUMPTO - | JUMPIF - | JUMPSUB - | JUMPSUBV - | BEGINSUB - | BEGINDATA - | RETURNSUB - | PUTLOCAL - | GETLOCAL - | SLOADBYTES - | SSTOREBYTES - | SSIZE - | CREATE - | DELEGATECALL - | CREATE2 - | STATICCALL - | TXEXECGAS - | INVALID + | RETURN | REVERT -> ret insInfo ctxt + | CALL -> callExternFunc insInfo ctxt "call" 7 true + | CALLCODE -> callExternFunc insInfo ctxt "callcode" 7 true + | LOG0 -> callExternFunc insInfo ctxt "log0" 2 false + | LOG1 -> callExternFunc insInfo ctxt "log1" 3 false + | LOG2 -> callExternFunc insInfo ctxt "log2" 4 false + | LOG3 -> callExternFunc insInfo ctxt "log3" 5 false + | LOG4 -> callExternFunc insInfo ctxt "log4" 6 false + | CREATE -> callExternFunc insInfo ctxt "create" 3 true + | DELEGATECALL -> callExternFunc insInfo ctxt "delegatecall" 6 true + | CREATE2 -> callExternFunc insInfo ctxt "create2" 4 true + | STATICCALL -> callExternFunc insInfo ctxt "staticcall" 6 true + | INVALID -> sideEffects insInfo Terminate | SELFDESTRUCT -> selfdestruct insInfo ctxt |> fun builder -> builder.ToStmts () diff --git a/src/FrontEnd/EVM/EVMParser.fs b/src/FrontEnd/BinLifter/EVM/EVMParser.fs similarity index 91% rename from src/FrontEnd/EVM/EVMParser.fs rename to src/FrontEnd/BinLifter/EVM/EVMParser.fs index c2c54441..42d212b9 100644 --- a/src/FrontEnd/EVM/EVMParser.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMParser.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module B2R2.FrontEnd.EVM.Parser +module B2R2.FrontEnd.BinLifter.EVM.Parser open B2R2 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter let private parsePush (reader: BinReader) opcode size pos = let struct (bytes, nextPos) = reader.ReadBytes (size, pos) @@ -163,18 +163,6 @@ let private parseOpcode (reader: BinReader) pos = | 0xa2uy -> struct (LOG2, 1125, nextPos) | 0xa3uy -> struct (LOG3, 1500, nextPos) | 0xa4uy -> struct (LOG4, 1875, nextPos) - | 0xb0uy -> struct (JUMPTO, 0, nextPos) - | 0xb1uy -> struct (JUMPIF, 0, nextPos) - | 0xb2uy -> struct (JUMPSUB, 0, nextPos) - | 0xb4uy -> struct (JUMPSUBV, 0, nextPos) - | 0xb5uy -> struct (BEGINSUB, 0, nextPos) - | 0xb6uy -> struct (BEGINDATA, 0, nextPos) - | 0xb8uy -> struct (RETURNSUB, 0, nextPos) - | 0xb9uy -> struct (PUTLOCAL, 0, nextPos) - | 0xbauy -> struct (GETLOCAL, 0, nextPos) - | 0xe1uy -> struct (SLOADBYTES, 0, nextPos) - | 0xe2uy -> struct (SSTOREBYTES, 0, nextPos) - | 0xe3uy -> struct (SSIZE, 0, nextPos) | 0xf0uy -> struct (CREATE, 32000, nextPos) | 0xf1uy -> struct (CALL, -1, nextPos) | 0xf2uy -> struct (CALLCODE, -1, nextPos) @@ -182,19 +170,18 @@ let private parseOpcode (reader: BinReader) pos = | 0xf4uy -> struct (DELEGATECALL, -1, nextPos) | 0xf5uy -> struct (CREATE2, 0, nextPos) | 0xfauy -> struct (STATICCALL, 4, nextPos) - | 0xfcuy -> struct (TXEXECGAS, 0, nextPos) | 0xfduy -> struct (REVERT, 0, nextPos) | 0xfeuy -> struct (INVALID, 0, nextPos) | 0xffuy -> struct (SELFDESTRUCT, 5000, nextPos) | _ -> raise ParsingFailureException -let parse (reader: BinReader) (ctxt: ParsingContext) wordSize addr pos = +let parse (reader: BinReader) offset wordSize addr pos = let struct (opcode, gas, nextPos) = parseOpcode reader pos let instrLen = nextPos - pos |> uint32 let insInfo = { Address = addr NumBytes = instrLen - Offset = ctxt.CodeOffset + Offset = offset Opcode = opcode GAS = gas } EVMInstruction (addr, instrLen, insInfo, wordSize) diff --git a/src/FrontEnd/EVM/EVMRegExprs.fs b/src/FrontEnd/BinLifter/EVM/EVMRegExprs.fs similarity index 89% rename from src/FrontEnd/EVM/EVMRegExprs.fs rename to src/FrontEnd/BinLifter/EVM/EVMRegExprs.fs index 4fc6ed54..550dac87 100644 --- a/src/FrontEnd/EVM/EVMRegExprs.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMRegExprs.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.EVM +namespace B2R2.FrontEnd.BinLifter.EVM open B2R2 open B2R2.BinIR.LowUIR @@ -30,8 +30,8 @@ open B2R2.BinIR.LowUIR type internal RegExprs () = let var sz t name = AST.var sz t name (EVMRegisterSet.singleton t) - member val PC = var 64 (Register.toRegID Register.PC) "PC" with get - member val GAS = var 64 (Register.toRegID Register.GAS) "Gas" with get + member val PC = var 256 (Register.toRegID Register.PC) "PC" with get + member val GAS = var 64 (Register.toRegID Register.GAS) "GAS" with get member val SP = var 256 (Register.toRegID Register.SP) "SP" with get member __.GetRegVar (name) = @@ -39,6 +39,6 @@ type internal RegExprs () = | R.PC -> __.PC | R.GAS -> __.GAS | R.SP -> __.SP - | _ -> raise B2R2.FrontEnd.UnhandledRegExprException + | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/EVM/EVMRegisterBay.fs b/src/FrontEnd/BinLifter/EVM/EVMRegisterBay.fs new file mode 100644 index 00000000..dd7101b9 --- /dev/null +++ b/src/FrontEnd/BinLifter/EVM/EVMRegisterBay.fs @@ -0,0 +1,76 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.EVM + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR.LowUIR + +type EVMRegisterBay () = + + inherit RegisterBay () + + override __.GetAllRegExprs () = Utils.futureFeature () + + override __.GetAllRegNames () = [] + + override __.GetGeneralRegExprs () = Utils.futureFeature () + + override __.RegIDFromRegExpr (e) = + match e.E with + | Var (_, id, _ ,_) -> id + | PCVar (_, _) -> Register.toRegID Register.PC + | _ -> failwith "not a register expression" + + override __.RegIDToRegExpr (id) = Utils.impossible () + + override __.StrToRegExpr _s = Utils.impossible () + + override __.RegIDFromString str = + Register.ofString str |> Register.toRegID + + override __.RegIDToString rid = + Register.ofRegID rid |> Register.toString + + override __.RegIDToRegType rid = + Register.ofRegID rid |> Register.toRegType + + override __.GetRegisterAliases _ = Utils.futureFeature () + + override __.ProgramCounter = + Register.PC |> Register.toRegID + + override __.StackPointer = + Register.SP |> Register.toRegID |> Some + + override __.FramePointer = Utils.futureFeature () + + override __.IsProgramCounter regid = + __.ProgramCounter = regid + + override __.IsStackPointer regid = + (__.StackPointer |> Option.get) = regid + + override __.IsFramePointer _ = false diff --git a/src/FrontEnd/EVM/EVMRegisterSet.fs b/src/FrontEnd/BinLifter/EVM/EVMRegisterSet.fs similarity index 71% rename from src/FrontEnd/EVM/EVMRegisterSet.fs rename to src/FrontEnd/BinLifter/EVM/EVMRegisterSet.fs index 6605f1af..2d3566f3 100644 --- a/src/FrontEnd/EVM/EVMRegisterSet.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMRegisterSet.fs @@ -22,32 +22,40 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.EVM +namespace B2R2.FrontEnd.BinLifter.EVM open B2R2 +module private RegisterSetLiteral = + let [] arrLen = 2 + +open RegisterSetLiteral + type EVMRegisterSet (bitArray: uint64 [], s: Set) = inherit NonEmptyRegisterSet (bitArray, s) - static let defaultSize = 2 - static let emptyArr = Array.init defaultSize (fun _ -> 0UL) - static member EmptySet = - new EVMRegisterSet (emptyArr, Set.empty) :> RegisterSet + new () = EVMRegisterSet (RegisterSet.MakeInternalBitArray arrLen, Set.empty) override __.Tag = RegisterSetTag.EVM - override __.ArrSize = defaultSize - override __.New x s = new EVMRegisterSet (x, s) :> RegisterSet - override __.Empty = EVMRegisterSet.EmptySet - override __.EmptyArr = emptyArr - override __.Project x = - match Register.ofRegID x with + + override __.ArrSize = arrLen + + override __.New arr s = new EVMRegisterSet (arr, s) :> RegisterSet + + override __.RegIDToIndex rid = + match Register.ofRegID rid with | R.GAS -> 1 | _ -> -1 + override __.IndexToRegID index = + match index with + | 1 -> R.GAS |> Register.toRegID + | _ -> Utils.impossible () + override __.ToString () = sprintf "EVMReisterSet<%x, %x>" __.BitArray.[0] __.BitArray.[1] [] module EVMRegisterSet = - let singleton = RegisterSetBuilder.singletonBuilder EVMRegisterSet.EmptySet - let empty = EVMRegisterSet.EmptySet + let singleton rid = EVMRegisterSet().Add(rid) + let empty = EVMRegisterSet () :> RegisterSet diff --git a/src/FrontEnd/EVM/EVMTypes.fs b/src/FrontEnd/BinLifter/EVM/EVMTypes.fs similarity index 93% rename from src/FrontEnd/EVM/EVMTypes.fs rename to src/FrontEnd/BinLifter/EVM/EVMTypes.fs index efb8b5c3..dc119b86 100644 --- a/src/FrontEnd/EVM/EVMTypes.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMTypes.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.EVM +namespace B2R2.FrontEnd.BinLifter.EVM open B2R2 open System.Runtime.CompilerServices -[] +[] do () exception internal InvalidConditionException @@ -60,15 +60,21 @@ module Register = let ofString (str: string) = match str.ToLower () with - | "pc" -> R.PC - | "gas" -> R.GAS - | "sp" -> R.SP + | "PC" -> R.PC + | "GAS" -> R.GAS + | "SP" -> R.SP | _ -> Utils.impossible () let toString = function - | R.GAS -> "gas" - | R.PC -> "pc" - | R.SP -> "sp" + | R.PC -> "PC" + | R.GAS -> "GAS" + | R.SP -> "SP" + | _ -> Utils.impossible () + + let toRegType = function + | R.PC -> 256 + | R.GAS -> 64 + | R.SP -> 256 | _ -> Utils.impossible () @@ -337,30 +343,6 @@ type Opcode = | LOG3 /// Append log record with four topics | LOG4 - /// Tentative libevmasm has different numbers - | JUMPTO - /// Tentative - | JUMPIF - /// Tentative - | JUMPSUB - /// Tentative - | JUMPSUBV - /// Tentative - | BEGINSUB - /// Tentative - | BEGINDATA - /// Tentative - | RETURNSUB - /// Tentative - | PUTLOCAL - /// Tentative - | GETLOCAL - /// Only referenced in pyethereum - | SLOADBYTES - /// Only referenced in pyethereum - | SSTOREBYTES - /// Only referenced in pyethereum - | SSIZE /// Create a new account with associated code | CREATE /// Message-call into an account @@ -377,8 +359,6 @@ type Opcode = | CREATE2 /// Similar to CALL, but does not modify state | STATICCALL - /// FIXME: Not in the yellow paper. - | TXEXECGAS /// Stop execution and revert state changes, without consuming all provided /// gas and providing a reason | REVERT diff --git a/src/FrontEnd/BinLifter/EVM/README.md b/src/FrontEnd/BinLifter/EVM/README.md new file mode 100644 index 00000000..756fff31 --- /dev/null +++ b/src/FrontEnd/BinLifter/EVM/README.md @@ -0,0 +1,11 @@ +# B2R2.FrontEnd.BinLifter.EVM + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.BinLifter.EVM Package? + +`B2R2.FrontEnd.BinLifter.EVM` includes EVM parsers and lifters. diff --git a/src/FrontEnd/BinLifter/Intel/B2R2.FrontEnd.BinLifter.Intel.fsproj b/src/FrontEnd/BinLifter/Intel/B2R2.FrontEnd.BinLifter.Intel.fsproj new file mode 100644 index 00000000..ad5f9a20 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/B2R2.FrontEnd.BinLifter.Intel.fsproj @@ -0,0 +1,44 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 Intel frontend. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FrontEnd/Intel/Intel.fs b/src/FrontEnd/BinLifter/Intel/Intel.fs similarity index 73% rename from src/FrontEnd/Intel/Intel.fs rename to src/FrontEnd/BinLifter/Intel/Intel.fs index b8235428..530507ae 100644 --- a/src/FrontEnd/Intel/Intel.fs +++ b/src/FrontEnd/BinLifter/Intel/Intel.fs @@ -22,24 +22,30 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.Intel +namespace B2R2.FrontEnd.BinLifter.Intel -open B2R2.FrontEnd +open B2R2 +open B2R2.FrontEnd.BinLifter /// Translation context for Intel (x86 or x86-64) instructions. -type IntelTranslationContext (isa) = +type IntelTranslationContext internal (isa, regexprs) = inherit TranslationContext (isa) /// Register expressions. - member val private RegExprs: RegExprs = RegExprs (isa.WordSize) + member val private RegExprs: RegExprs = regexprs override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar override __.GetPseudoRegVar id pos = __.RegExprs.GetPseudoRegVar (Register.ofRegID id ) pos -/// Parser for Intel (x86 or x86-64) instructions. Parser will return a -/// platform-agnostic instruction type (Instruction). -type IntelParser (wordSize) = - inherit Parser () - override __.Parse binReader _ctxt addr pos = - Parser.parse binReader wordSize addr pos :> Instruction +module Basis = + let init (isa: ISA) = + let regexprs = RegExprs (isa.WordSize) + struct ( + IntelTranslationContext (isa, regexprs) :> TranslationContext, + IntelRegisterBay (isa.WordSize, regexprs) :> RegisterBay + ) + + let initRegBay wordSize = + let regexprs = RegExprs (wordSize) + IntelRegisterBay (wordSize, regexprs) :> RegisterBay // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Intel/IntelAVXLifter.fs b/src/FrontEnd/BinLifter/Intel/IntelAVXLifter.fs new file mode 100644 index 00000000..4eb33668 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelAVXLifter.fs @@ -0,0 +1,2313 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.Intel.AVXLifter + +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.FrontEnd.BinLifter.Intel.LiftingUtils +open B2R2.FrontEnd.BinLifter.Intel.MMXLifter + +let private haveEVEXPrx = function + | Some v -> Option.isSome v.EVEXPrx + | None -> false + +let private r128to256 = function + | OprReg R.XMM0 -> R.YMM0 + | OprReg R.XMM1 -> R.YMM1 + | OprReg R.XMM2 -> R.YMM2 + | OprReg R.XMM3 -> R.YMM3 + | OprReg R.XMM4 -> R.YMM4 + | OprReg R.XMM5 -> R.YMM5 + | OprReg R.XMM6 -> R.YMM6 + | OprReg R.XMM7 -> R.YMM7 + | OprReg R.XMM8 -> R.YMM8 + | OprReg R.XMM9 -> R.YMM9 + | OprReg R.XMM10 -> R.YMM10 + | OprReg R.XMM11 -> R.YMM11 + | OprReg R.XMM12 -> R.YMM12 + | OprReg R.XMM13 -> R.YMM13 + | OprReg R.XMM14 -> R.YMM14 + | OprReg R.XMM15 -> R.YMM15 + | _ -> raise InvalidOperandException + +let private r128to512 = function + | OprReg R.XMM0 -> R.ZMM0 + | OprReg R.XMM1 -> R.ZMM1 + | OprReg R.XMM2 -> R.ZMM2 + | OprReg R.XMM3 -> R.ZMM3 + | OprReg R.XMM4 -> R.ZMM4 + | OprReg R.XMM5 -> R.ZMM5 + | OprReg R.XMM6 -> R.ZMM6 + | OprReg R.XMM7 -> R.ZMM7 + | OprReg R.XMM8 -> R.ZMM8 + | OprReg R.XMM9 -> R.ZMM9 + | OprReg R.XMM10 -> R.ZMM10 + | OprReg R.XMM11 -> R.ZMM11 + | OprReg R.XMM12 -> R.ZMM12 + | OprReg R.XMM13 -> R.ZMM13 + | OprReg R.XMM14 -> R.ZMM14 + | OprReg R.XMM15 -> R.ZMM15 + | _ -> raise InvalidOperandException + +let private r256to512 = function + | OprReg R.YMM0 -> R.ZMM0 + | OprReg R.YMM1 -> R.ZMM1 + | OprReg R.YMM2 -> R.ZMM2 + | OprReg R.YMM3 -> R.ZMM3 + | OprReg R.YMM4 -> R.ZMM4 + | OprReg R.YMM5 -> R.ZMM5 + | OprReg R.YMM6 -> R.ZMM6 + | OprReg R.YMM7 -> R.ZMM7 + | OprReg R.YMM8 -> R.ZMM8 + | OprReg R.YMM9 -> R.ZMM9 + | OprReg R.YMM10 -> R.ZMM10 + | OprReg R.YMM11 -> R.ZMM11 + | OprReg R.YMM12 -> R.ZMM12 + | OprReg R.YMM13 -> R.ZMM13 + | OprReg R.YMM14 -> R.ZMM14 + | OprReg R.YMM15 -> R.ZMM15 + | _ -> raise InvalidOperandException + +let private fillZeroHigh128 ctxt dst ir = + let dst = r128to256 dst + let dstC, dstD = getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4 + let n0 = AST.num0 64 + !!ir (dstC := n0) + !!ir (dstD := n0) + +let private fillZeroHigh256 ctxt dst ir = + let dst = r256to512 dst + let dstE, dstF, dstG, dstH = + getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4, + getPseudoRegVar ctxt dst 5, getPseudoRegVar ctxt dst 6 + let n0 = AST.num0 64 + !!ir (dstE := n0) + !!ir (dstF := n0) + !!ir (dstG := n0) + !!ir (dstH := n0) + +let private vexedPackedFPBinOp32 ins insLen ctxt op = + let ir = IRBuilder (16) + let struct (dst, src1, src2) = getThreeOprs ins + let oprSz = getOperationSize ins + let do32PackedOp dst64 src1 src2 ir = + let dstA, dstB = AST.xtlo 32 dst64, AST.xthi 32 dst64 + let src1A, src1B = AST.xtlo 32 src1, AST.xthi 32 src1 + let src2A, src2B = AST.xtlo 32 src2, AST.xthi 32 src2 + !!ir (dstA := op src1A src2A) + !!ir (dstB := op src1B src2B) + ! -> + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + do32PackedOp dst1 src1A src2A ir + do32PackedOp dst2 src1B src2B ir + fillZeroHigh128 ctxt dst ir + | 256 -> + let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst + let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ins insLen ctxt src1 + let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ins insLen ctxt src2 + do32PackedOp dst1 sr1A sr2A ir + do32PackedOp dst2 sr1B sr2B ir + do32PackedOp dst3 sr1C sr2C ir + do32PackedOp dst4 sr1D sr2D ir + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let private vexedPackedFPBinOp64 ins insLen ctxt op = + let ir = IRBuilder (16) + let struct (dst, src1, src2) = getThreeOprs ins + let oprSz = getOperationSize ins + ! -> + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + !!ir (dst1 := op src1A src2A) + !!ir (dst2 := op src1B src2B) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst + let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ins insLen ctxt src1 + let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ins insLen ctxt src2 + !!ir (dst1 := op sr1A sr2A) + !!ir (dst2 := op sr1B sr2B) + !!ir (dst3 := op sr1C sr2C) + !!ir (dst4 := op sr1D sr2D) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let private vexedScalarFPBinOp ins insLen ctxt sz op = + let ir = IRBuilder (8) + let struct (dst, src1, src2) = getThreeOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + ! -> + let src2 = transOprToExpr32 ins insLen ctxt src2 + !!ir (AST.xtlo 32 dst1 := op (AST.xtlo 32 src1A) src2) + !!ir (AST.xthi 32 dst1 := AST.xthi 32 src1A) + | 64 -> + let src2 = transOprToExpr64 ins insLen ctxt src2 + !!ir (dst1 := op src1A src2) + | _ -> raise InvalidOperandSizeException + !!ir (dst2 := src1B) + fillZeroHigh128 ctxt dst ir + !>ir insLen + +let vsqrtps ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src) = getTwoOprs ins + let oprSz = getOperationSize ins + let do32PackedSqrt dst64 src ir = + let dstA, dstB = AST.xtlo 32 dst64, AST.xthi 32 dst64 + let srcA, srcB = AST.xtlo 32 src, AST.xthi 32 src + !!ir (dstA := AST.fsqrt srcA) + !!ir (dstB := AST.fsqrt srcB) + ! -> + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + do32PackedSqrt dst1 srcA ir + do32PackedSqrt dst2 srcB ir + fillZeroHigh128 ctxt dst ir + | 256 -> + let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst + let srD, srC, srB, srA = transOprToExpr256 ins insLen ctxt src + do32PackedSqrt dst1 srA ir + do32PackedSqrt dst2 srB ir + do32PackedSqrt dst3 srC ir + do32PackedSqrt dst4 srD ir + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vsqrtpd ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src) = getTwoOprs ins + let oprSz = getOperationSize ins + ! -> + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + !!ir (dst1 := AST.fsqrt src1) + !!ir (dst2 := AST.fsqrt src2) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst + let sr4, sr3, sr2, sr1 = transOprToExpr256 ins insLen ctxt src + !!ir (dst1 := AST.fsqrt sr1) + !!ir (dst2 := AST.fsqrt sr2) + !!ir (dst3 := AST.fsqrt sr3) + !!ir (dst4 := AST.fsqrt sr4) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let private vsqrts ins insLen ctxt sz = + let ir = IRBuilder (16) + let struct (dst, src1, src2) = getThreeOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + ! -> + let src2 = transOprToExpr32 ins insLen ctxt src2 + !!ir (AST.xtlo 32 dst1 := AST.fsqrt src2) + !!ir (AST.xthi 32 dst1 := AST.xthi 32 src1A) + | 64 -> + let src2 = transOprToExpr64 ins insLen ctxt src2 + !!ir (dst1 := AST.fsqrt src2) + | _ -> raise InvalidOperandSizeException + !!ir (dst2 := src1B) + fillZeroHigh128 ctxt dst ir + !>ir insLen + +let vsqrtss ins insLen ctxt = + vsqrts ins insLen ctxt 32 + +let vsqrtsd ins insLen ctxt = + vsqrts ins insLen ctxt 64 + +let vaddps ins insLen ctxt = + match getOperationSize ins with + | 512 -> GeneralLifter.nop insLen + | _ -> vexedPackedFPBinOp32 ins insLen ctxt AST.fadd + +let vaddpd ins insLen ctxt = + vexedPackedFPBinOp64 ins insLen ctxt AST.fadd + +let vaddss ins insLen ctxt = + vexedScalarFPBinOp ins insLen ctxt 32 AST.fadd + +let vaddsd ins insLen ctxt = + vexedScalarFPBinOp ins insLen ctxt 64 AST.fadd + +let vsubps ins insLen ctxt = + match getOperationSize ins with + | 512 -> GeneralLifter.nop insLen + | _ -> vexedPackedFPBinOp32 ins insLen ctxt AST.fsub + +let vsubpd ins insLen ctxt = + vexedPackedFPBinOp64 ins insLen ctxt AST.fsub + +let vsubss ins insLen ctxt = + vexedScalarFPBinOp ins insLen ctxt 32 AST.fsub + +let vsubsd ins insLen ctxt = + vexedScalarFPBinOp ins insLen ctxt 64 AST.fsub + +let vmulps ins insLen ctxt = + vexedPackedFPBinOp32 ins insLen ctxt AST.fmul + +let vmulpd ins insLen ctxt = + vexedPackedFPBinOp64 ins insLen ctxt AST.fmul + +let vmulss ins insLen ctxt = + vexedScalarFPBinOp ins insLen ctxt 32 AST.fmul + +let vmulsd ins insLen ctxt = + vexedScalarFPBinOp ins insLen ctxt 64 AST.fmul + +let vdivps ins insLen ctxt = + vexedPackedFPBinOp32 ins insLen ctxt AST.fdiv + +let vdivpd ins insLen ctxt = + match getOperationSize ins with + | 512 -> GeneralLifter.nop insLen (* FIXME: #196 *) + | _ -> vexedPackedFPBinOp64 ins insLen ctxt AST.fdiv + +let vdivss ins insLen ctxt = + vexedScalarFPBinOp ins insLen ctxt 32 AST.fdiv + +let vdivsd ins insLen ctxt = + vexedScalarFPBinOp ins insLen ctxt 64 AST.fdiv + +let vcvtsi2ss ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2) = getThreeOprs ins + let dstB , dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2 = transOprToExpr ins insLen ctxt src2 + ! dstA := AST.cast CastKind.IntToFloat 32 src2) + !!ir (AST.xthi 32 dstA := AST.xthi 32 src1A) + !!ir (dstB := src1B) + fillZeroHigh128 ctxt dst ir + !>ir insLen + +let vcvtsi2sd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2) = getThreeOprs ins + let dstB , dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 + let src2 = transOprToExpr ins insLen ctxt src2 + ! src2) + !!ir (dstB := src1B) + fillZeroHigh128 ctxt dst ir + !>ir insLen + +let vcvtsd2ss ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2 = transOprToExpr64 ins insLen ctxt src2 + ! dstA := AST.cast CastKind.FloatCast 32 src2) + !!ir (AST.xthi 32 dstA := AST.xthi 32 src1A) + !!ir (dstB := src1B) + fillZeroHigh128 ctxt dst ir + !>ir insLen + +let vcvtss2sd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 + let src2 = transOprToExpr32 ins insLen ctxt src2 + ! src2) + !!ir (dstB := src1B) + fillZeroHigh128 ctxt dst ir + !>ir insLen + +let private getEVEXPrx = function + | Some v -> match v.EVEXPrx with + | Some ev -> ev + | None -> Utils.impossible () + | None -> Utils.impossible () + +let private buildVectorMove ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let oprSize = getOperationSize ins + ! then + match dst with + | OprReg _ -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + !!ir (dstA := srcA) + !!ir (dstB := srcB) + fillZeroHigh128 ctxt dst ir + | OprMem _ -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + !!ir (dstA := srcA) + !!ir (dstB := srcB) + | _ -> raise InvalidOperandException + elif oprSize = 256 then + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + !!ir (dstA := srcA) + !!ir (dstB := srcB) + !!ir (dstC := srcC) + !!ir (dstD := srcD) + elif oprSize = 512 then + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) + let masking dst = + match ePrx.Z with + | Zeroing -> AST.num0 32 + | Merging -> dst + let cond idx = + (* no write mask *) + let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 + AST.extract k 1 idx .| noWritemask + let kl, vl = 16, 512 + match dst with + | OprReg _ -> + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = + transOprToExpr512 ins insLen ctxt src + let ite i src dst extFn = + AST.ite (cond i) (extFn 32 src) (masking (extFn 32 dst)) + !!ir (AST.xtlo 32 dstA := ite 0 srcA dstA AST.xtlo) + !!ir (AST.xthi 32 dstA := ite 1 srcA dstA AST.xthi) + !!ir (AST.xtlo 32 dstB := ite 2 srcB dstB AST.xtlo) + !!ir (AST.xthi 32 dstB := ite 3 srcB dstB AST.xthi) + !!ir (AST.xtlo 32 dstC := ite 4 srcC dstC AST.xtlo) + !!ir (AST.xthi 32 dstC := ite 5 srcC dstC AST.xthi) + !!ir (AST.xtlo 32 dstD := ite 6 srcD dstD AST.xtlo) + !!ir (AST.xthi 32 dstD := ite 7 srcD dstD AST.xthi) + !!ir (AST.xtlo 32 dstE := ite 8 srcE dstE AST.xtlo) + !!ir (AST.xthi 32 dstE := ite 9 srcE dstE AST.xthi) + !!ir (AST.xtlo 32 dstF := ite 10 srcF dstF AST.xtlo) + !!ir (AST.xthi 32 dstF := ite 11 srcF dstF AST.xthi) + !!ir (AST.xtlo 32 dstG := ite 12 srcG dstG AST.xtlo) + !!ir (AST.xthi 32 dstG := ite 13 srcG dstG AST.xthi) + !!ir (AST.xtlo 32 dstH := ite 14 srcH dstH AST.xtlo) + !!ir (AST.xthi 32 dstH := ite 15 srcH dstH AST.xthi) + | OprMem _ -> + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = + transOprToExpr512 ins insLen ctxt src + let ite i src dst extFn = + AST.ite (cond i) (extFn 32 src) (extFn 32 dst) + let evAssign src dst idx = + AST.concat (ite (idx + 1) src dst AST.xthi) (ite idx src dst AST.xtlo) + !!ir (dstA := evAssign srcA dstA 0) + !!ir (dstB := evAssign srcB dstB 2) + !!ir (dstC := evAssign srcC dstB 4) + !!ir (dstD := evAssign srcD dstB 6) + !!ir (dstE := evAssign srcE dstB 8) + !!ir (dstF := evAssign srcF dstB 10) + !!ir (dstG := evAssign srcG dstB 12) + !!ir (dstH := evAssign srcH dstB 14) + | _ -> raise InvalidOperandException + else raise InvalidOperandSizeException + !>ir insLen + +let vmovd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let oprSize = getOperationSize ins + ! + let regToReg r1 r2 = + match Register.getKind r1, Register.getKind r2 with + | Register.Kind.XMM, Register.Kind.GP -> + let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) + let src = !.ctxt r2 + !!ir (dstAssign 32 dstA src) + !!ir (dstB := n0) + !!ir (dstC := n0) + !!ir (dstD := n0) + | Register.Kind.GP, Register.Kind.XMM -> + let dst = !.ctxt r1 + let srcA = getPseudoRegVar ctxt r2 1 + !!ir (dstAssign oprSize dst (AST.xtlo 32 srcA)) + | _ -> raise InvalidOperandException + match dst, src with + | OprReg r1, OprReg r2 -> regToReg r1 r2 + | OprReg r, OprMem _ -> + let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) + let src = transOprToExpr ins insLen ctxt src + !!ir (dstAssign 32 dstA src) + !!ir (dstB := n0) + !!ir (dstC := n0) + !!ir (dstD := n0) + | OprMem _, OprReg r -> + let dst = transOprToExpr ins insLen ctxt dst + let srcA = getPseudoRegVar ctxt r 1 + !!ir (dst := AST.xtlo 32 srcA) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vmovq ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + ! + let regToReg r1 r2 = + match Register.getKind r1, Register.getKind r2 with + | Register.Kind.XMM, Register.Kind.XMM -> + let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) + let srcA = getPseudoRegVar ctxt r2 1 + !!ir (dstA := srcA) + !!ir (dstB := n0) + !!ir (dstC := n0) + !!ir (dstD := n0) + | Register.Kind.XMM, Register.Kind.GP -> + let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) + let src = !.ctxt r2 + !!ir (dstA := src) + !!ir (dstB := n0) + !!ir (dstC := n0) + !!ir (dstD := n0) + | Register.Kind.GP, Register.Kind.XMM -> + let dst = !.ctxt r1 + let srcA = getPseudoRegVar ctxt r2 1 + !!ir (dst := srcA) + | _ -> raise InvalidOperandException + match dst, src with + | OprReg r1, OprReg r2 -> regToReg r1 r2 + | OprReg _, OprMem _ -> + let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) + let src = transOprToExpr ins insLen ctxt src + !!ir (dstA := src) + !!ir (dstB := n0) + !!ir (dstC := n0) + !!ir (dstD := n0) + | OprMem _, OprReg r -> + let dst = transOprToExpr ins insLen ctxt dst + let srcA = getPseudoRegVar ctxt r 1 + !!ir (dst := srcA) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vmovdqu ins insLen ctxt = + buildVectorMove ins insLen ctxt + +let private fillZeroFromVLToMaxVL ctxt dst vl maxVl ir = + let n0 = AST.num0 64 + match maxVl, vl with + | 512, 128 -> + let dst = r128to512 dst + let dstC, dstD, dstE, dstF, dstG, dstH = + getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4, + getPseudoRegVar ctxt dst 5, getPseudoRegVar ctxt dst 6, + getPseudoRegVar ctxt dst 7, getPseudoRegVar ctxt dst 8 + !!ir (dstC := n0) + !!ir (dstD := n0) + !!ir (dstE := n0) + !!ir (dstF := n0) + !!ir (dstG := n0) + !!ir (dstH := n0) + | 512, 256 -> + let dst = r256to512 dst + let dstE, dstF, dstG, dstH = + getPseudoRegVar ctxt dst 5, getPseudoRegVar ctxt dst 6, + getPseudoRegVar ctxt dst 7, getPseudoRegVar ctxt dst 8 + !!ir (dstE := n0) + !!ir (dstF := n0) + !!ir (dstG := n0) + !!ir (dstH := n0) + | _ -> Utils.impossible () + +let vmovdqu16 ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let oprSize = getOperationSize ins + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) + let masking dst = + match ePrx.Z with + | Zeroing -> AST.num0 16 + | Merging -> dst + let cond idx = + (* no write mask *) + let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 + AST.extract k 1 idx .| noWritemask + ! -> + let kl, vl = 8, 128 + match dst with + | OprReg _ -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let assign dst src idx = + let pos = (idx % 4) * 16 + let dst = AST.extract dst 16 pos + dst := AST.ite (cond idx) (AST.extract src 16 pos) (masking dst) + !!ir (assign dstA srcA 0) + !!ir (assign dstA srcA 1) + !!ir (assign dstA srcA 2) + !!ir (assign dstA srcA 3) + !!ir (assign dstB srcB 4) + !!ir (assign dstB srcB 5) + !!ir (assign dstB srcB 6) + !!ir (assign dstB srcB 7) + fillZeroFromVLToMaxVL ctxt dst vl 512 ir + | OprMem _ -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let tmps = Array.init 4 (fun _ -> !*ir 16) + let assign dst src idx = + for i in 0 .. 3 do + let pos = i * 16 + let dst = AST.extract dst 16 pos + !!ir + (tmps.[i] := AST.ite (cond (idx + i)) (AST.extract src 16 pos) dst) + AST.concatArr tmps + !!ir (dstA := assign dstA srcA 0) + !!ir (dstB := assign dstB srcB 4) + | _ -> raise InvalidOperandException + | 256 -> + let kl, vl = 16, 256 + match dst with + | OprReg _ -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + let assign dst src idx = + let pos = (idx % 4) * 16 + let dst = AST.extract dst 16 pos + dst := AST.ite (cond idx) (AST.extract src 16 pos) (masking dst) + !!ir (assign dstA srcA 0) + !!ir (assign dstA srcA 1) + !!ir (assign dstA srcA 2) + !!ir (assign dstA srcA 3) + !!ir (assign dstB srcB 4) + !!ir (assign dstB srcB 5) + !!ir (assign dstB srcB 6) + !!ir (assign dstB srcB 7) + !!ir (assign dstC srcA 8) + !!ir (assign dstC srcA 9) + !!ir (assign dstC srcA 10) + !!ir (assign dstC srcA 11) + !!ir (assign dstD srcB 12) + !!ir (assign dstD srcB 13) + !!ir (assign dstD srcB 14) + !!ir (assign dstD srcB 15) + fillZeroFromVLToMaxVL ctxt dst vl 512 ir + | OprMem _ -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + let tmps = Array.init 4 (fun _ -> !*ir 16) + let assign dst src idx = + for i in 0 .. 3 do + let pos = i * 16 + let dst = AST.extract dst 16 pos + !!ir + (tmps.[i] := AST.ite (cond (idx + i)) (AST.extract src 16 pos) dst) + AST.concatArr tmps + !!ir (dstA := assign dstA srcA 0) + !!ir (dstB := assign dstB srcB 4) + !!ir (dstC := assign dstC srcC 8) + !!ir (dstD := assign dstD srcD 12) + | _ -> raise InvalidOperandException + | 512 -> + let kl, vl = 32, 512 + match dst with + | OprReg _ -> + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = + transOprToExpr512 ins insLen ctxt src + let assign dst src idx = + let pos = (idx % 4) * 16 + let dst = AST.extract dst 16 pos + dst := AST.ite (cond idx) (AST.extract src 16 pos) (masking dst) + !!ir (assign dstA srcA 0) + !!ir (assign dstA srcA 1) + !!ir (assign dstA srcA 2) + !!ir (assign dstA srcA 3) + !!ir (assign dstB srcB 4) + !!ir (assign dstB srcB 5) + !!ir (assign dstB srcB 6) + !!ir (assign dstB srcB 7) + !!ir (assign dstC srcA 8) + !!ir (assign dstC srcA 9) + !!ir (assign dstC srcA 10) + !!ir (assign dstC srcA 11) + !!ir (assign dstD srcB 12) + !!ir (assign dstD srcB 13) + !!ir (assign dstD srcB 14) + !!ir (assign dstD srcB 15) + !!ir (assign dstF srcA 16) + !!ir (assign dstF srcA 17) + !!ir (assign dstF srcA 18) + !!ir (assign dstF srcA 19) + !!ir (assign dstG srcB 20) + !!ir (assign dstG srcB 21) + !!ir (assign dstG srcB 22) + !!ir (assign dstG srcB 23) + !!ir (assign dstH srcA 24) + !!ir (assign dstH srcA 25) + !!ir (assign dstH srcA 26) + !!ir (assign dstH srcA 27) + !!ir (assign dstG srcB 28) + !!ir (assign dstG srcB 29) + !!ir (assign dstG srcB 30) + !!ir (assign dstG srcB 31) + | OprMem _ -> + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = + transOprToExpr512 ins insLen ctxt src + let tmps = Array.init 4 (fun _ -> !*ir 16) + let assign dst src idx = + for i in 0 .. 3 do + let pos = i * 16 + let dst = AST.extract dst 16 pos + !!ir + (tmps.[i] := AST.ite (cond (idx + i)) (AST.extract src 16 pos) dst) + AST.concatArr tmps + !!ir (dstA := assign dstA srcA 0) + !!ir (dstB := assign dstB srcB 4) + !!ir (dstC := assign dstC srcC 8) + !!ir (dstD := assign dstD srcD 12) + !!ir (dstE := assign dstE srcE 16) + !!ir (dstF := assign dstF srcF 20) + !!ir (dstG := assign dstG srcG 24) + !!ir (dstH := assign dstH srcH 28) + | _ -> raise InvalidOperandException + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vmovdqu64 ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let oprSize = getOperationSize ins + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) + let masking dst = + match ePrx.Z with + | Zeroing -> AST.num0 64 + | Merging -> dst + let cond idx = + if ePrx.AAA = 0uy then AST.num0 1 (* no write mask *) + else AST.extract k 1 idx + ! -> + let kl, vl = 4, 128 + match dst with + | OprReg _ -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + !!ir (dstA := AST.ite (cond 0) srcA (masking dstA)) + !!ir (dstB := AST.ite (cond 1) srcB (masking dstB)) + fillZeroFromVLToMaxVL ctxt dst vl 512 ir + | OprMem _ -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + !!ir (dstA := AST.ite (cond 0) srcA dstA) + !!ir (dstB := AST.ite (cond 1) srcB dstB) + | _ -> raise InvalidOperandException + | 256 -> + let kl, vl = 8, 256 + match dst with + | OprReg _ -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + !!ir (dstA := AST.ite (cond 0) srcA (masking dstA)) + !!ir (dstB := AST.ite (cond 1) srcB (masking dstB)) + !!ir (dstC := AST.ite (cond 2) srcC (masking dstC)) + !!ir (dstD := AST.ite (cond 3) srcD (masking dstD)) + fillZeroFromVLToMaxVL ctxt dst vl 512 ir + | OprMem _ -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + !!ir (dstA := AST.ite (cond 0) srcA dstA) + !!ir (dstB := AST.ite (cond 1) srcB dstB) + !!ir (dstC := AST.ite (cond 2) srcC dstC) + !!ir (dstD := AST.ite (cond 3) srcD dstD) + | _ -> raise InvalidOperandException + | 512 -> + let kl, vl = 16, 512 + match dst with + | OprReg _ -> + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = + transOprToExpr512 ins insLen ctxt src + !!ir (dstA := AST.ite (cond 0) srcA (masking dstA)) + !!ir (dstB := AST.ite (cond 1) srcB (masking dstB)) + !!ir (dstC := AST.ite (cond 2) srcC (masking dstC)) + !!ir (dstD := AST.ite (cond 3) srcD (masking dstD)) + !!ir (dstE := AST.ite (cond 4) srcE (masking dstE)) + !!ir (dstF := AST.ite (cond 5) srcF (masking dstF)) + !!ir (dstG := AST.ite (cond 6) srcG (masking dstG)) + !!ir (dstH := AST.ite (cond 7) srcH (masking dstH)) + | OprMem _ -> + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = + transOprToExpr512 ins insLen ctxt src + !!ir (dstA := AST.ite (cond 0) srcA dstA) + !!ir (dstB := AST.ite (cond 1) srcB dstB) + !!ir (dstC := AST.ite (cond 2) srcC dstC) + !!ir (dstD := AST.ite (cond 3) srcD dstD) + !!ir (dstE := AST.ite (cond 4) srcE dstE) + !!ir (dstF := AST.ite (cond 5) srcF dstF) + !!ir (dstG := AST.ite (cond 6) srcG dstG) + !!ir (dstH := AST.ite (cond 7) srcH dstH) + | _ -> raise InvalidOperandException + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vmovdqa ins insLen ctxt = buildVectorMove ins insLen ctxt + +let vmovdqa64 ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let oprSize = getOperationSize ins + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) + let masking dst = + match ePrx.Z with + | Zeroing -> AST.num0 64 + | Merging -> dst + let cond idx = + (* no write mask *) + let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 + AST.extract k 1 idx .| noWritemask + ! -> + let kl, vl = 2, 128 + match dst with + | OprReg _ -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + !!ir (dstA := AST.ite (cond 0) srcA (masking dstA)) + !!ir (dstB := AST.ite (cond 1) srcB (masking dstB)) + fillZeroFromVLToMaxVL ctxt dst vl 512 ir + | OprMem _ -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + !!ir (dstA := AST.ite (cond 0) srcA dstA) + !!ir (dstB := AST.ite (cond 1) srcB dstB) + | _ -> raise InvalidOperandException + | 256 -> + let kl, vl = 4, 256 + match dst with + | OprReg _ -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + !!ir (dstA := AST.ite (cond 0) srcA (masking dstA)) + !!ir (dstB := AST.ite (cond 1) srcB (masking dstB)) + !!ir (dstC := AST.ite (cond 2) srcC (masking dstC)) + !!ir (dstD := AST.ite (cond 3) srcD (masking dstD)) + fillZeroFromVLToMaxVL ctxt dst vl 512 ir + | OprMem _ -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + !!ir (dstA := AST.ite (cond 0) srcA dstA) + !!ir (dstB := AST.ite (cond 1) srcB dstB) + !!ir (dstC := AST.ite (cond 2) srcC dstC) + !!ir (dstD := AST.ite (cond 3) srcD dstD) + | _ -> raise InvalidOperandException + | 512 -> + let kl, vl = 8, 512 + match dst with + | OprReg _ -> + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = + transOprToExpr512 ins insLen ctxt src + !!ir (dstA := AST.ite (cond 0) srcA (masking dstA)) + !!ir (dstB := AST.ite (cond 1) srcB (masking dstB)) + !!ir (dstC := AST.ite (cond 2) srcC (masking dstC)) + !!ir (dstD := AST.ite (cond 3) srcD (masking dstD)) + !!ir (dstE := AST.ite (cond 4) srcE (masking dstE)) + !!ir (dstF := AST.ite (cond 5) srcF (masking dstF)) + !!ir (dstG := AST.ite (cond 6) srcG (masking dstG)) + !!ir (dstH := AST.ite (cond 7) srcH (masking dstH)) + | OprMem _ -> + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = + transOprToExpr512 ins insLen ctxt src + !!ir (dstA := AST.ite (cond 0) srcA dstA) + !!ir (dstB := AST.ite (cond 1) srcB dstB) + !!ir (dstC := AST.ite (cond 2) srcC dstC) + !!ir (dstD := AST.ite (cond 3) srcD dstD) + !!ir (dstE := AST.ite (cond 4) srcE dstE) + !!ir (dstF := AST.ite (cond 5) srcF dstF) + !!ir (dstG := AST.ite (cond 6) srcG dstG) + !!ir (dstH := AST.ite (cond 7) srcH dstH) + | _ -> raise InvalidOperandException + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vmovntdq ins insLen ctxt = + SSELifter.buildMove ins insLen ctxt 16 + +let vmovups ins insLen ctxt = + buildVectorMove ins insLen ctxt + +let vmovupd ins insLen ctxt = + buildVectorMove ins insLen ctxt + +let vmovddup ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + ! -> + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src = transOprToExpr64 ins insLen ctxt src + !!ir (dst1 := src) + !!ir (dst2 := src) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst + let _src4, src3, _src2, src1 = transOprToExpr256 ins insLen ctxt src + !!ir (dst1 := src1) + !!ir (dst2 := src1) + !!ir (dst3 := src3) + !!ir (dst4 := src3) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vmovntps ins insLen ctxt = + SSELifter.buildMove ins insLen ctxt 16 + +let vmovntpd ins insLen ctxt = + SSELifter.buildMove ins insLen ctxt 16 + +let vmovhlps ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 + let src2B, _src2A = transOprToExpr128 ins insLen ctxt src2 + !ir insLen + +let vmovhpd (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (8) + ! + if haveEVEXPrx ins.VEXInfo then () + else + let dst = transOprToExpr64 ins insLen ctxt dst + let src2, _src1 = transOprToExpr128 ins insLen ctxt src + !!ir (dst := src2) + | ThreeOperands (dst, src1, src2)-> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let _src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2 = transOprToExpr64 ins insLen ctxt src2 + !!ir (dstA := src1A) + !!ir (dstB := src2) + fillZeroHigh128 ctxt dst ir + | _ -> raise InvalidOperandException + !>ir insLen + +let vmovlhps ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let _src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let _src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + !ir insLen + +let vmovlpd (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (8) + ! + let dst = transOprToExpr64 ins insLen ctxt dst + let _src2, src1 = transOprToExpr128 ins insLen ctxt src + !!ir (dst := src1) + | ThreeOperands (dst, src1, src2)-> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 + let _src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + !!ir (dstA := src2A) + !!ir (dstB := src1B) + fillZeroHigh128 ctxt dst ir + | _ -> raise InvalidOperandException + !>ir insLen + +let vmovmskpd ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr ins insLen ctxt dst + let dstSz = TypeCheck.typeOf dst + let mskpd r = + match Register.getKind r with + | Register.Kind.XMM -> SSELifter.movmskpd ins insLen ctxt + | Register.Kind.YMM -> + ! src1) + let src127 = (AST.sext dstSz (AST.xthi 1 src2)) << AST.num1 dstSz + let src191 = (AST.sext dstSz (AST.xthi 1 src3)) << numI32 2 dstSz + let src255 = (AST.sext dstSz (AST.xthi 1 src4)) << numI32 3 dstSz + !!ir (dst := src63 .| src127 .| src191 .| src255) + !>ir insLen + | _ -> raise InvalidOperandException + match src with + | OprReg r -> mskpd r + | _ -> raise InvalidOperandSizeException + +let vmovmskps ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr ins insLen ctxt dst + let dstSz = TypeCheck.typeOf dst + let mskpd r = + match Register.getKind r with + | Register.Kind.XMM -> SSELifter.movmskps ins insLen ctxt + | Register.Kind.YMM -> + ! src1, AST.xthi 32 src1 + let src2A, src2B = AST.xtlo 32 src2, AST.xthi 32 src2 + let src3A, src3B = AST.xtlo 32 src3, AST.xthi 32 src3 + let src4A, src4B = AST.xtlo 32 src4, AST.xthi 32 src4 + let src31 = AST.sext dstSz (AST.xthi 1 src1A) + let src63 = AST.sext dstSz (AST.xthi 1 src1B) << AST.num1 dstSz + let src95 = (AST.sext dstSz (AST.xthi 1 src2A)) << numI32 2 dstSz + let src127 = (AST.sext dstSz (AST.xthi 1 src2B)) << numI32 3 dstSz + let src159 = (AST.sext dstSz (AST.xthi 1 src3A)) << numI32 4 dstSz + let src191 = (AST.sext dstSz (AST.xthi 1 src3B)) << numI32 5 dstSz + let src223 = (AST.sext dstSz (AST.xthi 1 src4A)) << numI32 6 dstSz + let src255 = (AST.sext dstSz (AST.xthi 1 src4B)) << numI32 7 dstSz + !!ir (dst := src31 .| src63 .| src95 .| src127) + !!ir (dst := dst .| src159 .| src191 .| src223 .| src255) + !>ir insLen + | _ -> raise InvalidOperandException + match src with + | OprReg r -> mskpd r + | _ -> raise InvalidOperandSizeException + +let vmovsd (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (8) + ! SSELifter.movsd ins insLen ctxt + | TwoOperands (OprReg _ as dst, src) -> + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src = transOprToExpr64 ins insLen ctxt src + !!ir (dst1 := src) + !!ir (dst2 := AST.num0 64) + fillZeroHigh128 ctxt dst ir + !>ir insLen + | ThreeOperands (dst, src1, src2)-> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 + let _src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + !!ir (dstA := src2A) + !!ir (dstB := src1B) + fillZeroHigh128 ctxt dst ir + !>ir insLen + | _ -> raise InvalidOperandException + +let vmovshdup ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src) = getTwoOprs ins + ! -> + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + !!ir (AST.xtlo 32 dst1 := AST.xthi 32 src1) + !!ir (AST.xthi 32 dst1 := AST.xthi 32 src1) + !!ir (AST.xtlo 32 dst2 := AST.xthi 32 src2) + !!ir (AST.xthi 32 dst2 := AST.xthi 32 src2) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst + let src4, src3, src2, src1 = transOprToExpr256 ins insLen ctxt src + !!ir (AST.xtlo 32 dst1 := AST.xthi 32 src1) + !!ir (AST.xthi 32 dst1 := AST.xthi 32 src1) + !!ir (AST.xtlo 32 dst2 := AST.xthi 32 src2) + !!ir (AST.xthi 32 dst2 := AST.xthi 32 src2) + !!ir (AST.xtlo 32 dst3 := AST.xthi 32 src3) + !!ir (AST.xthi 32 dst3 := AST.xthi 32 src3) + !!ir (AST.xtlo 32 dst4 := AST.xthi 32 src4) + !!ir (AST.xthi 32 dst4 := AST.xthi 32 src4) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vmovsldup ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src) = getTwoOprs ins + ! -> + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + !!ir (AST.xtlo 32 dst1 := AST.xtlo 32 src1) + !!ir (AST.xthi 32 dst1 := AST.xtlo 32 src1) + !!ir (AST.xtlo 32 dst2 := AST.xtlo 32 src2) + !!ir (AST.xthi 32 dst2 := AST.xtlo 32 src2) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst + let src4, src3, src2, src1 = transOprToExpr256 ins insLen ctxt src + !!ir (AST.xtlo 32 dst1 := AST.xtlo 32 src1) + !!ir (AST.xthi 32 dst1 := AST.xtlo 32 src1) + !!ir (AST.xtlo 32 dst2 := AST.xtlo 32 src2) + !!ir (AST.xthi 32 dst2 := AST.xtlo 32 src2) + !!ir (AST.xtlo 32 dst3 := AST.xtlo 32 src3) + !!ir (AST.xthi 32 dst3 := AST.xtlo 32 src3) + !!ir (AST.xtlo 32 dst4 := AST.xtlo 32 src4) + !!ir (AST.xthi 32 dst4 := AST.xtlo 32 src4) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vmovss (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (8) + ! SSELifter.movss ins insLen ctxt + | TwoOperands (OprReg _ as dst, src) -> + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src = transOprToExpr32 ins insLen ctxt src + !!ir (AST.xtlo 32 dst1 := src) + !!ir (AST.xthi 32 dst1 := AST.num0 32) + !!ir (dst2 := AST.num0 64) + fillZeroHigh128 ctxt dst ir + !>ir insLen + | ThreeOperands (dst, src1, src2)-> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let _src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + !!ir (AST.xtlo 32 dstA := AST.xtlo 32 src2A) + !!ir (AST.xthi 32 dstA := AST.xthi 32 src1A) + !!ir (dstB := src1B) + fillZeroHigh128 ctxt dst ir + !>ir insLen + | _ -> raise InvalidOperandException + +let vandps ins insLen ctxt = + vexedPackedFPBinOp32 ins insLen ctxt (.&) + +let vandpd ins insLen ctxt = + vexedPackedFPBinOp64 ins insLen ctxt (.&) + +let private andnpdOp e1 e2 = (AST.not e1) .& e2 + +let vandnps ins insLen ctxt = + vexedPackedFPBinOp32 ins insLen ctxt andnpdOp + +let vandnpd ins insLen ctxt = + vexedPackedFPBinOp64 ins insLen ctxt andnpdOp + +let vorps ins insLen ctxt = + vexedPackedFPBinOp32 ins insLen ctxt (.|) + +let vorpd ins insLen ctxt = + vexedPackedFPBinOp64 ins insLen ctxt (.|) + +let vshufi32x4 ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src1, src2, imm) = getFourOprs ins + let oprSize = getOperationSize ins + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) + let masking dst = + match ePrx.Z with + | Zeroing -> AST.num0 32 + | Merging -> dst + let cond idx = + (* no write mask *) + let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 + AST.extract k 1 idx .| noWritemask + let imm = transOprToExpr ins insLen ctxt imm + let struct (tmpDest, tmp) = tmpVars2 ir oprSize + ! -> + let kl, vl = 8, 256 + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let src1D, src1C, src1B, src1A = + transOprToExpr256 ins insLen ctxt src1 + let src2D, src2C, src2B, src2A = + transOprToExpr256 ins insLen ctxt src2 + let conSrc1 = AST.concat (AST.concat src1D src1C) (AST.concat src1B src1A) + let conSrc2 = AST.concat (AST.concat src2D src2C) (AST.concat src2B src2A) + let srcLow src = AST.extract src 128 0 + let srcHigh src = AST.extract src 128 128 + let select2 src pos = AST.ite (AST.extract imm 1 pos) (srcHigh src) (srcLow src) + !!ir (AST.extract tmpDest 128 0 := select2 conSrc1 0) + !!ir (AST.extract tmpDest 128 128 := select2 conSrc2 1) + let assign dst idx dstPos tmpPos = + let dst = AST.extract dst 32 dstPos + dst := AST.ite (cond idx) (AST.extract tmpDest 32 tmpPos) (masking dst) + !!ir (assign dstA 0 0 0) + !!ir (assign dstA 1 32 32) + !!ir (assign dstB 2 0 64) + !!ir (assign dstB 3 32 96) + !!ir (assign dstC 4 0 128) + !!ir (assign dstC 5 32 160) + !!ir (assign dstD 6 0 192) + !!ir (assign dstD 7 32 224) + | 512 -> + let kl, vl = 16, 512 + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let src1H, src1G, src1F, src1E, src1D, src1C, src1B, src1A = + transOprToExpr512 ins insLen ctxt src1 + let src2H, src2G, src2F, src2E, src2D, src2C, src2B, src2A = + transOprToExpr512 ins insLen ctxt src2 + let conSrc1 = AST.concat (AST.concat (AST.concat src1H src1G) (AST.concat src1F src1E)) + (AST.concat (AST.concat src1D src1C) (AST.concat src1B src1A)) + let conSrc2 = AST.concat (AST.concat (AST.concat src2H src2G) (AST.concat src2F src2E)) + (AST.concat (AST.concat src2D src2C) (AST.concat src2B src2A)) + let src128 src = AST.extract src 128 0 + let src256 src = AST.extract src 128 128 + let src384 src = AST.extract src 128 256 + let src512 src = AST.extract src 128 384 + let n0 = AST.num0 2 + let n1 = AST.num1 2 + let n2 = numI32 2 2 + let control pos = AST.extract imm 2 pos + let select4 src pos = + let control = control pos + AST.ite (control == n0) (src128 src) + (AST.ite (control == n1) (src256 src) (AST.ite (control == n2) (src384 src) + (src512 src))) + let tmpSrc2 = Array.init kl (fun _ -> !*ir 32) + for i in 0 .. kl - 1 do + let tSrc2 = + match src2 with + | OprMem _ when ePrx.B = 1uy -> AST.extract src2A 32 0 + | _ -> AST.extract conSrc2 32 (i * 32) + !!ir (tmpSrc2.[i] := tSrc2) + let tmpSrc2 = AST.concatArr tmpSrc2 + !!ir (AST.extract tmpDest 128 0 := select4 conSrc1 0) + !!ir (AST.extract tmpDest 128 128 := select4 conSrc2 2) + !!ir (AST.extract tmpDest 128 256 := select4 tmpSrc2 4) + !!ir (AST.extract tmpDest 128 384 := select4 tmpSrc2 6) + let assign dst idx dstPos tmpPos = + let dst = AST.extract dst 32 dstPos + dst := AST.ite (cond idx) (AST.extract tmpDest 32 tmpPos) (masking dst) + !!ir (assign dstA 0 0 0) + !!ir (assign dstA 1 32 32) + !!ir (assign dstB 2 0 64) + !!ir (assign dstB 3 32 96) + !!ir (assign dstC 4 0 128) + !!ir (assign dstC 5 32 160) + !!ir (assign dstD 6 0 192) + !!ir (assign dstD 7 32 224) + !!ir (assign dstE 8 0 256) + !!ir (assign dstE 9 32 288) + !!ir (assign dstF 10 0 320) + !!ir (assign dstF 11 32 352) + !!ir (assign dstG 12 0 384) + !!ir (assign dstG 13 32 416) + !!ir (assign dstH 14 0 448) + !!ir (assign dstH 15 32 480) + | _ -> raise InvalidOperandException + !>ir insLen + +let vshufps ins insLen ctxt = + let ir = IRBuilder (32) + let struct (dst, src1, src2, imm) = getFourOprs ins + let imm = transOprToExpr ins insLen ctxt imm + let cond1 = AST.xtlo 2 imm + let cond2 = AST.extract imm 2 2 + let cond3 = AST.extract imm 2 4 + let cond4 = AST.extract imm 2 6 + let doShuf cond dst e1 e2 = + !!ir (dst := AST.num0 32) + !!ir (dst := AST.ite (cond == AST.num0 2) (AST.xtlo 32 e1) dst) + !!ir (dst := AST.ite (cond == AST.num1 2) (AST.xthi 32 e1) dst) + !!ir (dst := AST.ite (cond == numI32 2 2) (AST.xtlo 32 e2) dst) + !!ir (dst := AST.ite (cond == numI32 3 2) (AST.xthi 32 e2) dst) + ! -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let sr1B, sr1A = transOprToExpr128 ins insLen ctxt src1 + let sr2B, sr2A = transOprToExpr128 ins insLen ctxt src2 + doShuf cond1 (AST.xtlo 32 dstA) sr1A sr1B + doShuf cond2 (AST.xthi 32 dstA) sr1A sr1B + doShuf cond3 (AST.xtlo 32 dstB) sr2A sr2B + doShuf cond4 (AST.xthi 32 dstB) sr2A sr2B + fillZeroHigh128 ctxt dst ir + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ins insLen ctxt src1 + let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ins insLen ctxt src2 + doShuf cond1 (AST.xtlo 32 dstA) sr1A sr1B + doShuf cond2 (AST.xthi 32 dstA) sr1A sr1B + doShuf cond3 (AST.xtlo 32 dstB) sr2A sr2B + doShuf cond4 (AST.xthi 32 dstB) sr2A sr2B + doShuf cond1 (AST.xtlo 32 dstC) sr1C sr1D + doShuf cond2 (AST.xthi 32 dstC) sr1C sr1D + doShuf cond3 (AST.xtlo 32 dstD) sr2C sr2D + doShuf cond4 (AST.xthi 32 dstD) sr2C sr2D + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vshufpd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2, imm) = getFourOprs ins + let imm = transOprToExpr ins insLen ctxt imm + let cond1 = AST.xtlo 1 imm + let cond2 = AST.extract imm 1 1 + let cond3 = AST.extract imm 1 2 + let cond4 = AST.extract imm 1 3 + ! -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + !!ir (dstA := AST.ite cond1 src1B src1A) + !!ir (dstB := AST.ite cond2 src2B src2A) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ins insLen ctxt src1 + let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ins insLen ctxt src2 + !!ir (dstA := AST.ite cond1 sr1B sr1A) + !!ir (dstB := AST.ite cond2 sr2B sr2A) + !!ir (dstC := AST.ite cond3 sr1C sr1D) + !!ir (dstB := AST.ite cond4 sr2C sr2D) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vunpckhps ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src1, src2) = getThreeOprs ins + ! -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 + let src2B, _src2A = transOprToExpr128 ins insLen ctxt src2 + !!ir (AST.xtlo 32 dstA := AST.xtlo 32 src1B) + !!ir (AST.xthi 32 dstA := AST.xtlo 32 src2B) + !!ir (AST.xtlo 32 dstB := AST.xthi 32 src1B) + !!ir (AST.xthi 32 dstB := AST.xthi 32 src2B) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let sr1D, _, sr1B, _ = transOprToExpr256 ins insLen ctxt src1 + let sr2D, _, sr2B, _ = transOprToExpr256 ins insLen ctxt src2 + !!ir (AST.xtlo 32 dstA := AST.xtlo 32 sr1B) + !!ir (AST.xthi 32 dstA := AST.xtlo 32 sr2B) + !!ir (AST.xtlo 32 dstB := AST.xthi 32 sr1B) + !!ir (AST.xthi 32 dstB := AST.xthi 32 sr2B) + !!ir (AST.xtlo 32 dstC := AST.xtlo 32 sr1D) + !!ir (AST.xthi 32 dstC := AST.xtlo 32 sr2D) + !!ir (AST.xtlo 32 dstD := AST.xthi 32 sr1D) + !!ir (AST.xthi 32 dstD := AST.xthi 32 sr2D) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vunpckhpd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2) = getThreeOprs ins + ! -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 + let src2B, _src2A = transOprToExpr128 ins insLen ctxt src2 + !!ir (dstA := src1B) + !!ir (dstB := src2B) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let sr1D, _, sr1B, _ = transOprToExpr256 ins insLen ctxt src1 + let sr2D, _, sr2B, _ = transOprToExpr256 ins insLen ctxt src2 + !!ir (dstA := sr1B) + !!ir (dstB := sr2B) + !!ir (dstC := sr1D) + !!ir (dstD := sr2D) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vunpcklps ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src1, src2) = getThreeOprs ins + ! -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let _src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let _src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + !!ir (AST.xtlo 32 dstA := AST.xtlo 32 src1A) + !!ir (AST.xthi 32 dstA := AST.xtlo 32 src2A) + !!ir (AST.xtlo 32 dstB := AST.xthi 32 src1A) + !!ir (AST.xthi 32 dstB := AST.xthi 32 src2A) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let _, src1C, _, src1A = transOprToExpr256 ins insLen ctxt src1 + let _, src2C, _, src2A = transOprToExpr256 ins insLen ctxt src2 + !!ir (AST.xtlo 32 dstA := AST.xtlo 32 src1A) + !!ir (AST.xthi 32 dstA := AST.xtlo 32 src2A) + !!ir (AST.xtlo 32 dstB := AST.xthi 32 src1A) + !!ir (AST.xthi 32 dstB := AST.xthi 32 src2A) + !!ir (AST.xtlo 32 dstC := AST.xtlo 32 src1C) + !!ir (AST.xthi 32 dstC := AST.xtlo 32 src2C) + !!ir (AST.xtlo 32 dstD := AST.xthi 32 src1C) + !!ir (AST.xthi 32 dstD := AST.xthi 32 src2C) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vunpcklpd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2) = getThreeOprs ins + ! -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let _src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let _src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + !!ir (dstA := src1A) + !!ir (dstB := src2A) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let _, src1C, _, src1A = transOprToExpr256 ins insLen ctxt src1 + let _, src2C, _, src2A = transOprToExpr256 ins insLen ctxt src2 + !!ir (dstA := src1A) + !!ir (dstB := src2A) + !!ir (dstC := src1C) + !!ir (dstD := src2C) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vxorps ins insLen ctxt = + match getOperationSize ins with + | 512 -> + let ir = IRBuilder (16) + let struct (dst, src1, src2) = getThreeOprs ins + ! Disasm.getOpmaskRegister) + let masking dst = + match ePrx.Z with + | Zeroing -> AST.num0 32 + | Merging -> dst + let cond idx = + (* no write mask *) + let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 + AST.extract k 1 idx .| noWritemask + let tmpDest = Array.init 2 (fun _ -> !*ir 32) + let evAssign dst s1 s2 src2A idx = + for i in 0 .. 1 do + let s1 = AST.extract s1 32 (i * 32) + let s2 = AST.extract s2 32 (i * 32) + let dst = AST.extract dst 32 (i * 32) + let tSrc = + match src2 with + | OprMem _ when ePrx.AAA (* B *) = 1uy -> + s1 <+> (AST.extract src2A 32 0) + | _ -> s1 <+> s2 + !!ir (tmpDest.[i] := AST.ite (cond (idx + i)) tSrc (masking dst)) + AST.concatArr tmpDest + let kl, vl = 16, 512 + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let src1H, src1G, src1F, src1E, src1D, src1C, src1B, src1A = + transOprToExpr512 ins insLen ctxt src1 + let src2H, src2G, src2F, src2E, src2D, src2C, src2B, src2A = + transOprToExpr512 ins insLen ctxt src2 + !!ir (dstA := evAssign dstA src1A src2A src2A 0) + !!ir (dstB := evAssign dstB src1B src2B src2A 2) + !!ir (dstC := evAssign dstC src1C src2C src2A 4) + !!ir (dstD := evAssign dstD src1D src2D src2A 6) + !!ir (dstE := evAssign dstE src1E src2E src2A 8) + !!ir (dstF := evAssign dstF src1F src2F src2A 10) + !!ir (dstG := evAssign dstG src1G src2G src2A 12) + !!ir (dstH := evAssign dstH src1H src2H src2A 14) + !>ir insLen + | _ -> vexedPackedFPBinOp32 ins insLen ctxt (<+>) + +let vxorpd ins insLen ctxt = + vexedPackedFPBinOp64 ins insLen ctxt (<+>) + +let vbroadcasti128 ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + !ir insLen + +let vbroadcastss ins insLen ctxt = + let ir = IRBuilder (32) + let struct (dst, src) = getTwoOprs ins + let src = transOprToExpr32 ins insLen ctxt src + let tmp = !*ir 32 + ! -> + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + !!ir (tmp := src) + !!ir (AST.xtlo 32 dst1 := tmp) + !!ir (AST.xthi 32 dst1 := tmp) + !!ir (AST.xtlo 32 dst2 := tmp) + !!ir (AST.xthi 32 dst2 := tmp) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst + !!ir (tmp := src) + !!ir (AST.xtlo 32 dst1 := tmp) + !!ir (AST.xthi 32 dst1 := tmp) + !!ir (AST.xtlo 32 dst2 := tmp) + !!ir (AST.xthi 32 dst2 := tmp) + !!ir (AST.xtlo 32 dst3 := tmp) + !!ir (AST.xthi 32 dst3 := tmp) + !!ir (AST.xtlo 32 dst4 := tmp) + !!ir (AST.xthi 32 dst4 := tmp) + | 512 -> () + | _ -> raise InvalidOperandException + !>ir insLen + +let vextracti32x8 ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src, imm) = getThreeOprs ins + let oprSize = getOperationSize ins + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) + let masking dst = + match ePrx.Z with + | Zeroing -> AST.num0 32 + | Merging -> dst + let cond idx = + (* no write mask *) + let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 + AST.extract k 1 idx .| noWritemask + let tDest = !*ir 256 + let vl = 512 + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = + transOprToExpr512 ins insLen ctxt src + let imm = transOprToExpr ins insLen ctxt imm + ! imm) srcHigh srcLow) + match dst with + | OprReg _ -> + let tmps = Array.init 2 (fun _ -> !*ir 32) + let assign dst src idx = + for i in 0 .. 1 do + let dstPos = i * 32 + let srcPos = 32 * (idx + i) + let dst = AST.extract dst 32 dstPos + let src = AST.extract src 32 srcPos + !!ir + (tmps.[i] := AST.ite (cond (idx + i)) src (masking dst)) + AST.concatArr tmps + !!ir (dstA := assign dstA tDest 0) + !!ir (dstB := assign dstB tDest 2) + !!ir (dstC := assign dstC tDest 4) + !!ir (dstD := assign dstD tDest 6) + | OprMem _ -> + let tmps = Array.init 2 (fun _ -> !*ir 32) + let assign dst src idx = + for i in 0 .. 1 do + let dstPos = i * 32 + let srcPos = 32 * (idx + i) + let dst = AST.extract dst 32 dstPos + !!ir + (tmps.[i] := AST.ite (cond (idx + i)) (AST.extract src 32 srcPos) dst) + AST.concatArr tmps + !!ir (dstA := assign dstA tDest 0) + !!ir (dstB := assign dstB tDest 2) + !!ir (dstC := assign dstC tDest 4) + !!ir (dstD := assign dstD tDest 6) + | _ -> raise InvalidOperandException + !>ir insLen + +let vextracti64x4 ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src, imm) = getThreeOprs ins + let oprSize = getOperationSize ins + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) + let masking dst = + match ePrx.Z with + | Zeroing -> AST.num0 64 + | Merging -> dst + let cond idx = + (* no write mask *) + let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 + AST.extract k 1 idx .| noWritemask + let tDest = !*ir 256 + let vl = 512 + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = + transOprToExpr512 ins insLen ctxt src + let imm = transOprToExpr ins insLen ctxt imm + ! imm) srcHigh srcLow) + match dst with + | OprReg _ -> + !!ir (dstA := AST.ite (cond 0) (AST.extract tDest 64 0) (masking dstA)) + !!ir (dstB := AST.ite (cond 1) (AST.extract tDest 64 64) (masking dstB)) + !!ir (dstC := AST.ite (cond 2) (AST.extract tDest 64 128) (masking dstC)) + !!ir (dstD := AST.ite (cond 3) (AST.extract tDest 64 192) (masking dstD)) + | OprMem _ -> + !!ir (dstA := AST.ite (cond 0) (AST.extract tDest 64 0) dstA) + !!ir (dstB := AST.ite (cond 1) (AST.extract tDest 64 64) dstB) + !!ir (dstC := AST.ite (cond 2) (AST.extract tDest 64 128) dstC) + !!ir (dstD := AST.ite (cond 3) (AST.extract tDest 64 192) dstD) + | _ -> raise InvalidOperandException + !>ir insLen + +let vinserti128 ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2, imm) = getFourOprs ins + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let src1D, src1C, src1B, src1A = transOprToExpr256 ins insLen ctxt src1 + let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + let imm = transOprToExpr ins insLen ctxt imm + let cond = !*ir 1 + ! imm) + !!ir (dstA := AST.ite cond src1A src2A) + !!ir (dstB := AST.ite cond src1B src2B) + !!ir (dstC := AST.ite cond src2A src1C) + !!ir (dstD := AST.ite cond src2B src1D) + !>ir insLen + +let vpaddb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 (opP (.+)) 32 + +let vpaddd ins insLen ctxt = + match getOperationSize ins with + | 512 -> + let ir = IRBuilder (16) + let struct (dst, src1, src2) = getThreeOprs ins + ! Disasm.getOpmaskRegister) + let masking dst = + match ePrx.Z with + | Zeroing -> AST.num0 32 + | Merging -> dst + let cond idx = + (* no write mask *) + let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 + AST.extract k 1 idx .| noWritemask + let tmpDest = Array.init 2 (fun _ -> !*ir 32) + let evAssign dst s1 s2 src2A idx = + for i in 0 .. 1 do + let s1 = AST.extract s1 32 (i * 32) + let s2 = AST.extract s2 32 (i * 32) + let dst = AST.extract dst 32 (i * 32) + let tSrc = + match src2 with + | OprMem _ when ePrx.AAA (* B *) = 1uy -> + s1 .+ (AST.extract src2A 32 0) + | _ -> s1 .+ s2 + !!ir (tmpDest.[i] := AST.ite (cond (idx + i)) tSrc (masking dst)) + AST.concatArr tmpDest + let kl, vl = 16, 512 + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let src1H, src1G, src1F, src1E, src1D, src1C, src1B, src1A = + transOprToExpr512 ins insLen ctxt src1 + let src2H, src2G, src2F, src2E, src2D, src2C, src2B, src2A = + transOprToExpr512 ins insLen ctxt src2 + !!ir (dstA := evAssign dstA src1A src2A src2A 0) + !!ir (dstB := evAssign dstB src1B src2B src2A 2) + !!ir (dstC := evAssign dstC src1C src2C src2A 4) + !!ir (dstD := evAssign dstD src1D src2D src2A 6) + !!ir (dstE := evAssign dstE src1E src2E src2A 8) + !!ir (dstF := evAssign dstF src1F src2F src2A 10) + !!ir (dstG := evAssign dstG src1G src2G src2A 12) + !!ir (dstH := evAssign dstH src1H src2H src2A 14) + !>ir insLen + | _ -> buildPackedInstr ins insLen ctxt 32 (opP (.+)) 16 + +let vpaddq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 (opP (.+)) 16 + +let vpalignr ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src1, src2, imm) = getFourOprs ins + let oprSize = getOperationSize ins + let imm = transOprToExpr ins insLen ctxt imm + let n8 = numU32 8u 256 + let imm = AST.zext 256 imm + ! then + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + let t = !*ir 256 + let struct (tSrc1, tSrc2) = tmpVars2 ir oprSize + !!ir (tSrc1 := AST.concat src1B src1A) + !!ir (tSrc2 := AST.concat src2B src2A) + !!ir (t := (AST.concat tSrc1 tSrc2) >> (imm .* n8)) + !!ir (dstA := AST.xtlo 64 t) + !!ir (dstB := AST.xthi 64 (AST.xtlo 128 t)) + fillZeroHigh128 ctxt dst ir + elif oprSize = 256 then + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let src1D, src1C, src1B, src1A = transOprToExpr256 ins insLen ctxt src1 + let src2D, src2C, src2B, src2A = transOprToExpr256 ins insLen ctxt src2 + let struct (t1, t2) = tmpVars2 ir 256 + let struct (tSrc1High, tSrc1Low, tSrc2High, tSrc2Low) = tmpVars4 ir 128 + !!ir (tSrc1Low := AST.concat src1B src1A) + !!ir (tSrc1High := AST.concat src1D src1C) + !!ir (tSrc2Low := AST.concat src2B src2A) + !!ir (tSrc2High := AST.concat src2D src2C) + !!ir (t1 := (AST.concat tSrc1Low tSrc2Low) >> (imm .* n8)) + !!ir (dstA := AST.xtlo 64 t1) + !!ir (dstB := AST.xthi 64 (AST.xtlo 128 t1)) + !!ir (t2 := (AST.concat tSrc1High tSrc2High) >> (imm .* n8)) + !!ir (dstC := AST.xtlo 64 t2) + !!ir (dstD := AST.xthi 64 (AST.xtlo 128 t2)) + else raise InvalidOperandSizeException + !>ir insLen + +let vpand ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPand 16 + +let vpandn ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPandn 16 + +let vpbroadcastb ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let oprSize = getOperationSize ins + match oprSize with + | 512 -> () (* FIXME: #196 *) + | _ -> + let src = + match src with + | OprReg _ -> transOprToExpr128 ins insLen ctxt src |> snd + | OprMem _ -> transOprToExpr ins insLen ctxt src + | _ -> raise InvalidOperandException + |> AST.xtlo 8 + let tSrc = !*ir 8 + ! !*ir 8) + for i in 0 .. 7 do !!ir (tmps.[i] := tSrc) done + let t = !*ir 64 + !!ir (t := AST.concatArr tmps) + match oprSize with + | 128 -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + !!ir (dstA := t) + !!ir (dstB := t) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + !!ir (dstA := t) + !!ir (dstB := t) + !!ir (dstC := t) + !!ir (dstD := t) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vpbroadcastd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let oprSize = getOperationSize ins + let temp = !*ir 32 + let src = + match src with + | OprReg r -> + match Register.getKind r with + | Register.Kind.XMM -> + transOprToExpr128 ins insLen ctxt src |> snd + | Register.Kind.GP -> transOprToExpr ins insLen ctxt src + | _ -> raise InvalidOperandException + | OprMem _ -> transOprToExpr ins insLen ctxt src + | _ -> raise InvalidOperandException + |> AST.xtlo 32 + ! -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + !!ir (AST.extract dstA 32 0 := temp) + !!ir (AST.extract dstA 32 32 := temp) + !!ir (AST.extract dstB 32 0 := temp) + !!ir (AST.extract dstB 32 32 := temp) + fillZeroFromVLToMaxVL ctxt dst 128 512 ir + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + !!ir (AST.extract dstA 32 0 := temp) + !!ir (AST.extract dstA 32 32 := temp) + !!ir (AST.extract dstB 32 0 := temp) + !!ir (AST.extract dstB 32 32 := temp) + !!ir (AST.extract dstC 32 0 := temp) + !!ir (AST.extract dstC 32 32 := temp) + !!ir (AST.extract dstD 32 0 := temp) + !!ir (AST.extract dstD 32 32 := temp) + fillZeroFromVLToMaxVL ctxt dst 256 512 ir + | 512 -> + let kl, vl = 16, 512 + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) + let masking dst = + match ePrx.Z with + | Zeroing -> AST.num0 32 + | Merging -> dst + let cond idx = + (* no write mask *) + let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 + AST.extract k 1 idx .| noWritemask + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let assign dst idx sPos = + let extDst = AST.extract dst 32 sPos + extDst := AST.ite (cond idx) temp (masking extDst) + !!ir (assign dstA 0 0) + !!ir (assign dstA 1 32) + !!ir (assign dstB 2 0) + !!ir (assign dstB 3 32) + !!ir (assign dstC 4 0) + !!ir (assign dstC 5 32) + !!ir (assign dstD 6 0) + !!ir (assign dstD 7 32) + !!ir (assign dstE 8 0) + !!ir (assign dstE 9 32) + !!ir (assign dstF 10 0) + !!ir (assign dstF 11 32) + !!ir (assign dstG 12 0) + !!ir (assign dstG 13 32) + !!ir (assign dstH 14 0) + !!ir (assign dstH 15 32) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vpcmpeqb ins insLen ctxt = + match getOperationSize ins with + | 512 -> GeneralLifter.nop insLen (* FIXME: #197 *) + | _ -> buildPackedInstr ins insLen ctxt 8 opPcmpeqb 64 + +let vpcmpeqd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPcmpeqd 32 + +let vpcmpeqq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 SSELifter.opPcmpeqq 16 + +let vpcmpgtb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPcmpgtb 64 + +let vpinsrd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2, imm) = getFourOprs ins + let oprSize = getOperationSize ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2 = transOprToExpr ins insLen ctxt src2 + let imm = transOprToExpr ins insLen ctxt imm + let struct (sel, mask, temp, tDst) = tmpVars4 ir 128 + ! (AST.xtlo 2 imm)) + !!ir (mask := numU64 0xFFFFFFFFUL 128 << (sel .* numI32 32 128)) + !!ir + (temp := ((AST.zext 128 src2) << (sel .* numI32 32 128)) .& mask) + !!ir (tDst := (((AST.concat src1B src1A) .& AST.not mask) .| temp)) + !!ir (dstA := AST.extract tDst 64 0) + !!ir (dstB := AST.extract tDst 64 64) + fillZeroFromVLToMaxVL ctxt dst 128 512 ir + !>ir insLen + +let vpminub ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 SSELifter.opPminub 64 + +let vpminud ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 SSELifter.opPminud 32 + +let private opVpmuludq _ = + let low32 expr = expr .& numI64 0xffffffffL 64 + Array.map2 (fun e1 e2 -> low32 e1 .* low32 e2) + +let vpmuludq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opVpmuludq 16 + +let vpor ins insLen ctxt = + match getOperationSize ins with + | 512 -> GeneralLifter.nop insLen + | _ -> buildPackedInstr ins insLen ctxt 64 opPor 8 + +let vpshufb ins insLen ctxt = + let struct (dst, src1, src2) = getThreeOprs ins + let oprSize = getOperationSize ins + let cnt = if oprSize = 128 then 16 else 32 + let ir = IRBuilder (2 * cnt) + let struct (tDst, tSrc1, tSrc2) = tmpVars3 ir oprSize + ! -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + !!ir (tSrc1 := AST.concat src1B src1A) + !!ir (tSrc2 := AST.concat src2B src2A) + let tmps = Array.init cnt (fun _ -> !*ir 8) + let mask = numU32 0x0Fu 8 + for i in 0 .. cnt - 1 do + let cond = AST.extract tSrc2 1 (i * 8 + 7) + let idx = (AST.extract tSrc2 8 (i * 8)) .& mask + let s = AST.zext oprSize idx .* numI32 8 oprSize + !!ir + (tmps.[i] := AST.ite cond (AST.num0 8) (AST.xtlo 8 (tSrc1 >> s))) + done + !!ir (tDst := AST.concatArr tmps) + !!ir (dstA := AST.xtlo 64 tDst) + !!ir (dstB := AST.xthi 64 tDst) + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let src1D, src1C, src1B, src1A = + transOprToExpr256 ins insLen ctxt src1 + let src2D, src2C, src2B, src2A = + transOprToExpr256 ins insLen ctxt src2 + !!ir (tSrc1 := AST.concat (AST.concat src1D src1C) (AST.concat src1B src1A)) + !!ir (tSrc2 := AST.concat (AST.concat src2D src2C) (AST.concat src2B src2A)) + let tmps = Array.init cnt (fun _ -> !*ir 8) + let mask = numU32 0x0Fu 8 + for i in 0 .. cnt - 1 do + let cond = AST.extract tSrc2 1 (i * 8 + 7) + let idx = (AST.extract tSrc2 8 (i * 8)) .& mask + let s = AST.zext oprSize idx .* numI32 8 oprSize + !!ir + (tmps.[i] := AST.ite cond (AST.num0 8) (AST.xtlo 8 (tSrc1 >> s))) + done + !!ir (tDst := AST.concatArr tmps) + !!ir (dstA := AST.xtlo 64 tDst) + !!ir (dstB := AST.extract tDst 64 64) + !!ir + (dstC := AST.extract tDst 64 (RegType.toBitWidth (TypeCheck.typeOf tDst) - 64)) + !!ir (dstD := AST.xthi 64 tDst) + | 512 -> + let kl, vl = 64, 512 + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) + let cond idx = + if ePrx.AAA = 0uy then AST.num0 1 (* no write mask *) + else AST.extract k 1 idx + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let src1H, src1G, src1F, src1E, src1D, src1C, src1B, src1A = + transOprToExpr512 ins insLen ctxt src1 + let src2H, src2G, src2F, src2E, src2D, src2C, src2B, src2A = + transOprToExpr512 ins insLen ctxt src2 + !!ir + (tSrc1 := AST.concat (AST.concat (AST.concat src1H src1G) (AST.concat src1F src1E)) + (AST.concat (AST.concat src1D src1C) (AST.concat src1B src1A))) + !!ir + (tSrc2 := AST.concat (AST.concat (AST.concat src2H src2G) (AST.concat src2F src2E)) + (AST.concat (AST.concat src2D src2C) (AST.concat src2B src2A))) + let num0F = numU32 0x0Fu 8 + let jmask = !*ir 8 + let tmps = Array.init kl (fun _ -> !*ir 8) + !!ir (jmask := numI32 (kl - 1) 8 .& (AST.not num0F)) + for i in 0 .. kl - 1 do + let cond idx = + (* no write mask *) + let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 + AST.extract k 1 idx .| noWritemask + let index1 = AST.extract tSrc2 8 (i * 8) + let index2 = (index1 .& num0F) .+ (numI32 i 8 .& jmask) + let src1 = + AST.xtlo 8 (tSrc1 >> (AST.zext oprSize (index2 .* numI32 8 8))) + !!ir (tmps.[i] := AST.ite (cond i) (AST.ite (AST.xthi 1 index1) + (AST.num0 8) src1) (AST.num0 8)) + done + !!ir (tDst := AST.concatArr tmps) + !!ir (dstA := AST.extract tDst 64 0) + !!ir (dstB := AST.extract tDst 64 64) + !!ir (dstC := AST.extract tDst 64 128) + !!ir (dstD := AST.extract tDst 64 192) + !!ir (dstE := AST.extract tDst 64 256) + !!ir (dstF := AST.extract tDst 64 320) + !!ir (dstG := AST.extract tDst 64 384) + !!ir (dstH := AST.extract tDst 64 448) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vpshufd ins insLen ctxt = + let struct (dst, src, ord) = getThreeOprs ins + let ord = transOprToExpr ins insLen ctxt ord + let oprSize = getOperationSize ins + let cnt = RegType.toBitWidth oprSize / 32 + let ir = IRBuilder (2 * cnt) + let tmps = Array.init cnt (fun _ -> !*ir 32) + let n32 = numI32 32 oprSize + let mask2 = numI32 3 32 (* 2-bit mask *) + let tSrc = !*ir oprSize + let tDst = !*ir oprSize + let shuffleDword src = + for i in 1 .. cnt do + let order = + ((AST.xtlo 32 ord) >> (numI32 ((i - 1) * 2) 32)) .& mask2 + let order' = AST.zext oprSize order + !!ir (tmps.[i - 1] := AST.xtlo 32 (src >> (order' .* n32))) + done + ! -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + !!ir (tSrc := AST.concat srcB srcA) + shuffleDword tSrc + !!ir (tDst := AST.concatArr tmps) + !!ir (dstA := AST.extract tDst 64 0) + !!ir (dstB := AST.extract tDst 64 64) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + !!ir (tSrc := AST.concat (AST.concat srcD srcC) (AST.concat srcB srcA)) + shuffleDword tSrc + !!ir (tDst := AST.concatArr tmps) + !!ir (dstA := AST.extract tDst 64 0) + !!ir (dstB := AST.extract tDst 64 64) + !!ir (dstC := AST.extract tDst 64 128) + !!ir (dstD := AST.extract tDst 64 192) + fillZeroHigh256 ctxt dst ir + | 512 -> () (* FIXME: #196 *) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let private opShiftVpackedDataLogical oprSize packSz shift src1 (src2: Expr []) = + let count = src2.[0] |> AST.zext oprSize + let cond = AST.gt count (numI32 ((int packSz) - 1) oprSize) + let shifted expr = AST.extract (shift (AST.zext oprSize expr) count) packSz 0 + Array.map (fun e -> AST.ite cond (AST.num0 packSz) (shifted e)) src1 + +let private opVpslld oprSize = opShiftVpackedDataLogical oprSize 32 (<<) + +let vpslld ins insLen ctxt = + match getOperationSize ins with + | 512 -> GeneralLifter.nop insLen + | _ -> buildPackedInstr ins insLen ctxt 32 opVpslld 16 + +let private shiftVDQ ins insLen ctxt shift = + let ir = IRBuilder (8) + let struct (dst, src, cnt) = getThreeOprs ins + let cnt = transOprToExpr ins insLen ctxt cnt |> castNum 8 + let oprSize = getOperationSize ins + let t = !*ir 8 + !) cnt) (numU32 16u 8) cnt) + match oprSize with + | 128 -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let struct (tDst, tSrc) = tmpVars2 ir 128 + !!ir (tDst := AST.concat dstB dstA) + !!ir (tSrc := AST.concat srcB srcA) + !!ir (tDst := (shift tSrc (AST.zext oprSize (t .* numU32 8u 8)))) + !!ir (dstA := AST.xtlo 64 tDst) + !!ir (dstB := AST.xthi 64 tDst) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + let struct (tDst, tSrc) = tmpVars2 ir 256 + !!ir (tDst := AST.concat (AST.concat dstD dstC) (AST.concat dstB dstA)) + !!ir (tSrc := AST.concat (AST.concat srcD srcC) (AST.concat srcB srcA)) + !!ir (tDst := (shift tSrc (AST.zext oprSize (t .* numU32 8u 8)))) + !!ir (dstA := AST.xtlo 64 tDst) + !!ir (dstB := AST.xtlo 64 tDst) + !!ir (dstC := AST.extract tDst 64 128) + !!ir (dstD := AST.xthi 64 tDst) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let private opVpsllq oprSize = opShiftVpackedDataLogical oprSize 64 (<<) + +let vpsllq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opVpsllq 16 + +let vpslldq ins insLen ctxt = shiftVDQ ins insLen ctxt (<<) + +let vpsrlq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opVpsllq 16 + +let vpsrldq ins insLen ctxt = shiftVDQ ins insLen ctxt (>>) + +let private opVpsrld oprSize = opShiftVpackedDataLogical oprSize 32 (<<) + +let vpsrld ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opVpsrld 16 + +let vpsubb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPsub 128 + +let vptest ins insLen ctxt = + if getOperationSize ins = 128 then SSELifter.ptest ins insLen ctxt + else + let ir = IRBuilder (16) + let struct (src1, src2) = getTwoOprs ins + let src1D, src1C, src1B, src1A = + transOprToExpr256 ins insLen ctxt src1 + let src2D, src2C, src2B, src2A = + transOprToExpr256 ins insLen ctxt src2 + let struct (t1, t2, t3, t4) = tmpVars4 ir 64 + let struct (t5, t6, t7, t8) = tmpVars4 ir 64 + !)) + !!ir (t5 := src2A .& AST.not src1A) + !!ir (t6 := src2B .& AST.not src1B) + !!ir (t7 := src2C .& AST.not src1C) + !!ir (t8 := src2D .& AST.not src1D) + !!ir (!.ctxt R.CF := (t5 .| t6 .| t7 .| t8) == (AST.num0 64)) + !!ir (!.ctxt R.AF := AST.b0) + !!ir (!.ctxt R.OF := AST.b0) + !!ir (!.ctxt R.PF := AST.b0) + !!ir (!.ctxt R.SF := AST.b0) + !>ir insLen + +let vpunpckhdq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPunpckHigh 16 + +let vpunpckhqdq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPunpckHigh 16 + +let vpunpckldq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPunpckLow 16 + +let vpunpcklqdq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPunpckLow 16 + +let vpxor ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2) = getThreeOprs ins + let oprSize = getOperationSize ins + ! -> + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + !!ir (dstB := src1B <+> src2B) + !!ir (dstA := src1A <+> src2A) + fillZeroHigh128 ctxt dst ir + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let src1D, src1C, src1B, src1A = + transOprToExpr256 ins insLen ctxt src1 + let src2D, src2C, src2B, src2A = + transOprToExpr256 ins insLen ctxt src2 + !!ir (dstD := src1D <+> src2D) + !!ir (dstC := src1C <+> src2C) + !!ir (dstB := src1B <+> src2B) + !!ir (dstA := src1A <+> src2A) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vpxord ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2) = getThreeOprs ins + let oprSize = getOperationSize ins + ! Disasm.getOpmaskRegister) + let masking dst = + match ePrx.Z with + | Zeroing -> AST.num0 32 + | Merging -> dst + let cond idx = + (* no write mask *) + let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 + AST.extract k 1 idx .| noWritemask + let tmpDest = Array.init 2 (fun _ -> !*ir 32) + let evAssign dst s1 s2 src2A dstA idx = + for i in 0 .. 1 do + let s1 = AST.extract s1 32 (i * 32) + let s2 = AST.extract s2 32 (i * 32) + let dst = AST.extract dstA 32 0 + let tSrc = + match src2 with + | OprMem _ when ePrx.AAA (* B *) = 1uy -> + s1 <+> (AST.extract src2A 32 0) + | _ -> s1 <+> s2 + !!ir (tmpDest.[i] := AST.ite (cond (idx + i)) tSrc (masking dst)) + AST.concatArr tmpDest + match oprSize with + | 128 -> + let kl, vl = 4, 128 + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + !!ir (dstA := evAssign dstA src1A src2A src2A dstA 0) + !!ir (dstB := evAssign dstB src1B src2B src2A dstA 2) + fillZeroHigh128 ctxt dst ir + | 256 -> + let kl, vl = 8, 256 + let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let src1D, src1C, src1B, src1A = + transOprToExpr256 ins insLen ctxt src1 + let src2D, src2C, src2B, src2A = + transOprToExpr256 ins insLen ctxt src2 + !!ir (dstA := evAssign dstA src1A src2A src2A dstA 0) + !!ir (dstB := evAssign dstB src1B src2B src2A dstA 2) + !!ir (dstC := evAssign dstC src1C src2B src2A dstA 4) + !!ir (dstD := evAssign dstD src1D src2B src2A dstA 6) + fillZeroHigh256 ctxt dst ir + | 512 -> + let kl, vl = 16, 512 + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ins insLen ctxt dst + let src1H, src1G, src1F, src1E, src1D, src1C, src1B, src1A = + transOprToExpr512 ins insLen ctxt src1 + let src2H, src2G, src2F, src2E, src2D, src2C, src2B, src2A = + transOprToExpr512 ins insLen ctxt src2 + !!ir (dstA := evAssign dstA src1A src2A src2A dstA 0) + !!ir (dstB := evAssign dstB src1B src2B src2A dstA 2) + !!ir (dstC := evAssign dstC src1C src2C src2A dstA 4) + !!ir (dstD := evAssign dstD src1D src2D src2A dstA 6) + !!ir (dstE := evAssign dstE src1E src2E src2A dstA 8) + !!ir (dstF := evAssign dstF src1F src2F src2A dstA 10) + !!ir (dstG := evAssign dstG src1G src2G src2A dstA 12) + !!ir (dstH := evAssign dstH src1H src2H src2A dstA 14) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vzeroupper ins insLen ctxt = + let ir = IRBuilder (32) + ! + !!ir (getPseudoRegVar ctxt R.YMM0 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM0 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM1 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM1 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM2 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM2 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM3 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM3 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM4 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM4 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM5 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM5 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM6 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM6 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM7 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM7 4 := n0) + if is64bit ctxt then + !!ir (getPseudoRegVar ctxt R.YMM8 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM8 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM9 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM9 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM10 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM10 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM11 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM11 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM12 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM12 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM13 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM13 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM14 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM14 4 := n0) + !!ir (getPseudoRegVar ctxt R.YMM15 3 := n0) + !!ir (getPseudoRegVar ctxt R.YMM15 4 := n0) + !>ir insLen + +let vfmadd132sd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src2, src3) = getThreeOprs ins + let _dstB , dstA = transOprToExpr128 ins insLen ctxt dst + let src2 = transOprToExpr64 ins insLen ctxt src2 + let src3 = transOprToExpr64 ins insLen ctxt src3 + let tmp = !*ir 64 + !ir insLen + +let vfmadd213sd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src2, src3) = getThreeOprs ins + let _dstB , dstA = transOprToExpr128 ins insLen ctxt dst + let src2 = transOprToExpr64 ins insLen ctxt src2 + let src3 = transOprToExpr64 ins insLen ctxt src3 + let tmp = !*ir 64 + !ir insLen + +let vfmadd231sd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src2, src3) = getThreeOprs ins + let _dstB , dstA = transOprToExpr128 ins insLen ctxt dst + let src2 = transOprToExpr64 ins insLen ctxt src2 + let src3 = transOprToExpr64 ins insLen ctxt src3 + let tmp = !*ir 64 + !ir insLen diff --git a/src/FrontEnd/Intel/IntelDisasm.fs b/src/FrontEnd/BinLifter/Intel/IntelDisasm.fs similarity index 72% rename from src/FrontEnd/Intel/IntelDisasm.fs rename to src/FrontEnd/BinLifter/Intel/IntelDisasm.fs index 8dbe04f7..ddeaca3f 100644 --- a/src/FrontEnd/Intel/IntelDisasm.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelDisasm.fs @@ -22,11 +22,10 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.Intel.Disasm +module internal B2R2.FrontEnd.BinLifter.Intel.Disasm open B2R2 -open B2R2.BinFile -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter let opCodeToString = function | Opcode.AAA -> "aaa" @@ -40,12 +39,17 @@ let opCodeToString = function | Opcode.ADDSD -> "addsd" | Opcode.ADDSS -> "addss" | Opcode.AND -> "and" + | Opcode.ANDN -> "andn" | Opcode.ANDNPD -> "andnpd" | Opcode.ANDNPS -> "andnps" | Opcode.ANDPD -> "andpd" | Opcode.ANDPS -> "andps" | Opcode.ARPL -> "arpl" + | Opcode.BLENDVPD -> "blendvpd" + | Opcode.BNDCL -> "bndcl" + | Opcode.BNDMK -> "bndmk" | Opcode.BNDMOV -> "bndmov" + | Opcode.BNDSTX -> "bndstx" | Opcode.BOUND -> "bound" | Opcode.BSF -> "bsf" | Opcode.BSR -> "bsr" @@ -388,6 +392,8 @@ let opCodeToString = function | Opcode.PCMPGTW -> "pcmpgtw" | Opcode.PCMPISTRI -> "pcmpistri" | Opcode.PCMPISTRM -> "pcmpistrm" + | Opcode.PEXT -> "pext" + | Opcode.PEXTRD -> "pextrd" | Opcode.PEXTRW -> "pextrw" | Opcode.PHADDD -> "phaddd" | Opcode.PHADDSW -> "phaddsw" @@ -489,6 +495,8 @@ let opCodeToString = function | Opcode.PUSHFQ -> "pushfq" | Opcode.PXOR -> "pxor" | Opcode.RCL -> "rcl" + | Opcode.RCPPS -> "rcpps" + | Opcode.RCPSS -> "rcpss" | Opcode.RCR -> "rcr" | Opcode.RDFSBASE -> "rdfsbase" | Opcode.RDGSBASE -> "rdgsbase" @@ -506,8 +514,12 @@ let opCodeToString = function | Opcode.ROL -> "rol" | Opcode.ROR -> "ror" | Opcode.RORX -> "rorx" + | Opcode.ROUNDPD -> "roundpd" + | Opcode.ROUNDPS -> "roundps" | Opcode.ROUNDSD -> "roundsd" | Opcode.RSM -> "rsm" + | Opcode.RSQRTPS -> "rsqrtps" + | Opcode.RSQRTSS -> "rsqrtss" | Opcode.RSTORSSP -> "rstorssp" | Opcode.SAHF -> "sahf" | Opcode.SAR -> "sar" @@ -589,16 +601,27 @@ let opCodeToString = function | Opcode.VANDNPS -> "vandnps" | Opcode.VANDPD -> "vandpd" | Opcode.VANDPS -> "vandps" + | Opcode.VBLENDVPD -> "vblendvpd" | Opcode.VBROADCASTI128 -> "vbroadcasti128" + | Opcode.VBROADCASTSD -> "vbroadcastsd" | Opcode.VBROADCASTSS -> "vbroadcastss" + | Opcode.VCMPPD -> "vcmppd" + | Opcode.VCMPPS -> "vcmpps" + | Opcode.VCMPSD -> "vcmpsd" + | Opcode.VCMPSS -> "vcmpss" | Opcode.VCOMISD -> "vcomisd" | Opcode.VCOMISS -> "vcomiss" + | Opcode.VCVTDQ2PD -> "vcvtdq2pd" + | Opcode.VCVTDQ2PS -> "vcvtdq2ps" + | Opcode.VCVTPD2PS -> "vcvtpd2ps" + | Opcode.VCVTPS2PD -> "vcvtps2pd" | Opcode.VCVTSD2SI -> "vcvtsd2si" | Opcode.VCVTSD2SS -> "vcvtsd2ss" | Opcode.VCVTSI2SD -> "vcvtsi2sd" | Opcode.VCVTSI2SS -> "vcvtsi2ss" | Opcode.VCVTSS2SD -> "vcvtss2sd" | Opcode.VCVTSS2SI -> "vcvtss2si" + | Opcode.VCVTTPD2DQ -> "vcvttpd2dq" | Opcode.VCVTTSD2SI -> "vcvttsd2si" | Opcode.VCVTTSS2SI -> "vcvttss2si" | Opcode.VDIVPD -> "vdivpd" @@ -607,17 +630,50 @@ let opCodeToString = function | Opcode.VDIVSS -> "vdivss" | Opcode.VERR -> "verr" | Opcode.VERW -> "verw" + | Opcode.VEXTRACTF128 -> "vextractf128" + | Opcode.VEXTRACTF32X8 -> "vextractf32x8" + | Opcode.VEXTRACTF64X2 -> "vextractf64x2" + | Opcode.VEXTRACTF64X4 -> "vextractf64x4" + | Opcode.VEXTRACTI64X4 -> "vextracti64x4" + | Opcode.VFMADD132PD -> "vfmadd132pd" | Opcode.VFMADD132SD -> "vfmadd132sd" | Opcode.VFMADD132SS -> "vfmadd132ss" + | Opcode.VFMADD213PD -> "vfmadd213pd" + | Opcode.VFMADD213PS -> "vfmadd213ps" | Opcode.VFMADD213SD -> "vfmadd213sd" | Opcode.VFMADD213SS -> "vfmadd213ss" + | Opcode.VFMADD231PD -> "vfmadd231pd" | Opcode.VFMADD231SD -> "vfmadd231sd" | Opcode.VFMADD231SS -> "vfmadd231ss" + | Opcode.VFMSUB132SS -> "vfmsub132ss" + | Opcode.VFMSUB213PD -> "vfmsub213pd" + | Opcode.VFMSUB213SD -> "vfmsub213sd" + | Opcode.VFMSUB231PD -> "vfmsub231pd" + | Opcode.VFMSUB231SD -> "vfmsub231sd" + | Opcode.VFNMADD132PD -> "vfnmadd132pd" + | Opcode.VFNMADD213PD -> "vfnmadd213pd" + | Opcode.VFNMADD231PD -> "vfnmadd231pd" + | Opcode.VFNMADD132SD -> "vfnmadd132sd" + | Opcode.VFNMADD213SD -> "vfnmadd213sd" + | Opcode.VFNMADD231SD -> "vfnmadd231sd" + | Opcode.VGATHERQPD -> "vgatherqpd" + | Opcode.VGATHERDPS -> "vgatherdps" + | Opcode.VGETEXPSD -> "vgetexpsd" + | Opcode.VGETMANTSD -> "vgetmantsd" + | Opcode.VINSERTF128 -> "vinsertf128" + | Opcode.VINSERTF64X4 -> "vinsertf64x4" | Opcode.VINSERTI128 -> "vinserti128" + | Opcode.VINSERTI64X4 -> "vinserti64x4" | Opcode.VLDDQU -> "vlddqu" + | Opcode.VMAXPS -> "vmaxps" + | Opcode.VMAXSD -> "vmaxsd" + | Opcode.VMAXSS -> "vmaxss" | Opcode.VMCALL -> "vmcall" | Opcode.VMCLEAR -> "vmclear" | Opcode.VMFUNC -> "vmfunc" + | Opcode.VMINPD -> "vminpd" + | Opcode.VMINPS -> "vminps" + | Opcode.VMINSS -> "vminss" | Opcode.VMLAUNCH -> "vmlaunch" | Opcode.VMOVAPD -> "vmovapd" | Opcode.VMOVAPS -> "vmovaps" @@ -627,6 +683,8 @@ let opCodeToString = function | Opcode.VMOVDQA32 -> "vmovdqa32" | Opcode.VMOVDQA64 -> "vmovdqa64" | Opcode.VMOVDQU -> "vmovdqu" + | Opcode.VMOVDQU8 -> "vmovdqu8" + | Opcode.VMOVDQU16 -> "vmovdqu16" | Opcode.VMOVDQU32 -> "vmovdqu32" | Opcode.VMOVDQU64 -> "vmovdqu64" | Opcode.VMOVHLPS -> "vmovhlps" @@ -679,6 +737,8 @@ let opCodeToString = function | Opcode.VPAVGB -> "vpavgb" | Opcode.VPAVGW -> "vpavgw" | Opcode.VPBROADCASTB -> "vpbroadcastb" + | Opcode.VPBROADCASTD -> "vpbroadcastd" + | Opcode.VPBROADCASTQ -> "vpbroadcastq" | Opcode.VPCMPEQB -> "vpcmpeqb" | Opcode.VPCMPEQD -> "vpcmpeqd" | Opcode.VPCMPEQQ -> "vpcmpeqq" @@ -691,7 +751,12 @@ let opCodeToString = function | Opcode.VPCMPGTW -> "vpcmpgtw" | Opcode.VPCMPISTRI -> "vpcmpistri" | Opcode.VPCMPISTRM -> "vpcmpistrm" + | Opcode.VPERMI2D -> "vpermi2d" + | Opcode.VPERMI2PD -> "vpermi2pd" + | Opcode.VPERMI2W -> "vpermi2w" + | Opcode.VPEXTRD -> "vpextrd" | Opcode.VPEXTRW -> "vpextrw" + | Opcode.VPGATHERDD -> "vpgatherdd" | Opcode.VPHADDD -> "vphaddd" | Opcode.VPHADDSW -> "vphaddsw" | Opcode.VPHADDW -> "vphaddw" @@ -700,7 +765,9 @@ let opCodeToString = function | Opcode.VPHSUBSW -> "vphsubsw" | Opcode.VPHSUBW -> "vphsubw" | Opcode.VPINSRB -> "vpinsrb" + | Opcode.VPINSRD -> "vpinsrd" | Opcode.VPINSRW -> "vpinsrw" + | Opcode.VPINSRQ -> "vpinsrq" | Opcode.VPMADDWD -> "vpmaddwd" | Opcode.VPMAXSB -> "vpmaxsb" | Opcode.VPMAXSD -> "vpmaxsd" @@ -721,6 +788,7 @@ let opCodeToString = function | Opcode.VPMOVSXDQ -> "vpmovsxdq" | Opcode.VPMOVSXWD -> "vpmovsxwd" | Opcode.VPMOVSXWQ -> "vpmovsxwq" + | Opcode.VPMOVWB -> "vpmovwb" | Opcode.VPMOVZXBD -> "vpmovzxbd" | Opcode.VPMOVZXBQ -> "vpmovzxbq" | Opcode.VPMOVZXBW -> "vpmovzxbw" @@ -761,6 +829,7 @@ let opCodeToString = function | Opcode.VPSUBUSB -> "vpsubusb" | Opcode.VPSUBUSW -> "vpsubusw" | Opcode.VPSUBW -> "vpsubw" + | Opcode.VPTERNLOGD -> "vpternlogd" | Opcode.VPTEST -> "vptest" | Opcode.VPUNPCKHBW -> "vpunpckhbw" | Opcode.VPUNPCKHDQ -> "vpunpckhdq" @@ -771,8 +840,28 @@ let opCodeToString = function | Opcode.VPUNPCKLQDQ -> "vpunpcklqdq" | Opcode.VPUNPCKLWD -> "vpunpcklwd" | Opcode.VPXOR -> "vpxor" + | Opcode.VPXORD -> "vpxord" + | Opcode.VPXORQ -> "vpxorq" + | Opcode.VRCP14SD -> "vrcp14sd" + | Opcode.VRCP28SD -> "vrcp28sd" + | Opcode.VRCPPS -> "vrcpps" + | Opcode.VRCPSS -> "vrcpss" + | Opcode.VREDUCESD -> "vreducesd" + | Opcode.VRNDSCALESD -> "vrndscalesd" + | Opcode.VROUNDPD -> "vroundpd" + | Opcode.VROUNDPS -> "vroundps" + | Opcode.VROUNDSD -> "vroundsd" + | Opcode.VRSQRT28SD -> "vrsqrt28sd" + | Opcode.VRSQRTPS -> "vrsqrtps" + | Opcode.VRSQRTSS -> "vrsqrtss" + | Opcode.VSHUFI64X2 -> "vshufi64x2" + | Opcode.VSHUFI32X4 -> "vshufi32x4" | Opcode.VSHUFPD -> "vshufpd" | Opcode.VSHUFPS -> "vshufps" + | Opcode.VSQRTPD -> "vsqrtpd" + | Opcode.VSQRTPS -> "vsqrtps" + | Opcode.VSQRTSD -> "vsqrtsd" + | Opcode.VSQRTSS -> "vsqrtss" | Opcode.VSUBPD -> "vsubpd" | Opcode.VSUBPS -> "vsubps" | Opcode.VSUBSD -> "vsubsd" @@ -819,106 +908,107 @@ let opCodeToString = function | Opcode.XTEST -> "xtest" | _ -> raise InvalidOpcodeException -let inline private iToHexStr (i: int64) builder acc = - builder AsmWordKind.Value ("0x" + i.ToString("X")) acc +let inline private iToHexStr (i: int64) (builder: DisasmBuilder<_>) = + builder.Accumulate AsmWordKind.Value (String.i64ToHex i) -let inline private uToHexStr (i: uint64) builder acc = - builder AsmWordKind.Value ("0x" + i.ToString("X")) acc +let inline private uToHexStr (i: uint64) (builder: DisasmBuilder<_>) = + builder.Accumulate AsmWordKind.Value (String.u64ToHex i) -let inline private ptrDirectiveString isFar = function - | 1 -> "byte ptr" - | 2 -> "word ptr" - | 4 -> if isFar then "word far ptr" else "dword ptr" - | 6 -> "dword far ptr" - | 8 -> "qword ptr" - | 10 -> if isFar then "qword far ptr" else "tword ptr" - | 16 -> "xmmword ptr" - | 32 -> "ymmword ptr" - | 64 -> "zmmword ptr" - | 28 | 108 -> "" (* x87 FPU state *) - | _ -> failwithf "Invalid ptr attribute" +let private ptrDirectiveString isFar = function + | 8 -> "byte ptr" + | 16 -> "word ptr" + | 32 -> if isFar then "word far ptr" else "dword ptr" + | 48 -> "dword far ptr" + | 64 -> "qword ptr" + | 80 -> if isFar then "qword far ptr" else "tword ptr" + | 128 -> "xmmword ptr" + | 256 -> "ymmword ptr" + | 512 -> "zmmword ptr" + | 224 | 864 -> "" (* x87 FPU state *) + | _ -> Utils.impossible () -let inline dispToString showSign wordSz (disp: Disp) builder acc = - let mask = WordSize.toRegType wordSz |> RegType.getMask |> uint64 +let dispToString showSign (disp: Disp) (builder: DisasmBuilder<_>) = + let mask = WordSize.toRegType builder.WordSize |> RegType.getMask |> uint64 if showSign && disp < 0L then - builder AsmWordKind.String "-" acc |> iToHexStr (- disp) builder + builder.Accumulate AsmWordKind.String "-" + iToHexStr (- disp) builder elif showSign then - builder AsmWordKind.String "+" acc |> iToHexStr disp builder + builder.Accumulate AsmWordKind.String "+" + iToHexStr disp builder else - uToHexStr (uint64 disp &&& mask) builder acc + uToHexStr (uint64 disp &&& mask) builder -let inline private memDispToStr showSign disp wordSz builder acc = +let inline private memDispToStr showSign disp builder = match disp with - | None -> acc - | Some d -> dispToString showSign wordSz d builder acc + | None -> () + | Some d -> dispToString showSign d builder -let inline scaleToString (scale: Scale) builder acc = - if scale = Scale.X1 then acc +let inline scaleToString (scale: Scale) (builder: DisasmBuilder<_>) = + if scale = Scale.X1 then () else - builder AsmWordKind.String "*" acc - |> builder AsmWordKind.Value ((int scale).ToString()) + builder.Accumulate AsmWordKind.String "*" + builder.Accumulate AsmWordKind.Value ((int scale).ToString()) -let inline private memScaleDispToStr emptyBase si d wordSz builder acc = +let private memScaleDispToStr emptyBase si d builder = match si with - | None -> memDispToStr (not emptyBase) d wordSz builder acc + | None -> memDispToStr (not emptyBase) d builder | Some (i, scale) -> - let acc = if emptyBase then acc else builder AsmWordKind.String "+" acc - builder AsmWordKind.Variable (Register.toString i) acc - |> scaleToString scale builder - |> memDispToStr true d wordSz builder + if emptyBase then () else builder.Accumulate AsmWordKind.String "+" + builder.Accumulate AsmWordKind.Variable (Register.toString i) + scaleToString scale builder + memDispToStr true d builder -let private memAddrToStr b si disp wordSz builder acc = +let private memAddrToStr b si disp builder = match b with - | None -> memScaleDispToStr true si disp wordSz builder acc + | None -> memScaleDispToStr true si disp builder | Some b -> - builder AsmWordKind.Variable (Register.toString b) acc - |> memScaleDispToStr false si disp wordSz builder + builder.Accumulate AsmWordKind.Variable (Register.toString b) + memScaleDispToStr false si disp builder let inline isFar (ins: InsInfo) = match ins.Opcode with | Opcode.JMPFar | Opcode.CALLFar -> true | _ -> false -let mToString wordSz (ins: InsInfo) b si d oprSz builder acc = - let ptrDirective = RegType.toByteWidth oprSz |> ptrDirectiveString (isFar ins) +let mToString (ins: InsInfo) (builder: DisasmBuilder<_>) b si d oprSz = + let ptrDirective = ptrDirectiveString (isFar ins) oprSz match Helper.getSegment ins.Prefixes with | None -> - builder AsmWordKind.String ptrDirective acc - |> builder AsmWordKind.String (" [") - |> memAddrToStr b si d wordSz builder - |> builder AsmWordKind.String "]" + builder.Accumulate AsmWordKind.String ptrDirective + builder.Accumulate AsmWordKind.String (" [") + memAddrToStr b si d builder + builder.Accumulate AsmWordKind.String "]" | Some seg -> - builder AsmWordKind.String ptrDirective acc - |> builder AsmWordKind.String (" [") - |> builder AsmWordKind.Variable (Register.toString seg) - |> builder AsmWordKind.String ":" - |> memAddrToStr b si d wordSz builder - |> builder AsmWordKind.String "]" + builder.Accumulate AsmWordKind.String ptrDirective + builder.Accumulate AsmWordKind.String (" [") + builder.Accumulate AsmWordKind.Variable (Register.toString seg) + builder.Accumulate AsmWordKind.String ":" + memAddrToStr b si d builder + builder.Accumulate AsmWordKind.String "]" -let commentWithSymbol (fi: FileInfo option) targetAddr builder acc = - match fi with - | Some fi -> - match fi.TryFindFunctionSymbolName (targetAddr) with - | false, _ -> - builder AsmWordKind.String " ; " acc |> uToHexStr targetAddr builder - | true, "" -> acc - | true, name -> - builder AsmWordKind.String " ; <" acc - |> builder AsmWordKind.Value name - |> builder AsmWordKind.String ">" - | None -> - builder AsmWordKind.String " ; " acc |> uToHexStr targetAddr builder +let commentWithSymbol (helper: DisasmHelper) targetAddr builder = + if (builder: DisasmBuilder<_>).ResolveSymbol then + match helper.FindFunctionSymbol (targetAddr) with + | Error _ -> + (builder: DisasmBuilder<_>).Accumulate AsmWordKind.String " ; " + uToHexStr targetAddr builder + | Ok "" -> () + | Ok name -> + builder.Accumulate AsmWordKind.String " ; <" + builder.Accumulate AsmWordKind.Value name + builder.Accumulate AsmWordKind.String ">" + else () -let inline relToString pc offset fi builder acc = - (if offset < 0L then builder AsmWordKind.String "-" acc - else builder AsmWordKind.String "+" acc) - |> iToHexStr (abs offset) builder - |> commentWithSymbol fi (pc + uint64 offset) builder +let inline relToString offset hlp (builder: DisasmBuilder<_>) = + if offset < 0L then builder.Accumulate AsmWordKind.String "-" + else builder.Accumulate AsmWordKind.String "+" + iToHexStr (abs offset) builder + commentWithSymbol hlp (builder.Address + uint64 offset) builder -let inline absToString selector (offset: Addr) builder acc = - uToHexStr (uint64 selector) builder acc - |> builder AsmWordKind.String ":" - |> uToHexStr offset builder +let inline absToString selector (offset: Addr) builder = + uToHexStr (uint64 selector) builder + builder.Accumulate AsmWordKind.String ":" + uToHexStr offset builder let getOpmaskRegister = function | 0x0uy -> Register.K0 @@ -932,24 +1022,25 @@ let getOpmaskRegister = function | _ -> raise InvalidRegisterException /// Zeroing/Merging (EVEX.z) -let maskZtoString ev builder acc = - if ev.Z = Zeroing then acc - else builder AsmWordKind.String "{z}" acc +let maskZtoString ev (builder: DisasmBuilder<_>) = + if ev.Z = Zeroing then () + else builder.Accumulate AsmWordKind.String "{z}" /// Opmask register -let maskRegToString ePrx builder acc = - if ePrx.AAA = 0uy then acc +let maskRegToString ePrx (builder: DisasmBuilder<_>) = + if ePrx.AAA = 0uy then () else - builder AsmWordKind.String " {" acc - |> builder AsmWordKind.Variable + builder.Accumulate AsmWordKind.String " {" + builder.Accumulate AsmWordKind.Variable (getOpmaskRegister ePrx.AAA |> Register.toString) - |> builder AsmWordKind.String "}" + builder.Accumulate AsmWordKind.String "}" -let buildMask (ins: InsInfo) builder acc = +let buildMask (ins: InsInfo) builder = match ins.VEXInfo with | Some { EVEXPrx = Some ePrx }-> - maskRegToString ePrx builder acc |> maskZtoString ePrx builder - | _ -> acc + maskRegToString ePrx builder + maskZtoString ePrx builder + | _ -> () let inline private getMask sz = match sz with @@ -958,88 +1049,88 @@ let inline private getMask sz = | 32 -> 0xFFFFFFFFL | _ -> 0xFFFFFFFFFFFFFFFFL -let oprToString wordSz ins insAddr fi opr isFstOpr builder acc = +let oprToString ins hlp opr isFst (builder: DisasmBuilder<_>) = match opr with | OprReg reg -> - let acc = builder AsmWordKind.Variable (Register.toString reg) acc - if isFstOpr then buildMask ins builder acc else acc + builder.Accumulate AsmWordKind.Variable (Register.toString reg) + if isFst then buildMask ins builder else () | OprMem (b, si, disp, oprSz) -> - let acc = mToString wordSz ins b si disp oprSz builder acc - if isFstOpr then buildMask ins builder acc else acc - | OprImm imm -> - iToHexStr (imm &&& getMask ins.InsSize.OperationSize) builder acc - | OprDirAddr (Absolute (sel, offset, _)) -> absToString sel offset builder acc - | OprDirAddr (Relative (offset)) -> relToString insAddr offset fi builder acc + mToString ins builder b si disp oprSz + if isFst then buildMask ins builder else () + | OprImm (imm, _) -> iToHexStr (imm &&& getMask ins.MainOperationSize) builder + | OprDirAddr (Absolute (sel, offset, _)) -> absToString sel offset builder + | OprDirAddr (Relative (offset)) -> relToString offset hlp builder | Label _ -> Utils.impossible () -let inline buildPref (prefs: Prefix) builder acc = - if (prefs &&& Prefix.PrxLOCK) <> Prefix.PrxNone then - builder AsmWordKind.String "lock " acc +let inline buildPref (prefs: Prefix) (builder: DisasmBuilder<_>) = + if prefs = Prefix.PrxNone then () + elif (prefs &&& Prefix.PrxLOCK) <> Prefix.PrxNone then + builder.Accumulate AsmWordKind.String "lock " elif (prefs &&& Prefix.PrxREPNZ) <> Prefix.PrxNone then - builder AsmWordKind.String "repnz " acc + builder.Accumulate AsmWordKind.String "repnz " elif (prefs &&& Prefix.PrxREPZ) <> Prefix.PrxNone then - builder AsmWordKind.String "repz " acc + builder.Accumulate AsmWordKind.String "repz " elif (prefs &&& Prefix.PrxBND) <> Prefix.PrxNone then - builder AsmWordKind.String "bnd " acc - else acc + builder.Accumulate AsmWordKind.String "bnd " + else () -let inline buildOpcode opcode builder acc = - builder AsmWordKind.Mnemonic (opCodeToString opcode) acc +let inline buildOpcode opcode (builder: DisasmBuilder<_>) = + builder.Accumulate AsmWordKind.Mnemonic (opCodeToString opcode) -let recomputeRIPRel pc disp (ins: InsInfo) (insLen: uint32) builder acc = - let oprSize = RegType.toByteWidth ins.InsSize.MemSize.EffOprSize +let recomputeRIPRel disp oprSize builder = let dir = ptrDirectiveString false oprSize - builder AsmWordKind.String dir acc - |> builder AsmWordKind.String " [" - |> uToHexStr (pc + uint64 disp + uint64 insLen) builder - |> builder AsmWordKind.String "]" + (builder: DisasmBuilder<_>).Accumulate AsmWordKind.String dir + builder.Accumulate AsmWordKind.String " [" + uToHexStr (builder.Address + uint64 disp + uint64 builder.InsLength) builder + builder.Accumulate AsmWordKind.String "]" -let buildOprs ins insLen pc fi wordSz builder acc = +let buildOprs (ins: InsInfo) hlp (builder: DisasmBuilder<_>) = match ins.Operands with - | NoOperand -> acc + | NoOperand -> () | OneOperand (OprMem (Some Register.RIP, None, Some off, 64)) -> - builder AsmWordKind.String (" ") acc - |> mToString wordSz ins (Some Register.RIP) None (Some off) 64 builder - |> commentWithSymbol fi (pc + uint64 insLen + uint64 off) builder + builder.Accumulate AsmWordKind.String (" ") + mToString ins builder (Some Register.RIP) None (Some off) 64 + commentWithSymbol hlp + (builder.Address + uint64 builder.InsLength + uint64 off) builder | OneOperand opr -> - builder AsmWordKind.String " " acc - |> oprToString wordSz ins pc fi opr true builder - | TwoOperands (OprMem (Some R.RIP, None, Some disp, _), opr) -> - builder AsmWordKind.String " " acc - |> recomputeRIPRel pc disp ins insLen builder - |> builder AsmWordKind.String ", " - |> oprToString wordSz ins pc fi opr false builder - | TwoOperands (opr, OprMem (Some R.RIP, None, Some disp, _)) -> - builder AsmWordKind.String " " acc - |> oprToString wordSz ins pc fi opr true builder - |> builder AsmWordKind.String ", " - |> recomputeRIPRel pc disp ins insLen builder + builder.Accumulate AsmWordKind.String " " + oprToString ins hlp opr true builder + | TwoOperands (OprMem (Some R.RIP, None, Some disp, sz), opr) -> + builder.Accumulate AsmWordKind.String " " + recomputeRIPRel disp sz builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins hlp opr false builder + | TwoOperands (opr, OprMem (Some R.RIP, None, Some disp, sz)) -> + builder.Accumulate AsmWordKind.String " " + oprToString ins hlp opr true builder + builder.Accumulate AsmWordKind.String ", " + recomputeRIPRel disp sz builder | TwoOperands (opr1, opr2) -> - builder AsmWordKind.String " " acc - |> oprToString wordSz ins pc fi opr1 true builder - |> builder AsmWordKind.String ", " - |> oprToString wordSz ins pc fi opr2 false builder + builder.Accumulate AsmWordKind.String " " + oprToString ins hlp opr1 true builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins hlp opr2 false builder | ThreeOperands (opr1, opr2, opr3) -> - builder AsmWordKind.String " " acc - |> oprToString wordSz ins pc fi opr1 true builder - |> builder AsmWordKind.String ", " - |> oprToString wordSz ins pc fi opr2 false builder - |> builder AsmWordKind.String ", " - |> oprToString wordSz ins pc fi opr3 false builder + builder.Accumulate AsmWordKind.String " " + oprToString ins hlp opr1 true builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins hlp opr2 false builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins hlp opr3 false builder | FourOperands (opr1, opr2, opr3, opr4) -> - builder AsmWordKind.String " " acc - |> oprToString wordSz ins pc fi opr1 true builder - |> builder AsmWordKind.String ", " - |> oprToString wordSz ins pc fi opr2 false builder - |> builder AsmWordKind.String ", " - |> oprToString wordSz ins pc fi opr3 false builder - |> builder AsmWordKind.String ", " - |> oprToString wordSz ins pc fi opr4 false builder + builder.Accumulate AsmWordKind.String " " + oprToString ins hlp opr1 true builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins hlp opr2 false builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins hlp opr3 false builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins hlp opr4 false builder -let disasm showAddr wordSize fi ins pc insLen builder acc = - DisasmBuilder.addr pc wordSize showAddr builder acc - |> buildPref ins.Prefixes builder - |> buildOpcode ins.Opcode builder - |> buildOprs ins insLen pc fi wordSize builder +let disasm hlp ins (builder: DisasmBuilder<_>) = + if builder.ShowAddr then builder.AccumulateAddr () else () + buildPref (ins: InsInfo).Prefixes builder + buildOpcode ins.Opcode builder + buildOprs ins hlp builder // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Intel/IntelGeneralLifter.fs b/src/FrontEnd/BinLifter/Intel/IntelGeneralLifter.fs new file mode 100644 index 00000000..096512e7 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelGeneralLifter.fs @@ -0,0 +1,1989 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.Intel.GeneralLifter + +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.FrontEnd.BinLifter.Intel.RegGroup +open B2R2.FrontEnd.BinLifter.Intel.Helper +open B2R2.FrontEnd.BinLifter.Intel.LiftingUtils + +open type BinOpType + +#if !EMULATION +let private undefCF = AST.undef 1 "CF is undefined." + +let private undefOF = AST.undef 1 "OF is undefined." + +let private undefAF = AST.undef 1 "AF is undefined." + +let private undefSF = AST.undef 1 "SF is undefined." + +let private undefZF = AST.undef 1 "ZF is undefined." + +let private undefPF = AST.undef 1 "PF is undefined." +#endif + +let private buildAF ctxt e1 e2 r size = + let t1 = r <+> e1 + let t2 = t1 <+> e2 + let t3 = (AST.num1 size) << (numU32 4ul size) + let t4 = t2 .& t3 + !.ctxt R.AF := t4 == t3 + +let private buildPF ctxt r size cond ir = + let struct (t1, t2) = tmpVars2 ir size + let s2 = r <+> (r >> (AST.zext size (numU32 4ul 8))) + let s4 = s2 <+> (t1 >> (AST.zext size (numU32 2ul 8))) + let s5 = s4 <+> (t2 >> (AST.zext size (AST.num1 8))) + let pf = !.ctxt R.PF + let computedPF = AST.unop UnOpType.NOT (AST.xtlo 1 s5) + !!ir (t1 := s2) + !!ir (t2 := s4) + !!ir (match cond with + | None -> pf := computedPF + | Some cond -> pf := AST.ite cond pf computedPF) + +let private enumSZPFlags ctxt r size ir = + !!ir (!.ctxt R.SF := AST.xthi 1 r) + !!ir (!.ctxt R.ZF := r == (AST.num0 size)) + !?ir (buildPF ctxt r size None) + +let private enumASZPFlags ctxt e1 e2 r size ir = + !!ir (buildAF ctxt e1 e2 r size) + !?ir (enumSZPFlags ctxt r size) + +let private enumEFLAGS ctxt e1 e2 e3 size cf ofl ir = + !!ir (!.ctxt R.CF := cf) + !!ir (!.ctxt R.OF := ofl) + !!ir (buildAF ctxt e1 e2 e3 size) + !!ir (!.ctxt R.SF := AST.xthi 1 e3) + !!ir (!.ctxt R.ZF := e3 == (AST.num0 size)) + !?ir (buildPF ctxt e3 size None) + +/// CF on add. +let private cfOnAdd e1 r = AST.lt r e1 + +/// CF on sub. +let private cfOnSub e1 e2 = AST.lt e1 e2 + +/// OF on add. +let private ofOnAdd e1 e2 r = + let e1High = AST.xthi 1 e1 + let e2High = AST.xthi 1 e2 + let rHigh = AST.xthi 1 r + (e1High == e2High) .& (e1High <+> rHigh) + +/// OF on sub. +let private ofOnSub e1 e2 r = + AST.xthi 1 ((e1 <+> e2) .& (e1 <+> r)) + +let private getInstrPtr ctxt = + !.ctxt (if is64bit ctxt then R.RIP else R.EIP) + +let private getStackPtr ctxt = + !.ctxt (if is64bit ctxt then R.RSP else R.ESP) + +let private getBasePtr ctxt = + !.ctxt (if is64bit ctxt then R.RBP else R.EBP) + +let private getRegOfSize ctxt oprSize regGrp = + regGrp oprSize |> !.ctxt + +let private getDividend ctxt = function + | 8 -> !.ctxt R.AX + | 16 -> AST.concat (!.ctxt R.DX) (!.ctxt R.AX) + | 32 -> AST.concat (!.ctxt R.EDX) (!.ctxt R.EAX) + | 64 -> AST.concat (!.ctxt R.RDX) (!.ctxt R.RAX) + | _ -> raise InvalidOperandSizeException + +let inline private getStackWidth wordSize oprSize = + numI32 (RegType.toByteWidth oprSize) wordSize + +let private auxPush oprSize ctxt expr ir = + let t = !*ir oprSize + let sp = getStackPtr ctxt + !!ir (t := expr) + !!ir (sp := sp .- (getStackWidth ctxt.WordBitSize oprSize)) + !!ir (AST.loadLE oprSize sp := t) + +let private computePopSize oprSize = function + | Var (_, id, _, _) when isSegReg (Register.ofRegID id) -> 16 + | _ -> oprSize + +let private auxPop oprSize ctxt dst ir = + let sp = getStackPtr ctxt + !!ir (dst := AST.loadLE (computePopSize oprSize dst.E) sp) + !!ir (sp := sp .+ (getStackWidth ctxt.WordBitSize oprSize)) + +let private maskOffset offset oprSize = + let offset = AST.zext oprSize offset + match oprSize with + | 16 -> offset .& numU32 0xFu 16 + | 32 -> offset .& numU32 0x1Fu 32 + | 64 -> offset .& numU32 0x3Fu 64 + | _ -> raise InvalidOperandSizeException + +let rec private isVar = function + | Var _ | TempVar _ -> true + | Extract (e, _, _, _) -> isVar e.E + | _ -> false + +let private calculateOffset offset oprSize = + let offset = AST.zext oprSize offset + match oprSize with + | 16 -> numU32 2u 16 .* (offset ./ numU32 16u 16), + offset .& numU32 15u 16 + | 32 -> numU32 4u 32 .* (offset ./ numU32 32u 32), + offset .& numU32 31u 32 + | 64 -> numU32 4u 64 .* (offset ./ numU32 32u 64), + offset .& numU32 31u 64 + | _ -> raise InvalidOperandSizeException + +let private strRepeat ins insLen ctxt body cond (ir: IRBuilder) = + let lblExit = ir.NewSymbol "Exit" + let lblCont = ir.NewSymbol "Continue" + let lblNext = ir.NewSymbol "Next" + let n0 = AST.num0 (ctxt: TranslationContext).WordBitSize + let cx = !.ctxt (if is64bit ctxt then R.RCX else R.ECX) + let pc = getInstrPtr ctxt + let ninstAddr = pc .+ numInsLen insLen ctxt + !!ir (AST.cjmp (cx == n0) (AST.name lblExit) (AST.name lblCont)) + !!ir (AST.lmark lblCont) + !?ir (body ins ctxt) + !!ir (cx := cx .- AST.num1 ctxt.WordBitSize) + match cond with + | None -> !!ir (AST.interjmp pc InterJmpKind.Base) + | Some cond -> + !!ir (AST.cjmp (cx == n0) (AST.name lblExit) (AST.name lblNext)) + !!ir (AST.lmark lblNext) + !!ir (AST.intercjmp cond ninstAddr pc) + !!ir (AST.lmark lblExit) + (* We consider each individual loop from a REP-prefixed instruction as an + independent basic block, because it is more intuitive and matches with + the definition of basic block from text books. *) + !!ir (AST.interjmp ninstAddr InterJmpKind.Base) + +let aaa insLen ctxt = +#if DEBUG + assert32 ctxt +#endif + let ir = IRBuilder (16) + let al = !.ctxt R.AL + let af = !.ctxt R.AF + let ax = !.ctxt R.AX + let cf = !.ctxt R.CF + let alAnd0f = al .& numI32 0x0f 8 + let cond1 = AST.gt alAnd0f (numI32 9 8) + let cond2 = af == AST.b1 + let cond = !*ir 1 + !) ax) + !!ir (af := AST.ite cond AST.b1 AST.b0) + !!ir (cf := AST.ite cond AST.b1 AST.b0) + !!ir (al := alAnd0f) +#if !EMULATION + !!ir (!.ctxt R.OF := undefOF) + !!ir (!.ctxt R.SF := undefSF) + !!ir (!.ctxt R.ZF := undefZF) + !!ir (!.ctxt R.PF := undefPF) +#endif + !>ir insLen + +let aad ins insLen ctxt = +#if DEBUG + assert32 ctxt +#endif + let imm8 = transOneOpr ins insLen ctxt |> AST.xtlo 8 + let al = !.ctxt R.AL + let ah = !.ctxt R.AH + let ir = IRBuilder (8) + !)) + !!ir (ah := AST.num0 8) + !?ir (enumSZPFlags ctxt al 8) +#if !EMULATION + !!ir (!.ctxt R.OF := undefOF) + !!ir (!.ctxt R.AF := undefAF) + !!ir (!.ctxt R.CF := undefCF) +#endif + !>ir insLen + +let aam ins insLen ctxt = +#if DEBUG + assert32 ctxt +#endif + let imm8 = transOneOpr ins insLen ctxt |> AST.xtlo 8 + let al = !.ctxt R.AL + let ah = !.ctxt R.AH + let ir = IRBuilder (8) + !) +#if !EMULATION + !!ir (!.ctxt R.OF := undefOF) + !!ir (!.ctxt R.AF := undefAF) + !!ir (!.ctxt R.CF := undefCF) +#endif + !>ir insLen + +let aas insLen ctxt = +#if DEBUG + assert32 ctxt +#endif + let ax = !.ctxt R.AX + let al = !.ctxt R.AL + let af = !.ctxt R.AF + let cf = !.ctxt R.CF + let ah = !.ctxt R.AH + let alAnd0f = al .& numI32 0x0f 8 + let cond1 = AST.gt alAnd0f (numI32 9 8) + let cond2 = af == AST.b1 + let ir = IRBuilder (16) + let cond = !*ir 1 + !) ax) + !!ir (ah := AST.ite cond (ah .- AST.num1 8) ah) + !!ir (af := AST.ite cond AST.b1 AST.b0) + !!ir (cf := AST.ite cond AST.b1 AST.b0) + !!ir (al := alAnd0f) + !>ir insLen + +let adc ins insLen ctxt = + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let cf = !.ctxt R.CF + let ir = IRBuilder (16) + let struct (t1, t2, t3, t4) = tmpVars4 ir oprSize + !ir insLen + +let add ins insLen ctxt = + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let ir = IRBuilder (16) + let struct (t1, t2, t3) = tmpVars3 ir oprSize + !ir insLen + +let ``and`` ins insLen ctxt = + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let ir = IRBuilder (16) + let t = !*ir oprSize + !ir insLen + +let andn ins insLen ctxt = + let struct (dst, src1, src2) = transThreeOprs ins insLen ctxt + let oprSize = getOperationSize ins + let ir = IRBuilder (16) + let t = !*ir oprSize + ! (int oprSize - 1)) + !!ir (!.ctxt R.ZF := AST.eq dst (AST.num0 oprSize)) + !>ir insLen + +let arpl ins insLen ctxt = +#if DEBUG + assert32 ctxt +#endif + let ir = IRBuilder (8) + let struct (dst, src) = transTwoOprs ins insLen ctxt + let struct (t1, t2) = tmpVars2 ir 16 + let mask = numI32 0xfffc 16 + let zF = !.ctxt R.ZF + !) + !!ir (t2 := src .& numI32 0x3 16) + !!ir (dst := AST.ite (AST.lt t1 t2) ((dst .& mask) .| t2) dst) + !!ir (zF := AST.lt t1 t2) + !>ir insLen + +let private bndmov64 ins insLen ctxt = + let struct (dst, src) = getTwoOprs ins + let dst1, dst2 = transOprToExpr128 ins insLen ctxt dst + let src1, src2 = transOprToExpr128 ins insLen ctxt src + let ir = IRBuilder (4) + !ir insLen + +let private bndmov32Aux ins insLen ctxt ir = + let struct (dst, src) = getTwoOprs ins + match dst, src with + | OprReg _, OprMem _ -> + let dst1, dst2 = transOprToExpr128 ins insLen ctxt dst + let src = transOprToExpr ins insLen ctxt src + !!ir (dst1 := AST.xthi 32 src |> AST.zext 64) + !!ir (dst2 := AST.xtlo 32 src |> AST.zext 64) + | OprMem _, OprReg _ -> + let src1, src2 = transOprToExpr128 ins insLen ctxt src + let dst = transOprToExpr ins insLen ctxt dst + !!ir (AST.xthi 32 dst := AST.xtlo 32 src1) + !!ir (AST.xtlo 32 dst := AST.xtlo 32 src2) + | _ -> raise InvalidOperandException + +let bndmov32 ins insLen ctxt = + let ir = IRBuilder (4) + !ir insLen + +let bndmov ins insLen ctxt = + if is64bit ctxt then bndmov64 ins insLen ctxt + else bndmov32 ins insLen ctxt + +let bsf ins insLen ctxt = + let ir = IRBuilder (26) + let lblL0 = ir.NewSymbol "L0" + let lblL1 = ir.NewSymbol "L1" + let lblEnd = ir.NewSymbol "End" + let lblLoopCond = ir.NewSymbol "LoopCond" + let lblLE = ir.NewSymbol "LoopEnd" + let lblLoop = ir.NewSymbol "Loop" + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let cond = src == AST.num0 oprSize + let zf = !.ctxt R.ZF + let t = !*ir oprSize + ! (src >> t)) == AST.b0) + (AST.name lblLoop) (AST.name lblLE)) + !!ir (AST.lmark lblLoop) + !!ir (t := t .+ AST.num1 oprSize) + !!ir (AST.jmp (AST.name lblLoopCond)) + !!ir (AST.lmark lblLE) + !!ir (dstAssign oprSize dst t) + !!ir (AST.lmark lblEnd) +#if !EMULATION + !!ir (!.ctxt R.CF := undefCF) + !!ir (!.ctxt R.OF := undefOF) + !!ir (!.ctxt R.AF := undefAF) + !!ir (!.ctxt R.SF := undefSF) + !!ir (!.ctxt R.PF := undefPF) +#endif + !>ir insLen + +let bsr ins insLen ctxt = + let ir = IRBuilder (26) + let lblL0 = ir.NewSymbol "L0" + let lblL1 = ir.NewSymbol "L1" + let lblEnd = ir.NewSymbol "End" + let lblLoopCond = ir.NewSymbol "LoopCond" + let lblLE = ir.NewSymbol "LoopEnd" + let lblLoop = ir.NewSymbol "Loop" + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let cond = src == AST.num0 oprSize + let zf = !.ctxt R.ZF + let t = !*ir oprSize + ! (src >> t)) == AST.b0) + (AST.name lblLoop) (AST.name lblLE)) + !!ir (AST.lmark lblLoop) + !!ir (t := t .- AST.num1 oprSize) + !!ir (AST.jmp (AST.name lblLoopCond)) + !!ir (AST.lmark lblLE) + !!ir (dst := t) + !!ir (AST.lmark lblEnd) +#if !EMULATION + !!ir (!.ctxt R.CF := undefCF) + !!ir (!.ctxt R.OF := undefOF) + !!ir (!.ctxt R.AF := undefAF) + !!ir (!.ctxt R.SF := undefSF) + !!ir (!.ctxt R.PF := undefPF) +#endif + !>ir insLen + +let bswap ins insLen ctxt = + let dst = transOneOpr ins insLen ctxt + let oprSize = getOperationSize ins + let cnt = RegType.toByteWidth oprSize |> int + let ir = IRBuilder (2 * cnt) + let t = !*ir oprSize + let tmps = Array.init cnt (fun _ -> !*ir 8) + ! (i * 8)) + done + !!ir (dstAssign oprSize dst (AST.concatArr (Array.rev tmps))) + !>ir insLen + +let private bit ins bitBase bitOffset oprSize = + match bitBase.E with + | Load (e, t, expr, _) -> + let effAddrSz = getEffAddrSz ins + let addrOffset, bitOffset = calculateOffset bitOffset oprSize + let addrOffset = AST.zext effAddrSz addrOffset + AST.xtlo 1 ((AST.load e t (expr .+ addrOffset)) >> bitOffset) + | _ -> if isVar bitBase.E + then AST.xtlo 1 (bitBase >> maskOffset bitOffset oprSize) + else raise InvalidExprException + +let bt ins insLen ctxt = + let struct (bitBase, bitOffset) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let ir = IRBuilder (8) + !ir insLen + +let private setBit ins bitBase bitOffset oprSize setValue = + match bitBase.E with + | Load (e, t, expr, _) -> + let effAddrSz = getEffAddrSz ins + let addrOffset, bitOffset = calculateOffset bitOffset oprSize + let addrOffset = AST.zext effAddrSz addrOffset + let mask = setValue << bitOffset + let loadMem = AST.load e t (expr .+ addrOffset) + loadMem := (loadMem .& (getMask oprSize .- mask)) .| mask + | _ -> if isVar bitBase.E + then let mask = setValue << maskOffset bitOffset oprSize + bitBase := (bitBase .& (getMask oprSize .- mask)) .| mask + else raise InvalidExprException + +let bitTest ins insLen ctxt setValue = + let struct (bitBase, bitOffset) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let setValue = AST.zext oprSize setValue + let ir = IRBuilder (8) + !ir insLen + +let btc ins insLen ctxt = + bitTest ins insLen ctxt (!.ctxt R.CF |> AST.not) + +let btr ins insLen ctxt = + bitTest ins insLen ctxt AST.b0 + +let bts ins insLen ctxt = + bitTest ins insLen ctxt AST.b1 + +let call ins insLen ctxt = + let pc = getInstrPtr ctxt + let oprSize = getOperationSize ins + let struct (target, ispcrel) = transJumpTargetOpr ins pc insLen ctxt + let ir = IRBuilder (8) + !ir insLen + +let convBWQ ins insLen ctxt = + let opr = !.ctxt (if is64bit ctxt then R.RAX else R.EAX) + let ir = IRBuilder (8) + ! -> AST.xtlo 16 opr := AST.sext 16 (AST.xtlo 8 opr) + | 32 -> AST.xtlo 32 opr := AST.sext 32 (AST.xtlo 16 opr) + | 64 -> opr := AST.sext 64 (AST.xtlo 32 opr) + | _ -> raise InvalidOperandSizeException) + !>ir insLen + +let clearFlag insLen ctxt flagReg = + let ir = IRBuilder (4) + !ir insLen + +let cmc ins insLen ctxt = + let cf = !.ctxt R.CF + let ir = IRBuilder (8) + !ir insLen + +let private getCondOfCMov (ins: IntelInternalInstruction) ctxt = + match ins.Opcode with + | Opcode.CMOVO -> !.ctxt R.OF + | Opcode.CMOVNO -> !.ctxt R.OF == AST.b0 + | Opcode.CMOVB -> !.ctxt R.CF + | Opcode.CMOVAE -> !.ctxt R.CF == AST.b0 + | Opcode.CMOVZ -> !.ctxt R.ZF + | Opcode.CMOVNZ -> !.ctxt R.ZF == AST.b0 + | Opcode.CMOVBE -> (!.ctxt R.CF) .| (!.ctxt R.ZF) + | Opcode.CMOVA -> ((!.ctxt R.CF) .| (!.ctxt R.ZF)) == AST.b0 + | Opcode.CMOVS -> !.ctxt R.SF + | Opcode.CMOVNS -> !.ctxt R.SF == AST.b0 + | Opcode.CMOVP -> !.ctxt R.PF + | Opcode.CMOVNP -> !.ctxt R.PF == AST.b0 + | Opcode.CMOVL -> !.ctxt R.SF != !.ctxt R.OF + | Opcode.CMOVGE -> !.ctxt R.SF == !.ctxt R.OF + | Opcode.CMOVLE -> !.ctxt R.ZF .| + (!.ctxt R.SF != !.ctxt R.OF) + | Opcode.CMOVG -> !.ctxt R.ZF == AST.b0 .& + (!.ctxt R.SF == !.ctxt R.OF) + | _ -> raise InvalidOpcodeException + +let cmovcc ins insLen ctxt = + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let ir = IRBuilder (4) + !ir insLen + +let cmp ins insLen ctxt = + let oprSize = getOperationSize ins + let struct (src1, src2) = transTwoOprs ins insLen ctxt + let ir = IRBuilder (16) + let struct (t1, t2, t3) = tmpVars3 ir oprSize + !ir insLen + +let private cmpsBody ins ctxt ir = + let oprSize = getOperationSize ins + let df = !.ctxt R.DF + let si = !.ctxt (if is64bit ctxt then R.RSI else R.ESI) + let di = !.ctxt (if is64bit ctxt then R.RDI else R.EDI) + let src1 = AST.loadLE oprSize si + let src2 = AST.loadLE oprSize di + let struct (t1, t2, t3) = tmpVars3 ir oprSize + let amount = numI32 (RegType.toByteWidth oprSize) ctxt.WordBitSize + !!ir (t1 := src1) + !!ir (t2 := src2) + !!ir (t3 := t1 .- t2) + !!ir (si := AST.ite df (si .- amount) (si .+ amount)) + !!ir (di := AST.ite df (di .- amount) (di .+ amount)) + !?ir (enumEFLAGS ctxt t1 t2 t3 oprSize (cfOnSub t1 t2) (ofOnSub t1 t2 t3)) + +let cmps (ins: InsInfo) insLen ctxt = + let pref = ins.Prefixes + let zf = !.ctxt R.ZF + let ir = IRBuilder (32) + !ir insLen + +let cmpxchg ins insLen ctxt = + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let ir = IRBuilder (32) + ! + !!ir (t := dst) + !!ir (r := acc .- t) + !!ir (cond := acc == t) + !!ir (!.ctxt R.ZF := AST.ite cond AST.b1 AST.b0) + !!ir (dstAssign oprSize dst (AST.ite cond src t)) + !!ir (dstAssign oprSize acc (AST.ite cond acc t)) + !!ir (!.ctxt R.OF := ofOnSub acc t r) + !!ir (!.ctxt R.SF := AST.xthi 1 r) + !!ir (buildAF ctxt acc t r oprSize) + !?ir (buildPF ctxt r oprSize None) + !!ir (!.ctxt R.CF := AST.lt (acc .+ t) acc) + !>ir insLen + +let compareExchangeBytes ins insLen ctxt = + let ir = IRBuilder (8) + let oprSize = getOperationSize ins + let zf = !.ctxt R.ZF + let cond = !*ir 1 + ! -> + let dst = transOneOpr ins insLen ctxt + let edx = getRegOfSize ctxt 32 grpEDX + let eax = getRegOfSize ctxt 32 grpEAX + let ecx = getRegOfSize ctxt 32 grpECX + let ebx = getRegOfSize ctxt 32 grpEBX + let t = !*ir oprSize + !!ir (t := dst) + !!ir (cond := AST.concat edx eax == t) + !!ir (zf := cond) + !!ir (eax := AST.ite cond eax (AST.extract t 32 0)) + !!ir (edx := AST.ite cond edx (AST.extract t 32 32)) + !!ir (dst := AST.ite cond (AST.concat ecx ebx) t) + | 128 -> + let dstB, dstA = + match ins.Operands with + | OneOperand opr -> transOprToExpr128 ins insLen ctxt opr + | _ -> raise InvalidOperandException + let rdx = getRegOfSize ctxt 64 grpEDX + let rax = getRegOfSize ctxt 64 grpEAX + let rcx = getRegOfSize ctxt 64 grpECX + let rbx = getRegOfSize ctxt 64 grpEBX + !!ir (cond := (dstB == rdx) .& (dstA == rax)) + !!ir (zf := cond) + !!ir (rax := AST.ite cond rax dstA) + !!ir (rdx := AST.ite cond rdx dstB) + !!ir (dstA := AST.ite cond rbx dstA) + !!ir (dstB := AST.ite cond rcx dstB) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let convWDQ ins insLen (ctxt: TranslationContext) = + let ir = IRBuilder (8) + let oprSize = getOperationSize ins + !, _ -> + let t = !*ir 32 + let ax = !.ctxt R.AX + let dx = !.ctxt R.DX + !!ir (t := AST.sext 32 ax) + !!ir (dx := AST.xthi 16 t) + !!ir (ax := AST.xtlo 16 t) + | 32, _ -> + let t = !*ir 64 + let eax = !.ctxt R.EAX + let edx = !.ctxt R.EDX + !!ir (t := AST.sext 64 eax) + !!ir (edx := AST.xthi 32 t) + !!ir (eax := AST.xtlo 32 t) + | 64, 64 -> + let t = !*ir 128 + let rdx = !.ctxt R.RDX + let rax = !.ctxt R.RAX + !!ir (t := AST.sext 128 rax) + !!ir (rdx := AST.xthi 64 t) + !!ir (rax := AST.xtlo 64 t) + | _, _ -> raise InvalidOperandSizeException + !>ir insLen + +let daa insLen ctxt = +#if DEBUG + assert32 ctxt +#endif + let ir = IRBuilder (16) + let al = !.ctxt R.AL + let cf = !.ctxt R.CF + let af = !.ctxt R.AF + let oldAl = !*ir 8 + let oldCf = !*ir 1 + let alAnd0f = al .& numI32 0x0f 8 + let subCond1 = AST.gt alAnd0f (numI32 9 8) + let subCond2 = af == AST.b1 + let cond1 = !*ir 1 + let subCond3 = AST.gt oldAl (numI32 0x99 8) + let subCond4 = oldCf == AST.b1 + let cond2 = !*ir 1 + !) al) + !!ir (cf := AST.ite cond1 oldCf cf) + !!ir (af := cond1) + !!ir (cond2 := subCond3 .| subCond4) + !!ir (al := AST.ite cond2 (al .+ numI32 0x60 8) al) + !!ir (cf := cond2) + !?ir (enumSZPFlags ctxt al 8) +#if !EMULATION + !!ir (!.ctxt R.OF := undefOF) +#endif + !>ir insLen + +let das insLen ctxt = +#if DEBUG + assert32 ctxt +#endif + let ir = IRBuilder (16) + let al = !.ctxt R.AL + let cf = !.ctxt R.CF + let af = !.ctxt R.AF + let oldAl = !*ir 8 + let oldCf = !*ir 1 + let alAnd0f = al .& numI32 0x0f 8 + let subCond1 = AST.gt alAnd0f (numI32 9 8) + let subCond2 = af == AST.b1 + let cond1 = !*ir 1 + let subCond3 = AST.gt oldAl (numI32 0x99 8) + let subCond4 = oldCf == AST.b1 + let cond2 = !*ir 1 + !) al) + !!ir (cf := AST.ite cond1 oldCf cf) + !!ir (af := cond1) + !!ir (cond2 := subCond3 .| subCond4) + !!ir (al := AST.ite cond2 (al .- numI32 0x60 8) al) + !!ir (cf := cond2) + !?ir (enumSZPFlags ctxt al 8) +#if !EMULATION + !!ir (!.ctxt R.OF := undefOF) +#endif + !>ir insLen + +let dec ins insLen ctxt = + let dst = transOneOpr ins insLen ctxt + let oprSize = getOperationSize ins + let ir = IRBuilder (16) + let struct (t1, t2, t3) = tmpVars3 ir oprSize + !ir insLen + +let private checkQuotientDIV oprSize lblAssign lblErr q = + AST.cjmp (AST.xthi oprSize q == AST.num0 oprSize) + (AST.name lblAssign) (AST.name lblErr) + +let private checkQuotientIDIV oprSize sz lblAssign lblErr q = + let amount = + AST.num (BitVector.ofInt32 (RegType.toBitWidth oprSize - 1) oprSize) + let mask = AST.num1 oprSize << amount + let msb = AST.xthi 1 q + let negRes = AST.lt q (AST.zext sz mask) + let posRes = AST.gt q (AST.zext sz (mask .- (AST.num1 oprSize))) + let cond = AST.ite (msb == AST.b1) negRes posRes + AST.cjmp cond (AST.name lblErr) (AST.name lblAssign) + +let div ins insLen ctxt = + let ir = IRBuilder (16) + let lblAssign = ir.NewSymbol "Assign" + let lblChk = ir.NewSymbol "Check" + let lblErr = ir.NewSymbol "DivErr" + let divisor = transOneOpr ins insLen ctxt + let oprSize = getOperationSize ins + let dividend = getDividend ctxt oprSize + let sz = TypeCheck.typeOf dividend + let quotient = !*ir sz + let remainder = !*ir sz + ! + let divisor = AST.zext sz divisor + !!ir (quotient := dividend ./ divisor) + !!ir (remainder := dividend .% divisor) + !!ir (checkQuotientDIV oprSize lblAssign lblErr quotient) + | Opcode.IDIV -> + let divisor = AST.sext sz divisor + !!ir (quotient := dividend ?/ divisor) + !!ir (remainder := dividend ?% divisor) + !!ir (checkQuotientIDIV oprSize sz lblAssign lblErr quotient) + | _ -> raise InvalidOpcodeException + !!ir (AST.lmark lblAssign) + match oprSize with + | 8 -> + !!ir (!.ctxt R.AL := AST.xtlo oprSize quotient) + !!ir (!.ctxt R.AH := AST.xtlo oprSize remainder) + | 16 | 32 | 64 -> + let q = getRegOfSize ctxt oprSize grpEAX + let r = getRegOfSize ctxt oprSize grpEDX + !!ir (dstAssign oprSize q (AST.xtlo oprSize quotient)) + !!ir (dstAssign oprSize r (AST.xtlo oprSize remainder)) + | _ -> raise InvalidOperandSizeException +#if !EMULATION + !!ir (!.ctxt R.CF := undefCF) + !!ir (!.ctxt R.OF := undefOF) + !!ir (!.ctxt R.AF := undefAF) + !!ir (!.ctxt R.SF := undefSF) + !!ir (!.ctxt R.ZF := undefZF) + !!ir (!.ctxt R.PF := undefPF) +#endif + !>ir insLen + +let enter ins insLen ctxt = + let oSz = getOperationSize ins + let ir = IRBuilder (16) + let struct (imm16, imm8) = transTwoOprs ins insLen ctxt + let struct (allocSize, nestingLevel, cnt) = tmpVars3 ir oSz + let struct (frameTemp, addrSize) = tmpVars2 ir ctxt.WordBitSize + let bp = getBasePtr ctxt + let sp = getStackPtr ctxt + let lblLoop = ir.NewSymbol "Loop" + let lblCont = ir.NewSymbol "Continue" + let lblLevelCheck = ir.NewSymbol "NestingLevelCheck" + let lblLv1 = ir.NewSymbol "NestingLevel1" + let getAddrSize bitSize = + if bitSize = 64 then numI32 8 bitSize else numI32 4 bitSize + !ir insLen + +let private oneOperandImul ctxt oprSize src ir = + let sF = !.ctxt R.SF + let shiftNum = RegType.toBitWidth oprSize + let mulSize = RegType.double oprSize + let t = !*ir mulSize + let cond = AST.sext mulSize (AST.xtlo oprSize t) == t + match oprSize with + | 8 -> + !!ir (t := AST.sext mulSize (!.ctxt R.AL) .* AST.sext mulSize src) + !!ir (dstAssign oprSize (!.ctxt R.AX) t) + | 16 | 32 | 64 -> + let r1 = getRegOfSize ctxt oprSize grpEDX + let r2 = getRegOfSize ctxt oprSize grpEAX + !!ir (t := AST.sext mulSize r2 .* AST.sext mulSize src) + !!ir (dstAssign oprSize r1 (AST.xthi oprSize t)) + !!ir (dstAssign oprSize r2 (AST.xtlo oprSize t)) + | _ -> raise InvalidOperandSizeException + !!ir (sF := AST.extract t 1 (shiftNum - 1)) + !!ir (!.ctxt R.CF := cond == AST.b0) + !!ir (!.ctxt R.OF := cond == AST.b0) + +let private operandsImul ctxt oprSize dst src1 src2 ir = + let doubleWidth = RegType.double oprSize + let t = !*ir doubleWidth + let cond = (AST.sext doubleWidth dst) != t + !!ir (t := AST.sext doubleWidth src1 .* AST.sext doubleWidth src2) + !!ir (dstAssign oprSize dst (AST.xtlo oprSize t)) + !!ir (!.ctxt R.SF := AST.xthi 1 dst) + !!ir (!.ctxt R.CF := cond) + !!ir (!.ctxt R.OF := cond) + +let private buildMulBody ins insLen ctxt ir = + let oprSize = getOperationSize ins + match ins.Operands with + | OneOperand op -> + let src = transOprToExpr ins insLen ctxt op + oneOperandImul ctxt oprSize src ir + | TwoOperands (o1, o2) -> + let dst = transOprToExpr ins insLen ctxt o1 + let src = transOprToExpr ins insLen ctxt o2 + operandsImul ctxt oprSize dst dst src ir + | ThreeOperands (o1, o2, o3) -> + let dst = transOprToExpr ins insLen ctxt o1 + let src1 = transOprToExpr ins insLen ctxt o2 + let src2 = transOprToExpr ins insLen ctxt o3 + operandsImul ctxt oprSize dst src1 src2 ir + | _ -> raise InvalidOperandException + +let imul ins insLen ctxt = + let ir = IRBuilder (24) + !ir insLen + +let inc ins insLen ctxt = + let dst = transOneOpr ins insLen ctxt + let oprSize = getOperationSize ins + let ir = IRBuilder (16) + let struct (t1, t2, t3) = tmpVars3 ir oprSize + !ir insLen + +let private insBody ins ctxt ir = + let oprSize = getOperationSize ins + let df = !.ctxt R.DF + let di = !.ctxt (if is64bit ctxt then R.RDI else R.EDI) + let src = AST.zext ctxt.WordBitSize (!.ctxt R.DX) + let amount = numI32 (RegType.toByteWidth oprSize) ctxt.WordBitSize + !!ir (AST.loadLE ctxt.WordBitSize di := src) + !!ir (di := AST.ite df (di .- amount) (di .+ amount)) + +let insinstr (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (16) + !ir insLen + +let interrupt ins insLen ctxt = + match transOneOpr ins insLen ctxt with + | { E = Num n } -> Interrupt (BitVector.toInt32 n) |> sideEffects insLen + | _ -> raise InvalidOperandException + +let private getCondOfJcc (ins: IntelInternalInstruction) (ctxt: TranslationContext) = +#if DEBUG + if ctxt.WordBitSize = 64 && (getOperationSize ins) = 16 then + Utils.impossible () + else () +#endif + match ins.Opcode with + | Opcode.JO -> !.ctxt R.OF + | Opcode.JNO -> !.ctxt R.OF == AST.b0 + | Opcode.JB -> !.ctxt R.CF + | Opcode.JNB -> !.ctxt R.CF == AST.b0 + | Opcode.JZ -> !.ctxt R.ZF + | Opcode.JNZ -> !.ctxt R.ZF == AST.b0 + | Opcode.JBE -> (!.ctxt R.CF) .| (!.ctxt R.ZF) + | Opcode.JA -> ((!.ctxt R.CF) .| (!.ctxt R.ZF)) == AST.b0 + | Opcode.JS -> !.ctxt R.SF + | Opcode.JNS -> !.ctxt R.SF == AST.b0 + | Opcode.JP -> !.ctxt R.PF + | Opcode.JNP -> !.ctxt R.PF == AST.b0 + | Opcode.JL -> !.ctxt R.SF != !.ctxt R.OF + | Opcode.JNL -> !.ctxt R.SF == !.ctxt R.OF + | Opcode.JLE -> (!.ctxt R.ZF) .| + (!.ctxt R.SF != !.ctxt R.OF) + | Opcode.JG -> (!.ctxt R.ZF == AST.b0) .& + (!.ctxt R.SF == !.ctxt R.OF) + | Opcode.JCXZ -> (!.ctxt R.CX) == (AST.num0 ctxt.WordBitSize) + | Opcode.JECXZ -> + let sz = ctxt.WordBitSize + (AST.cast CastKind.ZeroExt sz (!.ctxt R.ECX)) == (AST.num0 sz) + | Opcode.JRCXZ -> (!.ctxt R.RCX) == (AST.num0 ctxt.WordBitSize) + | _ -> raise InvalidOpcodeException + +let jcc ins insLen ctxt = + let pc = getInstrPtr ctxt + let jmpTarget = pc .+ transOneOpr ins insLen ctxt + let cond = getCondOfJcc ins ctxt + let fallThrough = pc .+ numInsLen insLen ctxt + let ir = IRBuilder (4) + !ir insLen + +let jmp ins insLen ctxt = + let pc = getInstrPtr ctxt + let struct (target, _) = transJumpTargetOpr ins pc insLen ctxt + let ir = IRBuilder (4) + !ir insLen + +let private convertSrc = function + | Load (_, _, expr, _) -> expr + | _ -> Utils.impossible () + +let lea ins insLen ctxt = + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let src = convertSrc src.E + let addrSize = getEffAddrSz ins + let ir = IRBuilder (4) + !, 16 | 32, 32 | 64, 64 -> + dstAssign oprSize dst src + | 16, 32 | 16, 64 -> + dstAssign oprSize dst (AST.xtlo 16 src) + | 32, 16 -> dstAssign oprSize dst (AST.zext 32 src) + | 32, 64 -> dstAssign oprSize dst (AST.xtlo 32 src) + | _ -> raise InvalidOperandSizeException) + !>ir insLen + +let leave _ins insLen ctxt = + let sp = getStackPtr ctxt + let bp = getBasePtr ctxt + let ir = IRBuilder (8) + !ir insLen + +let private lodsBody ins ctxt ir = + let oprSize = getOperationSize ins + let df = !.ctxt R.DF + let di = !.ctxt (if is64bit ctxt then R.RDI else R.EDI) + let dst = getRegOfSize ctxt oprSize grpEAX + let amount = numI32 (RegType.toByteWidth oprSize) ctxt.WordBitSize + !!ir (dst := AST.loadLE oprSize di) + !!ir (di := AST.ite df (di .- amount) (di .+ amount)) + +let lods (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (16) + !ir insLen + +let loop ins insLen ctxt = + let ir = IRBuilder (8) + let dst = transOneOpr ins insLen ctxt + let addrSize = getEffAddrSz ins + let pc = getInstrPtr ctxt + let count, cntSize = + if addrSize = 32 then !.ctxt R.ECX, 32 + elif addrSize = 64 then !.ctxt R.RCX, 64 + else !.ctxt R.CX, 16 + let zf = !.ctxt R.ZF + ! count != AST.num0 cntSize + | Opcode.LOOPE -> (zf == AST.b1) .& (count != AST.num0 cntSize) + | Opcode.LOOPNE -> (zf == AST.b0) .& (count != AST.num0 cntSize) + | _ -> raise InvalidOpcodeException + let fallThrough = pc .+ numInsLen insLen ctxt + let jumpTarget = if addrSize = 16 then pc .& numI32 0xFFFF 32 + else pc .+ AST.sext addrSize dst + !!ir (AST.intercjmp branchCond jumpTarget fallThrough) + !>ir insLen + +let lzcnt ins insLen ctxt = + let ir = IRBuilder (16) + let lblLoop = ir.NewSymbol "Loop" + let lblExit = ir.NewSymbol "Exit" + let lblLoopCond = ir.NewSymbol "LoopCond" + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let n = AST.num0 oprSize + ! (src >> temp)) == AST.b0) + !!ir (AST.cjmp cond1 (AST.name lblLoop) (AST.name lblExit)) + !!ir (AST.lmark lblLoop) + !!ir (temp := temp .- AST.num1 oprSize) + !!ir (dst := dst .+ AST.num1 oprSize) + !!ir (AST.jmp (AST.name lblLoopCond)) + !!ir (AST.lmark lblExit) + let oprSize = numI32 (RegType.toBitWidth oprSize) oprSize + !!ir (!.ctxt R.CF := dst == oprSize) + !!ir (!.ctxt R.ZF := dst == n) +#if !EMULATION + !!ir (!.ctxt R.OF := undefOF) + !!ir (!.ctxt R.SF := undefSF) + !!ir (!.ctxt R.PF := undefPF) + !!ir (!.ctxt R.AF := undefAF) +#endif + !>ir insLen + +let mov ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + !ir insLen + +let movbe ins insLen ctxt = + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let cnt = RegType.toByteWidth oprSize |> int + let ir = IRBuilder (2 * cnt) + let t = !*ir oprSize + let tmps = Array.init cnt (fun _ -> !*ir 8) + ! (i * 8)) + done + !!ir (dstAssign oprSize dst (AST.concatArr (Array.rev tmps))) + !>ir insLen + +let private movsBody ins ctxt ir = + let oprSize = getOperationSize ins + let df = !.ctxt R.DF + let si = !.ctxt (if is64bit ctxt then R.RSI else R.ESI) + let di = !.ctxt (if is64bit ctxt then R.RDI else R.EDI) + let amount = numI32 (RegType.toByteWidth oprSize) ctxt.WordBitSize + !!ir (AST.loadLE oprSize di := AST.loadLE oprSize si) + !!ir (si := AST.ite df (si .- amount) (si .+ amount)) + !!ir (di := AST.ite df (di .- amount) (di .+ amount)) + +let movs (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (16) + !ir insLen + +let movsx ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + !ir insLen + +let movzx ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + !ir insLen + +let mul ins insLen ctxt = + let ir = IRBuilder (16) + let oprSize = getOperationSize ins + let dblWidth = RegType.double oprSize + let src1 = AST.zext dblWidth (getRegOfSize ctxt oprSize grpEAX) + let src2 = AST.zext dblWidth (transOneOpr ins insLen ctxt) + let t = !*ir dblWidth + ! + match oprSize with + | 8 -> !!ir (!.ctxt R.AX := t) + | 16 | 32 | 64 -> + !!ir (getRegOfSize ctxt oprSize grpEDX := AST.xthi oprSize t) + !!ir (getRegOfSize ctxt oprSize grpEAX := AST.xtlo oprSize t) + | _ -> raise InvalidOperandSizeException + !!ir (cond := AST.xthi oprSize t != (AST.num0 oprSize)) + !!ir (!.ctxt R.CF := cond) + !!ir (!.ctxt R.OF := cond) +#if !EMULATION + !!ir (!.ctxt R.SF := undefSF) + !!ir (!.ctxt R.ZF := undefZF) + !!ir (!.ctxt R.AF := undefAF) + !!ir (!.ctxt R.PF := undefPF) +#endif + !>ir insLen + +let neg ins insLen ctxt = + let ir = IRBuilder (16) + let dst = transOneOpr ins insLen ctxt + let oprSize = getOperationSize ins + let t = !*ir oprSize + let oFCond = t == (AST.num1 oprSize << (numU32 31u oprSize) ) + !ir insLen + +let nop insLen = + let ir = IRBuilder (4) + !ir insLen + +let not ins insLen ctxt = + let ir = IRBuilder (4) + let dst = transOneOpr ins insLen ctxt + let oprSize = getOperationSize ins + !ir insLen + +let logOr ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let t = !*ir oprSize + !ir insLen + +let private outsBody ins ctxt ir = + let oprSize = getOperationSize ins + let df = !.ctxt R.DF + let si = !.ctxt (if is64bit ctxt then R.RSI else R.ESI) + let src = !.ctxt R.DX + let amount = numI32 (RegType.toByteWidth oprSize) ctxt.WordBitSize + match oprSize with + | 8 -> + !!ir (src := AST.zext 16 (AST.loadLE oprSize si)) + !!ir (si := AST.ite df (si .- amount) (si .+ amount)) + | 16 -> + !!ir (src := AST.loadLE oprSize si) + !!ir (si := AST.ite df (si .- amount) (si .+ amount)) + | 32 -> + !!ir (si := AST.ite df (si .- amount) (si .+ amount)) + !!ir (src := AST.xtlo 16 (AST.loadLE oprSize si)) + | _ -> raise InvalidOperandSizeException + +let outs (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (16) + !ir insLen + +let pop ins insLen ctxt = + let dst = transOneOpr ins insLen ctxt + let oprSize = getOperationSize ins + let ir = IRBuilder (4) + !ir insLen + +let popa insLen ctxt oprSize = + let sp = !.ctxt R.ESP + let di = if oprSize = 32 then R.EDI else R.DI + let si = if oprSize = 32 then R.ESI else R.SI + let bp = if oprSize = 32 then R.EBP else R.BP + let bx = if oprSize = 32 then R.EBX else R.BX + let dx = if oprSize = 32 then R.EDX else R.DX + let cx = if oprSize = 32 then R.ECX else R.CX + let ax = if oprSize = 32 then R.EAX else R.AX + let ir = IRBuilder (16) + !)) + !?ir (auxPop oprSize ctxt (!.ctxt bx)) + !?ir (auxPop oprSize ctxt (!.ctxt dx)) + !?ir (auxPop oprSize ctxt (!.ctxt cx)) + !?ir (auxPop oprSize ctxt (!.ctxt ax)) + !>ir insLen + +let popcnt ins insLen ctxt = + let ir = IRBuilder (16) + let lblLoop = ir.NewSymbol "Loop" + let lblExit = ir.NewSymbol "Exit" + let lblLoopCond = ir.NewSymbol "LoopCond" + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let max = numI32 (RegType.toBitWidth oprSize) oprSize + ! (src >> i)) == AST.b1 + !!ir (count := AST.ite cond (count .+ AST.num1 oprSize) count) + !!ir (i := i .+ AST.num1 oprSize) + !!ir (AST.jmp (AST.name lblLoopCond)) + !!ir (AST.lmark lblExit) + !!ir (dstAssign oprSize dst count) + !!ir (!.ctxt R.OF := AST.b0) + !!ir (!.ctxt R.SF := AST.b0) + !!ir (!.ctxt R.ZF := src == AST.num0 oprSize) + !!ir (!.ctxt R.AF := AST.b0) + !!ir (!.ctxt R.CF := AST.b0) + !!ir (!.ctxt R.PF := AST.b0) + !>ir insLen + +let popf ins insLen ctxt = + let ir = IRBuilder (16) + let oprSize = getOperationSize ins + let t = !*ir oprSize + ! 11) + !!ir (!.ctxt R.DF := AST.extract t 1 10) + !!ir (!.ctxt R.IF := AST.extract t 1 9) + !!ir (!.ctxt R.TF := AST.extract t 1 8) + !!ir (!.ctxt R.SF := AST.extract t 1 7) + !!ir (!.ctxt R.ZF := AST.extract t 1 6) + !!ir (!.ctxt R.AF := AST.extract t 1 4) + !!ir (!.ctxt R.PF := AST.extract t 1 2) + !!ir (!.ctxt R.CF := AST.xtlo 1 t) + !>ir insLen + +let inline private padPushExpr oprSize opr = + match opr.E with + | Var (_, s, _, _) -> + if isSegReg <| Register.ofRegID s then AST.zext oprSize opr else opr + | Num (_) -> AST.sext oprSize opr + | _ -> opr + +let push ins insLen ctxt = + let src = transOneOpr ins insLen ctxt + let oprSize = getOperationSize ins + let ir = IRBuilder (8) + !ir insLen + +let pusha ins insLen ctxt oprSize = + let ir = IRBuilder (16) + let t = !*ir oprSize + let sp = if oprSize = 32 then R.ESP else R.SP + let ax = if oprSize = 32 then R.EAX else R.AX + let cx = if oprSize = 32 then R.ECX else R.CX + let dx = if oprSize = 32 then R.EDX else R.DX + let bx = if oprSize = 32 then R.EBX else R.BX + let bp = if oprSize = 32 then R.EBP else R.BP + let si = if oprSize = 32 then R.ESI else R.SI + let di = if oprSize = 32 then R.EDI else R.DI + !ir insLen + +let pushf ins insLen ctxt = + let oprSize = getOperationSize ins + let e = AST.zext oprSize <| !.ctxt R.CF + (* We only consider 9 flags (we ignore system flags). *) + let e = e .| ((AST.zext oprSize (!.ctxt R.PF)) << numI32 2 oprSize) + let e = e .| ((AST.zext oprSize (!.ctxt R.AF)) << numI32 4 oprSize) + let e = e .| ((AST.zext oprSize (!.ctxt R.ZF)) << numI32 6 oprSize) + let e = e .| ((AST.zext oprSize (!.ctxt R.SF)) << numI32 7 oprSize) + let e = e .| ((AST.zext oprSize (!.ctxt R.TF)) << numI32 8 oprSize) + let e = e .| ((AST.zext oprSize (!.ctxt R.IF)) << numI32 9 oprSize) + let e = e .| ((AST.zext oprSize (!.ctxt R.DF)) << numI32 10 oprSize) + let e = e .| ((AST.zext oprSize (!.ctxt R.OF)) << numI32 11 oprSize) + let e = match oprSize with + | 16 -> e + | 32 -> e .& (numI32 0xfcffff 32) + | 64 -> e .& (numI32 0xfcffff 64) + | _ -> raise InvalidOperandSizeException + let ir = IRBuilder (8) + !ir insLen + +let rcl ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, count) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let cF = !.ctxt R.CF + let oF = !.ctxt R.OF + let tmpCount = !*ir oprSize + let size = numI32 (RegType.toBitWidth oprSize) oprSize + let count = AST.zext oprSize count + let cnt = + match oprSize with + | 8 -> (count .& numI32 0x1f oprSize) .% numI32 9 oprSize + | 16 -> (count .& numI32 0x1f oprSize) .% numI32 17 oprSize + | 32 -> count .& numI32 0x1f oprSize + | 64 -> count .& numI32 0x3f oprSize + | _ -> raise InvalidOperandSizeException + let cond = count == AST.num1 oprSize + !> (size .- tmpCount))) + !!ir (cF := AST.xthi 1 dst) +#if !EMULATION + !!ir (oF := AST.ite cond (AST.xthi 1 dst <+> cF) undefOF) +#else + !!ir (oF := AST.ite cond (AST.xthi 1 dst <+> cF) oF) +#endif + !>ir insLen + +let rcr ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, count) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let cF = !.ctxt R.CF + let oF = !.ctxt R.OF + let tmpCount = !*ir oprSize + let size = numI32 (RegType.toBitWidth oprSize) oprSize + let count = AST.zext oprSize count + let cnt = + match oprSize with + | 8 -> (count .& numI32 0x1f oprSize) .% numI32 9 oprSize + | 16 -> (count .& numI32 0x1f oprSize) .% numI32 17 oprSize + | 32 -> count .& numI32 0x1f oprSize + | 64 -> count .& numI32 0x3f oprSize + | _ -> raise InvalidOperandSizeException + let cond = count == AST.num1 oprSize + ! dst <+> cF) undefOF) +#else + !!ir (oF := AST.ite cond (AST.xthi 1 dst <+> cF) oF) +#endif + !!ir (dst := (dst >> tmpCount) .| (dst << (size .- tmpCount))) + !!ir (cF := AST.xthi 1 dst) + !>ir insLen + +let rdpkru ins insLen ctxt = + let ir = IRBuilder (8) + let lblSucc = ir.NewSymbol "Succ" + let lblErr = ir.NewSymbol "Err" + let oprSize = getOperationSize ins + let ecx = !.ctxt R.ECX + let eax = getRegOfSize ctxt ctxt.WordBitSize grpEAX + let edx = getRegOfSize ctxt ctxt.WordBitSize grpEDX + !ir insLen + +let retWithImm ins insLen ctxt = + let ir = IRBuilder (8) + let oprSize = getOperationSize ins + let t = !*ir oprSize + let sp = getStackPtr ctxt + let src = transOneOpr ins insLen ctxt + !ir insLen + +let ret ins insLen ctxt = + let ir = IRBuilder (6) + let oprSize = getOperationSize ins + let t = !*ir oprSize + !ir insLen + +let rotate ins insLen ctxt lfn hfn cfFn ofFn = + let ir = IRBuilder (8) + let struct (dst, count) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let cF = !.ctxt R.CF + let oF = !.ctxt R.OF + let countMask = if is64REXW ctxt ins then numU32 0x3Fu oprSize + else numU32 0x1Fu oprSize + let size = numI32 (RegType.toBitWidth oprSize) oprSize + let orgCount = !*ir oprSize + let cond1 = orgCount == AST.num0 oprSize + let cond2 = orgCount == AST.num1 oprSize + ! dst)) +#if !EMULATION + !!ir (oF := AST.ite cond2 (ofFn dst cF) undefOF) +#else + !!ir (oF := AST.ite cond2 (ofFn dst cF) oF) +#endif + !>ir insLen + +let rol ins insLen ctxt = + let ofFn dst cF = cF <+> AST.xthi 1 dst + rotate ins insLen ctxt (<<) (>>) AST.xtlo ofFn + +let ror ins insLen ctxt = + let ofFn dst _cF = + AST.xthi 1 dst <+> AST.extract dst 1 1 + rotate ins insLen ctxt (>>) (<<) AST.xthi ofFn + +let rorx ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src, imm) = transThreeOprs ins insLen ctxt + let oprSize = getOperationSize ins + let y = !*ir oprSize + if oprSize = 32 then + !!ir (y := imm .& (numI32 0x1F oprSize)) + !!ir (dst := (src >> y) .| (src << (numI32 32 oprSize .- y))) + else (* OperandSize = 64 *) + !!ir (y := imm .& (numI32 0x3F oprSize)) + !!ir (dst := (src >> y) .| (src << (numI32 64 oprSize .- y))) + !>ir insLen + +let sahf ins insLen ctxt = + let ir = IRBuilder (8) + let ah = !.ctxt R.AH + ! ah) + !!ir (!.ctxt R.PF := AST.extract ah 1 2) + !!ir (!.ctxt R.AF := AST.extract ah 1 4) + !!ir (!.ctxt R.ZF := AST.extract ah 1 6) + !!ir (!.ctxt R.SF := AST.extract ah 1 7) + !>ir insLen + +let shift ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let n0 = AST.num0 oprSize + let n1 = AST.num1 oprSize + let countMask = if is64REXW ctxt ins then numU32 0x3Fu oprSize + else numU32 0x1Fu oprSize + let cnt = (AST.zext oprSize src) .& countMask + let cond1 = cnt == n1 + let cond2 = cnt == n0 + let oF = !.ctxt R.OF + let cF = !.ctxt R.CF + let sF = !.ctxt R.SF + let zF = !.ctxt R.ZF + let aF = !.ctxt R.AF + let tDst = !*ir oprSize + let tCnt = !*ir oprSize + ! + let prevLBit = AST.xtlo 1 (tDst ?>> tCnt) + !!ir (dst := dst ?>> cnt) + !!ir (tCnt := cnt .- n1) + !!ir (cF := AST.ite cond2 cF prevLBit) +#if !EMULATION + !!ir (oF := AST.ite cond1 AST.b0 (AST.ite cond2 oF undefOF)) +#else + !!ir (oF := AST.ite cond1 AST.b0 oF) +#endif + | Opcode.SHL -> + let prevHBit = AST.xthi 1 (tDst << tCnt) + let of1 = AST.xthi 1 dst <+> cF + !!ir (dstAssign oprSize dst (dst << cnt)) + !!ir (tCnt := cnt .- n1) + !!ir (cF := AST.ite cond2 cF prevHBit) +#if !EMULATION + !!ir (oF := AST.ite cond1 of1 (AST.ite cond2 oF undefOF)) +#else + !!ir (oF := AST.ite cond1 of1 oF) +#endif + | Opcode.SHR -> + let prevLBit = AST.xtlo 1 (tDst ?>> tCnt) + !!ir (dstAssign oprSize dst (dst >> cnt)) + !!ir (tCnt := cnt .- n1) + !!ir (cF := AST.ite cond2 cF prevLBit) +#if !EMULATION + !!ir + (oF := AST.ite cond1 (AST.xthi 1 tDst) (AST.ite cond2 oF undefOF)) +#else + !!ir (oF := AST.ite cond1 (AST.xthi 1 tDst) oF) +#endif + | _ -> raise InvalidOpcodeException + !!ir (sF := AST.ite cond2 sF (AST.xthi 1 dst)) + !?ir (buildPF ctxt dst oprSize (Some cond2)) + !!ir (zF := AST.ite cond2 zF (dst == n0)) +#if !EMULATION + !!ir (aF := AST.ite cond2 aF undefAF) +#endif + !>ir insLen + +let sbb ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let struct (t1, t2, t3, t4) = tmpVars4 ir oprSize + let cf = !.ctxt R.CF + !ir insLen + +let private scasBody ins ctxt ir = + let oprSize = getOperationSize ins + let t = !*ir oprSize + let df = !.ctxt R.DF + let x = getRegOfSize ctxt oprSize grpEAX + let di = !.ctxt (if is64bit ctxt then R.RDI else R.EDI) + let tSrc = !*ir oprSize + let amount = numI32 (RegType.toByteWidth oprSize) ctxt.WordBitSize + !!ir (tSrc := AST.loadLE oprSize di) + !!ir (t := x .- tSrc) + !?ir (enumEFLAGS ctxt x tSrc t oprSize (cfOnSub x tSrc) (ofOnSub x tSrc t)) + !!ir (di := AST.ite df (di .- amount) (di .+ amount)) + +let scas (ins: InsInfo) insLen ctxt = + let pref = ins.Prefixes + let zfCond n = Some (!.ctxt R.ZF == n) + let ir = IRBuilder (32) + !ir insLen + +let private getCondOfSet (ins: IntelInternalInstruction) ctxt = + match ins.Opcode with + | Opcode.SETO -> !.ctxt R.OF + | Opcode.SETNO -> !.ctxt R.OF == AST.b0 + | Opcode.SETB -> !.ctxt R.CF + | Opcode.SETNB -> !.ctxt R.CF == AST.b0 + | Opcode.SETZ -> !.ctxt R.ZF + | Opcode.SETNZ -> !.ctxt R.ZF == AST.b0 + | Opcode.SETBE -> (!.ctxt R.CF) .| (!.ctxt R.ZF) + | Opcode.SETA -> ((!.ctxt R.CF) .| (!.ctxt R.ZF)) == AST.b0 + | Opcode.SETS -> !.ctxt R.SF + | Opcode.SETNS -> !.ctxt R.SF == AST.b0 + | Opcode.SETP -> !.ctxt R.PF + | Opcode.SETNP -> !.ctxt R.PF == AST.b0 + | Opcode.SETL -> !.ctxt R.SF != !.ctxt R.OF + | Opcode.SETNL -> !.ctxt R.SF == !.ctxt R.OF + | Opcode.SETLE -> !.ctxt R.ZF .| + (!.ctxt R.SF != !.ctxt R.OF) + | Opcode.SETG -> (!.ctxt R.ZF == AST.b0) .& + (!.ctxt R.SF == !.ctxt R.OF) + | _ -> raise InvalidOpcodeException + +let setcc ins insLen ctxt = + let ir = IRBuilder (4) + let dst = transOneOpr ins insLen ctxt + let oprSize = getOperationSize ins + let cond = getCondOfSet ins ctxt |> AST.zext oprSize + !ir insLen + +let inline shiftDblPrec ins insLen ctxt fnDst fnSrc isShl = + let ir = IRBuilder (16) + let struct (dst, src, cnt) = transThreeOprs ins insLen ctxt + let oprSize = getOperationSize ins + let orig = !*ir oprSize + let c = !*ir oprSize + let cond1 = c == AST.num0 oprSize + let cond2 = c == AST.num1 oprSize + let cF = !.ctxt R.CF + let oF = !.ctxt R.OF + let aF = !.ctxt R.AF + let maxSz = numI32 (if is64REXW ctxt ins then 64 else 32) oprSize + let final = AST.ite cond1 orig ((fnDst orig c) .| (fnSrc src (maxSz .- c))) + ! (orig >> (maxSz .- c))) + else + cF := AST.ite cond1 cF (AST.xtlo 1 (orig >> (c .- AST.num1 oprSize))) + ) +#if !EMULATION + !!ir (oF := AST.ite cond1 oF + (AST.ite cond2 (AST.xthi 1 (orig <+> dst)) undefOF)) + !!ir (aF := AST.ite cond1 aF undefAF) +#else + !!ir (oF := AST.ite cond1 oF + (AST.ite cond2 (AST.xthi 1 (orig <+> dst)) oF)) +#endif + !?ir (enumSZPFlags ctxt dst oprSize) + !>ir insLen + +let shld ins insLen ctxt = + shiftDblPrec ins insLen ctxt (<<) (>>) true + +let shrd ins insLen ctxt = + shiftDblPrec ins insLen ctxt (>>) (<<) false + +let shlx ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src1, src2) = transThreeOprs ins insLen ctxt + let oprSize = getOperationSize ins + let temp = !*ir oprSize + let countMask = if is64REXW ctxt ins then 0x3F else 0x1F // FIXME: CS.L = 1 + let count = src2 .& (numI32 countMask oprSize) + ! dst := AST.xthi 1 temp) + !!ir (dst := dst << count) + !>ir insLen + +let setFlag insLen ctxt flag = + let ir = IRBuilder (4) + !ir insLen + +let stc insLen ctxt = setFlag insLen ctxt R.CF + +let std insLen ctxt = setFlag insLen ctxt R.DF + +let sti insLen ctxt = setFlag insLen ctxt R.IF + +let private stosBody ins ctxt ir = + let oprSize = getOperationSize ins + let df = !.ctxt R.DF + let di = !.ctxt (if is64bit ctxt then R.RDI else R.EDI) + let src = getRegOfSize ctxt oprSize grpEAX + let amount = numI32 (RegType.toByteWidth oprSize) ctxt.WordBitSize + !!ir (AST.loadLE oprSize di := src) + !!ir (di := AST.ite df (di .- amount) (di .+ amount)) + +let stos (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (16) + !ir insLen + +let sub ins insLen ctxt = + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let ir = IRBuilder (16) + let struct (t1, t2, t3) = tmpVars3 ir oprSize + !ir insLen + +let test ins insLen ctxt = + let ir = IRBuilder (16) + let struct (src1, src2) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let t = !*ir oprSize + ! t) + !!ir (!.ctxt R.ZF := t == (AST.num0 oprSize)) + !?ir (buildPF ctxt t oprSize None) + !!ir (!.ctxt R.CF := AST.b0) + !!ir (!.ctxt R.OF := AST.b0) +#if !EMULATION + !!ir (!.ctxt R.AF := undefAF) +#endif + !>ir insLen + +let tzcnt ins insLen ctxt = + let ir = IRBuilder (16) + let lblLoop = ir.NewSymbol "Loop" + let lblExit = ir.NewSymbol "Exit" + let lblLoopCond = ir.NewSymbol "LoopCond" + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let max = numI32 (RegType.toBitWidth oprSize) oprSize + ! (src >> t1) == AST.b0) + !!ir (AST.cjmp cond (AST.name lblLoop) (AST.name lblExit)) + !!ir (AST.lmark lblLoop) + !!ir (t1 := t1 .+ AST.num1 oprSize) + !!ir (AST.jmp (AST.name lblLoopCond)) + !!ir (AST.lmark lblExit) + !!ir (dstAssign oprSize dst t1) + !!ir (!.ctxt R.CF := dst == max) + !!ir (!.ctxt R.ZF := dst == AST.num0 oprSize) +#if !EMULATION + !!ir (!.ctxt R.OF := undefOF) + !!ir (!.ctxt R.SF := undefSF) + !!ir (!.ctxt R.PF := undefPF) + !!ir (!.ctxt R.AF := undefAF) +#endif + !>ir insLen + +let wrfsbase ins insLen ctxt = + let ir = IRBuilder (4) + let src = transOneOpr ins insLen ctxt + !ir insLen + +let wrgsbase ins insLen ctxt = + let ir = IRBuilder (4) + let src = transOneOpr ins insLen ctxt + !ir insLen + +let wrpkru ins insLen ctxt = + let ir = IRBuilder (8) + let lblSucc = ir.NewSymbol "Succ" + let lblErr = ir.NewSymbol "Err" + let oprSize = getOperationSize ins + let ecxIsZero = !.ctxt R.ECX == AST.num0 oprSize + let edxIsZero = !.ctxt R.EDX == AST.num0 oprSize + let cond = ecxIsZero .& edxIsZero + !ir insLen + +let xadd ins insLen ctxt = + let ir = IRBuilder (16) + let struct (d, s) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let t = !*ir oprSize + !ir insLen + +let xchg ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = transTwoOprs ins insLen ctxt + ! src then + let oprSize = getOperationSize ins + let t = !*ir oprSize + !!ir (t := dst) + !!ir (dstAssign oprSize dst src) + !!ir (dstAssign oprSize src t) + !>ir insLen + +let xlatb ins insLen ctxt = + let ir = IRBuilder (4) + let addressSize = getEffAddrSz ins + let al = AST.zext addressSize (!.ctxt R.AL) + let bx = getRegOfSize ctxt addressSize grpEBX + ! (al .+ bx)) + !>ir insLen + +let xor ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src) = transTwoOprs ins insLen ctxt + let oprSize = getOperationSize ins + let r = !*ir oprSize + ! AST.sext oprSize src) + !!ir (dstAssign oprSize dst r) + !!ir (!.ctxt R.OF := AST.b0) + !!ir (!.ctxt R.CF := AST.b0) + !!ir (!.ctxt R.SF := AST.xthi 1 r) + !!ir (!.ctxt R.ZF := r == (AST.num0 oprSize)) + !?ir (buildPF ctxt r oprSize None) +#if !EMULATION + !!ir (!.ctxt R.AF := undefAF) +#endif + !>ir insLen diff --git a/src/FrontEnd/BinLifter/Intel/IntelHelper.fs b/src/FrontEnd/BinLifter/Intel/IntelHelper.fs new file mode 100644 index 00000000..1b71aa7c --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelHelper.fs @@ -0,0 +1,1098 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.Intel.Helper + +open B2R2 +open B2R2.FrontEnd.BinLifter +open System.Runtime.CompilerServices +open LanguagePrimitives + +[] +do () + +type [] OperandParser () = + abstract member Render: ReadHelper -> Operands + +and [] InsSizeComputer () = + abstract Render: ReadHelper -> SzCond -> unit + +and ReadHelper (rd, addr, initialPos, cpos, pref, rex, vex, wordSz, ops, szs) = + let mutable r: BinReader = rd + let mutable addr: Addr = addr + let mutable ipos: int = initialPos + let mutable cpos: int = cpos (* current position *) + let mutable pref: Prefix = pref + let mutable rex: REXPrefix = rex + let mutable vex: VEXInfo option = vex + let mutable wordSize: WordSize = wordSz + let mutable memOprSz = 0 + let mutable memAddrSz = 0 + let mutable memRegSz = 0 + let mutable regSz = 0 + let mutable operationSz = 0 + new (wordSz, oparsers, szcomputers) = + ReadHelper (EmptyBinReader () :> BinReader, + 0UL, 0, 0, Prefix.PrxNone, REXPrefix.NOREX, None, + wordSz, oparsers, szcomputers) + member __.BinReader with get() = r and set(r') = r <- r' + member __.InsAddr with get(): Addr = addr and set(a) = addr <- a + member __.InitialPos with get() = ipos and set(p) = ipos <- p + member __.CurrPos with get() = cpos and set(p) = cpos <- p + member __.IncPos () = cpos <- cpos + 1 + member __.Prefixes with get() = pref and set(p) = pref <- p + member __.REXPrefix with get(): REXPrefix = rex and set(r) = rex <- r + member __.VEXInfo with get(): VEXInfo option = vex and set(v) = vex <- v + member __.WordSize with get(): WordSize = wordSize and set(w) = wordSize <- w + member __.OprParsers with get(): OperandParser [] = ops + member __.SzComputers with get(): InsSizeComputer [] = szs + member __.MemEffOprSize with get() = memOprSz and set(s) = memOprSz <- s + member __.MemEffAddrSize with get() = memAddrSz and set(s) = memAddrSz <- s + member __.MemEffRegSize with get() = memRegSz and set(s) = memRegSz <- s + member __.RegSize with get() = regSz and set(s) = regSz <- s + member __.OperationSize with get() = operationSz and set(s) = operationSz <- s + + member inline private __.ModCPos i = cpos <- cpos + i + member inline __.PeekByte () = r.PeekByte cpos + member inline __.ReadByte () = let v = r.PeekByte cpos in __.ModCPos 1; v + member inline __.ReadInt8 () = let v = r.PeekInt8 cpos in __.ModCPos 1; v + member inline __.ReadInt16 () = let v = r.PeekInt16 cpos in __.ModCPos 2; v + member inline __.ReadInt32 () = let v = r.PeekInt32 cpos in __.ModCPos 4; v + member inline __.ReadInt64 () = let v = r.PeekInt64 cpos in __.ModCPos 8; v + member inline __.ReadUInt8 () = let v = r.PeekUInt8 cpos in __.ModCPos 1; v + member inline __.ReadUInt16 () = let v = r.PeekUInt16 cpos in __.ModCPos 2; v + member inline __.ReadUInt32 () = let v = r.PeekUInt32 cpos in __.ModCPos 4; v + member inline __.ReadUInt64 () = let v = r.PeekUInt64 cpos in __.ModCPos 8; v + member inline __.ParsedLen () = cpos - ipos + member inline __.GetInsID () = + let len = cpos - ipos + let bs = r.PeekBytes (len, ipos) + let chars: char [] = Array.zeroCreate (len * sizeof) + System.Buffer.BlockCopy (bs, 0, chars, 0, bs.Length) + System.String chars + +let inline hasREXW rexPref = rexPref &&& REXPrefix.REXW = REXPrefix.REXW + +let inline hasREXR rexPref = rexPref &&& REXPrefix.REXR = REXPrefix.REXR + +let inline hasAddrSz p = p &&& Prefix.PrxADDRSIZE = Prefix.PrxADDRSIZE + +let inline hasOprSz p = p &&& Prefix.PrxOPSIZE = Prefix.PrxOPSIZE + +let inline hasREPZ p = p &&& Prefix.PrxREPZ = Prefix.PrxREPZ + +let inline hasREPNZ p = p &&& Prefix.PrxREPNZ = Prefix.PrxREPNZ + +let inline hasLock p = p &&& Prefix.PrxLOCK = Prefix.PrxLOCK + +let inline is64bit (rhlp: ReadHelper) = rhlp.WordSize = WordSize.Bit64 + +let inline hasNoPref (rhlp: ReadHelper) = (int rhlp.Prefixes) = 0 + +let inline hasNoREX (rhlp: ReadHelper) = rhlp.REXPrefix = REXPrefix.NOREX + +let inline getMod (byte: byte) = (int byte >>> 6) &&& 0b11 + +let inline getReg (byte: byte) = (int byte >>> 3) &&& 0b111 + +let inline getRM (byte: byte) = (int byte) &&& 0b111 + +let inline getSTReg n = Register.make n Register.Kind.FPU 80 |> OprReg + +let inline modIsMemory b = (getMod b) <> 0b11 + +let inline modIsReg b = (getMod b) = 0b11 + +/// Filter out segment-related prefixes. +let [] clearSegMask: Prefix = EnumOfValue 0xFC0F + +/// Filter out PrxREPNZ(0x2), PrxREPZ(0x8), and PrxOPSIZE(0x400). +let [] clearVEXPrefMask: Prefix = EnumOfValue 0xFBF5 + +/// Filter out group 1 prefixes. +let [] clearGrp1PrefMask: Prefix = EnumOfValue 0xFFF0 + +let getSegment pref = + if (pref &&& Prefix.PrxCS) <> Prefix.PrxNone then Some R.CS + elif (pref &&& Prefix.PrxDS) <> Prefix.PrxNone then Some R.DS + elif (pref &&& Prefix.PrxES) <> Prefix.PrxNone then Some R.ES + elif (pref &&& Prefix.PrxFS) <> Prefix.PrxNone then Some R.FS + elif (pref &&& Prefix.PrxGS) <> Prefix.PrxNone then Some R.GS + elif (pref &&& Prefix.PrxSS) <> Prefix.PrxNone then Some R.SS + else None + +let isBranch = function + | Opcode.CALLFar | Opcode.CALLNear + | Opcode.JMPFar | Opcode.JMPNear + | Opcode.RETFar | Opcode.RETFarImm | Opcode.RETNear | Opcode.RETNearImm + | Opcode.JA | Opcode.JB | Opcode.JBE | Opcode.JCXZ | Opcode.JECXZ + | Opcode.JG | Opcode.JL | Opcode.JLE | Opcode.JNB | Opcode.JNL | Opcode.JNO + | Opcode.JNP | Opcode.JNS | Opcode.JNZ | Opcode.JO | Opcode.JP + | Opcode.JRCXZ | Opcode.JS | Opcode.JZ | Opcode.LOOP | Opcode.LOOPE + | Opcode.LOOPNE -> true + | _ -> false + +let isCETInstr = function + | Opcode.INCSSPD | Opcode.INCSSPQ | Opcode.RDSSPD | Opcode.RDSSPQ + | Opcode.SAVEPREVSSP | Opcode.RSTORSSP | Opcode.WRSSD | Opcode.WRSSQ + | Opcode.WRUSSD | Opcode.WRUSSQ | Opcode.SETSSBSY | Opcode.CLRSSBSY -> true + | _ -> false + +/////////////////////////////// +let getOprSize size sizeCond = + if sizeCond = SzCond.F64 || + (size = 32 && sizeCond = SzCond.D64) then 64 + else size + +let inline getEffOprSize32 prefs = + if hasOprSz prefs then 16 else 32 + +let inline getEffAddrSize32 prefs = + if hasAddrSz prefs then 16 else 32 + +let inline getEffOprSize64 prefs rexPref sizeCond = + if hasREXW rexPref then 64 + else + if hasOprSz prefs then getOprSize 16 sizeCond + else getOprSize 32 sizeCond + +let inline getEffAddrSize64 prefs = + if hasAddrSz prefs then 32 else 64 + +let getEffAddrSize (rhlp: ReadHelper) = + if rhlp.WordSize = WordSize.Bit32 then getEffAddrSize32 rhlp.Prefixes + else getEffAddrSize64 rhlp.Prefixes + +let getEffOprSize (rhlp: ReadHelper) sizeCond = + if rhlp.WordSize = WordSize.Bit32 then getEffOprSize32 rhlp.Prefixes + else getEffOprSize64 rhlp.Prefixes rhlp.REXPrefix sizeCond + +/// AHR12LIb ALIb ALOb ALR8LIb BHR15LIb BLR11LIb CHR13LIb CLR9LIb DHR14LIb +/// DLR10LIb Eb Eb1 EbCL EbGb EbIb GbEb IbAL Jb ObAL XbYb +type SzByte () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 8 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 8 + rhlp.RegSize <- 8 + rhlp.OperationSize <- 8 + +/// GwMw EvSw EwGw MwGw SwEw +type SzWord () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 16 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 16 + rhlp.RegSize <- 16 + rhlp.OperationSize <- 16 + +/// ALDX DXAL DXEAX EAX EAXDX EAXIb EBP EBX ECX EDI EDX ESI ESP Ev Ev1 EvCL EvGv +/// EvGvCL EvGvIb EvIb EvSIb EvSIz EyGy GvEv GvEvSIb GvEvSIz GvEy GvMa GvMv +/// GyByEy GyEy GyEyBy GyEyIb GyMy Ib IbEAX Iw IwIb Mv MyGy Mz OvRAX RAXIv RAXOv +/// RAXrAX RAXrBP RAXrBX RAXrCX RAXrDI RAXrDX RAXrSI RAXrSP RAXSIz RAXz RBPIv +/// RBPz RBXIv RBXz RCXIv RCXz RDIIv RDIz RDXIv RDXz RSIIv RSIz RSPIv RSPz Rv Ry +/// SIb SIz +type SzDef () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- effOprSz + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- effOprSz + +/// HxUxIb MpdVpd MpsVps MxVx MZxzVZxz VpdHpdWpd VpdHpdWpdIb VpdWpd VpsHpsWps +/// VpsHpsWpsIb VpsWps VsdHsdWsdIb VssHssWssIb VxHxWsd VxHxWss VxHxWx VxHxWxIb +/// VxMx VxWx VxWxIb VZxzWZxz WpdVpd WpsVps WsdHxVsd WssHxVss WxVx WZxzVZxz +type SzVecDef () = + inherit InsSizeComputer () + override __.Render (rhlp: ReadHelper) _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- vLen + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- vLen + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// GvEd Md +type SzDV () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 32 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 32 + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- effOprSz + +/// Md +type SzD () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 32 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 32 + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- 32 + +/// Ew Mw +type SzMemW () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 16 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 16 + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- 16 + +/// CS ES DS FS GS SS +type SzRegW () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- effOprSz + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- 16 + rhlp.OperationSize <- 16 + +/// GvEw +type SzWV () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 16 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 16 + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- effOprSz + +/// RAX RCX RDX RBX RSP RBP RSI RDI Jz +type SzD64 () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + let oprSize = WordSize.toRegType rhlp.WordSize + rhlp.MemEffOprSize <- effOprSz + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- oprSize + rhlp.OperationSize <- oprSize + +/// GzMp +type SzPZ () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + let oprSize = + if rhlp.Prefixes &&& Prefix.PrxOPSIZE = Prefix.PrxOPSIZE then 32 + else 48 + rhlp.MemEffOprSize <- oprSize + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- effOprSz + +/// MdqVdq VdqHdqUdq VdqHdqWdqIb VdqMdq VdqUdq VdqWdq VdqWdqIb WdqVdq +type SzDqDq () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 128 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- 128 + rhlp.OperationSize <- 128 + +/// VdqWdqd VdqMd VdqHdqWdqd VdqWdqdIb MdVdq +type SzDqdDq () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 32 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- 128 + rhlp.OperationSize <- 128 + +/// WdqdVdq MdVdq +type SzDqdDqMR () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 32 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- 128 + rhlp.OperationSize <- 32 + +/// VdqWdqq VdqMq VdqHdqMq VdqHdqWdqq VdqWdqqIb WdqqVdq MqVdq +type SzDqqDq () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 64 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- 128 + rhlp.OperationSize <- 128 + +/// WdqqVdq MqVdq +type SzDqqDqMR () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 64 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- 128 + rhlp.OperationSize <- 64 + +/// VxWxq +type SzXqX () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let effAddrSz = getEffAddrSize rhlp + let vLen = (Option.get rhlp.VEXInfo).VectorLength + let struct (mopr, maddr, mreg) = + match vLen with + | 128 -> struct (64, effAddrSz, 128) + | 256 -> struct (vLen, effAddrSz, vLen) + | _ -> Utils.futureFeature () (* EVEX *) + rhlp.MemEffOprSize <- mopr + rhlp.MemEffAddrSize <- maddr + rhlp.MemEffRegSize <- mreg + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// BNBNdqq BNdqqBN +type SzDqqDqWS () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + let struct (mopr, maddr, mreg) = + match rhlp.WordSize with + | WordSize.Bit32 -> struct (64, effAddrSz, 128) + | WordSize.Bit64 -> struct (128, effAddrSz, 128) + | _ -> raise ParsingFailureException + rhlp.MemEffOprSize <- mopr + rhlp.MemEffAddrSize <- maddr + rhlp.MemEffRegSize <- mreg + rhlp.RegSize <- 128 + rhlp.OperationSize <- effOprSz + +/// BNEv BNMv BNMib VdqEy VssHssEy VsdHsdEy +type SzVyDq () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- effOprSz + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- 128 + rhlp.OperationSize <- 128 + +/// EyVdq MibBN +type SzVyDqMR () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- effOprSz + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- 128 + rhlp.OperationSize <- effOprSz + +/// RyCd RyDd CdRy DdRy +type SzDY () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + let effRegSz = WordSize.toRegType rhlp.WordSize + rhlp.MemEffOprSize <- effOprSz + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effRegSz + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- effOprSz + +/// VdqQpi VdqNq +type SzQDq () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 64 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 64 + rhlp.RegSize <- 128 + rhlp.OperationSize <- 128 + +/// PpiWdqq +type SzDqqQ () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 64 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- 64 + rhlp.OperationSize <- 64 + +/// PpiWdq PqUdq +type SzDqQ () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 128 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- 64 + rhlp.OperationSize <- 64 + +/// GyWdqd +type SzDqdY () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 32 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- effOprSz + +/// GyWdqq +type SzDqqY () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 64 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- effOprSz + +/// GyUdq +type SzDqY () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 128 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- effOprSz + +/// UdqIb Mdq +type SzDq () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 128 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- 128 + +/// PqQd +type SzDQ () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 32 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 64 + rhlp.RegSize <- 64 + rhlp.OperationSize <- 64 + +/// PqQq PqQqIb QqPq MqPq +type SzQQ () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 64 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 64 + rhlp.RegSize <- 64 + rhlp.OperationSize <- 64 + +/// EyPq +type SzYQ () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- effOprSz + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- 64 + rhlp.OperationSize <- effOprSz + +/// PqEy +type SzYQRM () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- effOprSz + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- 64 + rhlp.OperationSize <- 64 + +/// PqEdwIb +type SzDwQ () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 16 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 32 + rhlp.RegSize <- 64 + rhlp.OperationSize <- 64 + +/// VdqEdwIb VdqHdqEdwIb +type SzDwDq () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 16 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 32 + rhlp.RegSize <- 128 + rhlp.OperationSize <- effOprSz + +/// EdwVdqIb +type SzDwDqMR () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 16 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 32 + rhlp.RegSize <- 128 + rhlp.OperationSize <- 16 + +/// GdNqIb GdNq +type SzQD () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 64 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 64 + rhlp.RegSize <- 32 + rhlp.OperationSize <- 32 + +/// GdUdqIb GdUdq +type SzDqd () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 128 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- 32 + rhlp.OperationSize <- 32 + +/// VxHxWdq +type SzXDq () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- 128 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VdqWx +type SzDqX () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- vLen + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- vLen + rhlp.RegSize <- 128 + rhlp.OperationSize <- vLen + +/// GdUx +type SzXD () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- vLen + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- vLen + rhlp.RegSize <- 32 + rhlp.OperationSize <- 32 + +/// VxWdqqdq +type SzDqqdqX () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let effAddrSz = getEffAddrSize rhlp + let vLen = (Option.get rhlp.VEXInfo).VectorLength + let struct (mopr, maddr, mreg) = + match vLen with + | 128 -> struct (64, effAddrSz, 128) + | 256 -> struct (128, effAddrSz, 128) + | _ -> Utils.futureFeature () (* EVEX *) + rhlp.MemEffOprSize <- mopr + rhlp.MemEffAddrSize <- maddr + rhlp.MemEffRegSize <- mreg + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VxWdqdq +type SzDqddqX () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let effAddrSz = getEffAddrSize rhlp + let vLen = (Option.get rhlp.VEXInfo).VectorLength + let struct (mopr, maddr, mreg) = + match vLen with + | 128 -> struct (32, effAddrSz, 128) + | 256 -> struct (64, effAddrSz, 128) + | _ -> Utils.futureFeature () (* EVEX *) + rhlp.MemEffOprSize <- mopr + rhlp.MemEffAddrSize <- maddr + rhlp.MemEffRegSize <- mreg + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VdqWdqw +type SzDqwDq () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 16 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- 128 + rhlp.OperationSize <- 128 + +/// VxWdqwd +type SzDqwX () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let effAddrSz = getEffAddrSize rhlp + let vLen = (Option.get rhlp.VEXInfo).VectorLength + let struct (mopr, maddr, mreg) = + match vLen with + | 128 -> struct (16, effAddrSz, 128) + | 256 -> struct (32, effAddrSz, 128) + | _ -> Utils.futureFeature () (* EVEX *) + rhlp.MemEffOprSize <- mopr + rhlp.MemEffAddrSize <- maddr + rhlp.MemEffRegSize <- mreg + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VqqMdq VqqHqqWdqIb +type SzDqQqq () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 128 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- 256 + rhlp.OperationSize <- 256 + +/// VxWdqb +type SzDqbX () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- 8 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VdqEdbIb VdqHdqEdbIb +type SzDbDq () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 8 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 32 + rhlp.RegSize <- 128 + rhlp.OperationSize <- 128 + +/// GvEb Mb +type SzBV () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 8 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 8 + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- effOprSz + +/// NqIb Mq +type SzQ () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 64 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 64 + rhlp.RegSize <- 64 + rhlp.OperationSize <- 64 + +/// Ms +type SzS () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let effOprSz = if rhlp.WordSize = WordSize.Bit32 then 48 else 80 + rhlp.MemEffOprSize <- effOprSz + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- effOprSz + +/// VxMd +type SzDX () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- 32 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 32 + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VZxzWdqd VxHxWdqd +type SzDqdXz () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- 32 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VxHxWdqq +type SzDqqX () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- 64 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// Ap Ep Mp +type SzP () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + let struct (regSz, oprSz) = + if effOprSz = 16 then struct (16, 32) + elif effOprSz = 32 then struct (32, 48) + else struct (64, 80) + rhlp.MemEffOprSize <- oprSz + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- regSz + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- oprSz + +/// GvMp +type SzPRM () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + let struct (regSz, oprSz) = + if effOprSz = 16 then struct (16, 32) + elif effOprSz = 32 then struct (32, 48) + else struct (64, 80) + rhlp.MemEffOprSize <- oprSz + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- regSz + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- effOprSz + +/// VZxzWxq +type SzXqXz () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let effAddrSz = getEffAddrSize rhlp + let vLen = (Option.get rhlp.VEXInfo).VectorLength + let struct (mopr, maddr, mreg) = + match vLen with + | 128 -> struct (64, effAddrSz, 128) + | 256 -> struct (128, effAddrSz, 128) + | 512 -> struct (256, effAddrSz, 256) + | _ -> raise ParsingFailureException + rhlp.MemEffOprSize <- mopr + rhlp.MemEffAddrSize <- maddr + rhlp.MemEffRegSize <- mreg + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VZxzWx +type SzXXz () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let effAddrSz = getEffAddrSize rhlp + let vLen = (Option.get rhlp.VEXInfo).VectorLength + let struct (mopr, maddr, mreg) = + match vLen with + | 128 -> struct (vLen, effAddrSz, vLen) + | 256 -> struct (128, effAddrSz, 128) + | 512 -> struct (256, effAddrSz, 256) + | _ -> raise ParsingFailureException + rhlp.MemEffOprSize <- mopr + rhlp.MemEffAddrSize <- maddr + rhlp.MemEffRegSize <- mreg + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VxWZxz +type SzXzX () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + let regSize = + match vLen with + | 128 -> vLen + | 256 -> 128 + | 512 -> 256 + | _ -> raise ParsingFailureException + rhlp.MemEffOprSize <- vLen + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- vLen + rhlp.RegSize <- regSize + rhlp.OperationSize <- regSize + +/// VZxzHxWZxz VZxzHxWZxzIb +type SzXzXz () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- vLen + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- vLen + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VqqWdqq +type SzDqqQq () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 64 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- 256 + rhlp.OperationSize <- 256 + +/// VZxzWdqq +type SzDqqXz () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- 64 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// WqqVZxz WZqqVZxzIb WqqVZxzIb +type SzQqXz () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- 256 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 256 + rhlp.RegSize <- vLen + rhlp.OperationSize <- 256 + +/// VZxzHxWqqIb +type SzQqXzRM () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- 256 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 256 + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VxWdqd +type SzDqdX () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- 32 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VZxzRd +type SzDXz () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- 32 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 32 + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// VZxzRq +type SzQXz () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- 64 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 64 + rhlp.RegSize <- vLen + rhlp.OperationSize <- vLen + +/// WdqVqqIb +type SzDqQq () = + inherit InsSizeComputer () + override __.Render rhlp _ = + rhlp.MemEffOprSize <- 128 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- 256 + rhlp.OperationSize <- 128 + +/// WdqVZxzIb +type SzDqXz () = + inherit InsSizeComputer () + override __.Render rhlp _ = + let vLen = (Option.get rhlp.VEXInfo).VectorLength + rhlp.MemEffOprSize <- 128 + rhlp.MemEffAddrSize <- getEffAddrSize rhlp + rhlp.MemEffRegSize <- 128 + rhlp.RegSize <- vLen + rhlp.OperationSize <- 128 + +/// VdqHdqEyIb +type SzYDq () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- effOprSz + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- 128 + rhlp.OperationSize <- 128 + +type SizeKind = + | Byte = 0 + | Word = 1 + | Def = 2 + | VecDef = 3 + | DV = 4 + | D = 5 + | MemW = 6 + | RegW = 7 + | WV = 8 + | D64 = 9 + | PZ = 10 + | DqDq = 11 + | DqdDq = 12 + | DqdDqMR = 13 + | DqqDq = 14 + | DqqDqMR = 15 + | XqX = 16 + | DqqDqWS = 17 + | VyDq = 18 + | VyDqMR = 19 + | DY = 20 + | QDq = 21 + | DqqQ = 22 + | DqQ = 23 + | DqdY = 24 + | DqqY = 25 + | DqY = 26 + | Dq = 27 + | DQ = 28 + | QQ = 29 + | YQ = 30 + | YQRM = 31 + | DwQ = 32 + | DwDq = 33 + | DwDqMR = 34 + | QD = 35 + | Dqd = 36 + | XDq = 37 + | DqX = 38 + | XD = 39 + | DqqdqX = 40 + | DqddqX = 41 + | DqwDq = 42 + | DqwX = 43 + | DqQqq = 44 + | DqbX = 45 + | DbDq = 46 + | BV = 47 + | Q = 48 + | S = 49 + | DX = 50 + | DqdXz = 51 + | DqqX = 52 + | P = 53 + | PRM = 54 + | XqXz = 55 + | XXz = 56 + | XzX = 57 + | XzXz = 58 + | DqqQq = 59 + | DqqXz = 60 + | QqXz = 61 + | QqXzRM = 62 + | DqdX = 63 + | DXz = 64 + | QXz = 65 + | DqQq = 66 + | DqXz = 67 + | YDq = 68 + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/Intel/IntelInstruction.fs b/src/FrontEnd/BinLifter/Intel/IntelInstruction.fs similarity index 61% rename from src/FrontEnd/Intel/IntelInstruction.fs rename to src/FrontEnd/BinLifter/Intel/IntelInstruction.fs index 5868f7e2..be32c857 100644 --- a/src/FrontEnd/Intel/IntelInstruction.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelInstruction.fs @@ -22,31 +22,28 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.Intel +namespace B2R2.FrontEnd.BinLifter.Intel open B2R2 -open B2R2.FrontEnd -open System.Text +open B2R2.FrontEnd.BinLifter + +module private Dummy = + let helper = DisasmHelper () /// The internal representation for an Intel instruction used by our /// disassembler and lifter. -type IntelInstruction (addr, numBytes, insInfo, wordSz) = - inherit Instruction (addr, numBytes, wordSz) - - let defaultCtxt = ParsingContext.Init () - - /// Basic instruction info. - member val Info: InsInfo = insInfo - - override __.NextParsingContext with get() = defaultCtxt - - override __.AuxParsingContext with get() = None +type IntelInstruction + (addr, len, wordSz, pref, rex, vex, opcode, oprs, opsz, psz) = + inherit IntelInternalInstruction + (addr, len, wordSz, pref, rex, vex, opcode, oprs, opsz, psz) override __.IsBranch () = - Helper.isBranch __.Info.Opcode + Helper.isBranch opcode + + override __.IsModeChanging () = false member __.HasConcJmpTarget () = - match __.Info.Operands with + match oprs with | OneOperand (OprDirAddr _) -> true | _ -> false @@ -57,7 +54,7 @@ type IntelInstruction (addr, numBytes, insInfo, wordSz) = __.IsBranch () && (not <| __.HasConcJmpTarget ()) override __.IsCondBranch () = - match __.Info.Opcode with + match opcode with | Opcode.JA | Opcode.JB | Opcode.JBE | Opcode.JCXZ | Opcode.JECXZ | Opcode.JG | Opcode.JL | Opcode.JLE | Opcode.JNB | Opcode.JNL | Opcode.JNO | Opcode.JNP | Opcode.JNS | Opcode.JNZ | Opcode.JO | Opcode.JP @@ -67,7 +64,7 @@ type IntelInstruction (addr, numBytes, insInfo, wordSz) = override __.IsCJmpOnTrue () = __.IsCondBranch () - && match __.Info.Opcode with + && match opcode with | Opcode.JA | Opcode.JB | Opcode.JBE | Opcode.JCXZ | Opcode.JECXZ | Opcode.JG | Opcode.JL | Opcode.JLE | Opcode.JO | Opcode.JP | Opcode.JRCXZ | Opcode.JS | Opcode.JZ | Opcode.LOOP | Opcode.LOOPE -> @@ -75,39 +72,41 @@ type IntelInstruction (addr, numBytes, insInfo, wordSz) = | _ -> false override __.IsCall () = - match __.Info.Opcode with + match opcode with | Opcode.CALLFar | Opcode.CALLNear -> true | _ -> false override __.IsRET () = - match __.Info.Opcode with + match opcode with | Opcode.RETFar | Opcode.RETFarImm | Opcode.RETNear | Opcode.RETNearImm -> true | _ -> false override __.IsInterrupt () = - match __.Info.Opcode with + match opcode with | Opcode.INT | Opcode.INT3 | Opcode.INTO | Opcode.SYSCALL | Opcode.SYSENTER -> true | _ -> false override __.IsExit () = - __.IsDirectBranch () - || __.IsIndirectBranch () - || __.Info.Opcode = Opcode.HLT - || __.Info.Opcode = Opcode.INT - || __.Info.Opcode = Opcode.INT3 - || __.Info.Opcode = Opcode.INTO - || __.Info.Opcode = Opcode.SYSCALL - || __.Info.Opcode = Opcode.SYSENTER - || __.Info.Opcode = Opcode.SYSEXIT - || __.Info.Opcode = Opcode.SYSRET - || __.Info.Opcode = Opcode.UD2 + match opcode with + (* In kernel code, HLT is often preceded by CLI to shut down the machine. + In user code, compilers insert HLT to raise a fault and exit. *) + | Opcode.HLT + | Opcode.UD2 + | Opcode.SYSEXIT | Opcode.SYSRET + | Opcode.IRET | Opcode.IRETW | Opcode.IRETD | Opcode.IRETQ -> true + | _ -> false + + override __.IsBBLEnd () = + __.IsBranch () + || __.IsInterrupt () + || __.IsExit () override __.DirectBranchTarget (addr: byref) = if __.IsBranch () then - match __.Info.Operands with - | OneOperand (OprDirAddr (Absolute (_))) -> failwith "Implement" // XXX + match oprs with + | OneOperand (OprDirAddr (Absolute (_))) -> Utils.futureFeature () | OneOperand (OprDirAddr (Relative offset)) -> addr <- (int64 __.Address + offset) |> uint64 true @@ -116,7 +115,7 @@ type IntelInstruction (addr, numBytes, insInfo, wordSz) = override __.IndirectTrampolineAddr (addr: byref) = if __.IsIndirectBranch () then - match __.Info.Operands with + match oprs with | OneOperand (OprMem (None, None, Some disp, _)) -> addr <- uint64 disp; true | OneOperand (OprMem (Some Register.RIP, None, Some disp, _)) -> @@ -125,6 +124,20 @@ type IntelInstruction (addr, numBytes, insInfo, wordSz) = | _ -> false else false + override __.Immediate (v: byref) = + match oprs with + | OneOperand (OprImm (c, _)) + | TwoOperands (OprImm (c, _), _) + | TwoOperands (_, OprImm (c, _)) + | ThreeOperands (OprImm (c, _), _, _) + | ThreeOperands (_, OprImm (c, _), _) + | ThreeOperands (_, _, OprImm (c, _)) + | FourOperands (OprImm (c, _), _, _, _) + | FourOperands (_, OprImm (c, _), _, _) + | FourOperands (_, _, OprImm (c, _), _) + | FourOperands (_, _, _, OprImm (c, _)) -> v <- c; true + | _ -> false + member private __.AddBranchTargetIfExist addrs = match __.DirectBranchTarget () |> Utils.tupleToOpt with | None -> addrs @@ -138,45 +151,43 @@ type IntelInstruction (addr, numBytes, insInfo, wordSz) = elif __.IsDirectBranch () || __.IsIndirectBranch () then if __.IsCondBranch () then acc |> __.AddBranchTargetIfExist else __.AddBranchTargetIfExist Seq.empty - elif __.Info.Opcode = Opcode.HLT then Seq.empty - elif __.Info.Opcode = Opcode.UD2 then Seq.empty + elif opcode = Opcode.HLT then Seq.empty + elif opcode = Opcode.UD2 then Seq.empty else acc override __.InterruptNum (num: byref) = - if __.Info.Opcode = Opcode.INT then - match __.Info.Operands with - | OneOperand (OprImm n) -> + if opcode = Opcode.INT then + match oprs with + | OneOperand (OprImm (n, _)) -> num <- n true | _ -> false else false override __.IsNop () = - __.Info.Opcode = Opcode.NOP + opcode = Opcode.NOP override __.Translate ctxt = - Lifter.translate __.Info addr numBytes ctxt - - member private __.StrBuilder _ (str: string) (sb: StringBuilder) = - sb.Append str + (Lifter.translate __ len ctxt).ToStmts () - override __.Disasm (showAddr, resolveSymbol, fileInfo) = - let file = if resolveSymbol then Some fileInfo else None - StringBuilder () - |> Disasm.disasm showAddr wordSz file __.Info addr numBytes __.StrBuilder - |> fun sb -> sb.ToString () + override __.Disasm (showAddr, resolveSymb, disasmHelper) = + let builder = DisasmStringBuilder (showAddr, resolveSymb, wordSz, addr, len) + Disasm.disasm disasmHelper __ builder + builder.Finalize () override __.Disasm () = - StringBuilder () - |> Disasm.disasm false wordSz None __.Info addr numBytes __.StrBuilder - |> fun sb -> sb.ToString () + let builder = DisasmStringBuilder (false, false, wordSz, addr, len) + Disasm.disasm Dummy.helper __ builder + builder.Finalize () + + override __.Decompose (showAddr) = + let builder = DisasmWordBuilder (showAddr, false, wordSz, addr, len, 8) + Disasm.disasm Dummy.helper __ builder + builder.Finalize () - member private __.WordBuilder kind str (acc: AsmWordBuilder) = - acc.Append ({ AsmWordKind = kind; AsmWordValue = str }) + override __.IsInlinedAssembly () = false - override __.Decompose () = - AsmWordBuilder (8) - |> Disasm.disasm true wordSz None __.Info addr numBytes __.WordBuilder - |> fun b -> b.Finish () + interface ICacheableOperation with + member __.Perform ctxt = (Lifter.translate __ len ctxt).ToStmts () // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Intel/IntelLifter.fs b/src/FrontEnd/BinLifter/Intel/IntelLifter.fs new file mode 100644 index 00000000..2a52680a --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelLifter.fs @@ -0,0 +1,640 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.Intel.Lifter + +open System.Collections.Concurrent +open B2R2 +open B2R2.BinIR +open B2R2.FrontEnd.BinLifter + +type OP = Opcode (* Just to make it concise. *) + +/// Translate IR. +let inline translate (ins: IntelInternalInstruction) insLen ctxt = + match ins.Opcode with + | OP.AAA -> GeneralLifter.aaa insLen ctxt + | OP.AAD -> GeneralLifter.aad ins insLen ctxt + | OP.AAM -> GeneralLifter.aam ins insLen ctxt + | OP.AAS -> GeneralLifter.aas insLen ctxt + | OP.ADC -> GeneralLifter.adc ins insLen ctxt + | OP.ADD -> GeneralLifter.add ins insLen ctxt + | OP.AND -> GeneralLifter.``and`` ins insLen ctxt + | OP.ANDN -> GeneralLifter.andn ins insLen ctxt + | OP.ARPL -> GeneralLifter.arpl ins insLen ctxt + | OP.BNDMOV -> GeneralLifter.bndmov ins insLen ctxt + | OP.BOUND -> GeneralLifter.nop insLen + | OP.BSF -> GeneralLifter.bsf ins insLen ctxt + | OP.BSR -> GeneralLifter.bsr ins insLen ctxt + | OP.BSWAP -> GeneralLifter.bswap ins insLen ctxt + | OP.BT -> GeneralLifter.bt ins insLen ctxt + | OP.BTC -> GeneralLifter.btc ins insLen ctxt + | OP.BTR -> GeneralLifter.btr ins insLen ctxt + | OP.BTS -> GeneralLifter.bts ins insLen ctxt + | OP.CALLNear -> GeneralLifter.call ins insLen ctxt + | OP.CALLFar -> LiftingUtils.sideEffects insLen UnsupportedFAR + | OP.CBW | OP.CWDE | OP.CDQE -> + GeneralLifter.convBWQ ins insLen ctxt + | OP.CLC -> GeneralLifter.clearFlag insLen ctxt R.CF + | OP.CLD -> GeneralLifter.clearFlag insLen ctxt R.DF + | OP.CLI -> GeneralLifter.clearFlag insLen ctxt R.IF + | OP.CLRSSBSY -> GeneralLifter.nop insLen + | OP.CLTS -> LiftingUtils.sideEffects insLen UnsupportedPrivInstr + | OP.CMC -> GeneralLifter.cmc ins insLen ctxt + | OP.CMOVO | OP.CMOVNO | OP.CMOVB | OP.CMOVAE + | OP.CMOVZ | OP.CMOVNZ | OP.CMOVBE | OP.CMOVA + | OP.CMOVS | OP.CMOVNS | OP.CMOVP | OP.CMOVNP + | OP.CMOVL | OP.CMOVGE | OP.CMOVLE | OP.CMOVG -> + GeneralLifter.cmovcc ins insLen ctxt + | OP.CMP -> GeneralLifter.cmp ins insLen ctxt + | OP.CMPSB | OP.CMPSW | OP.CMPSQ -> + GeneralLifter.cmps ins insLen ctxt + | OP.CMPXCHG -> GeneralLifter.cmpxchg ins insLen ctxt + | OP.CMPXCHG8B | OP.CMPXCHG16B -> + GeneralLifter.compareExchangeBytes ins insLen ctxt + | OP.CPUID -> LiftingUtils.sideEffects insLen ProcessorID + | OP.CRC32 -> GeneralLifter.nop insLen + | OP.CWD | OP.CDQ | OP.CQO -> + GeneralLifter.convWDQ ins insLen ctxt + | OP.DAA -> GeneralLifter.daa insLen ctxt + | OP.DAS -> GeneralLifter.das insLen ctxt + | OP.DEC -> GeneralLifter.dec ins insLen ctxt + | OP.DIV | OP.IDIV -> GeneralLifter.div ins insLen ctxt + | OP.ENDBR32 | OP.ENDBR64 -> GeneralLifter.nop insLen + | OP.ENTER -> GeneralLifter.enter ins insLen ctxt + | OP.HLT -> LiftingUtils.sideEffects insLen Delay + | OP.IMUL -> GeneralLifter.imul ins insLen ctxt + | OP.INC -> GeneralLifter.inc ins insLen ctxt + | OP.INCSSPD | OP.INCSSPQ -> GeneralLifter.nop insLen + | OP.INSB | OP.INSW | OP.INSD -> + GeneralLifter.insinstr ins insLen ctxt + | OP.INT | OP.INTO -> GeneralLifter.interrupt ins insLen ctxt + | OP.INT3 -> LiftingUtils.sideEffects insLen Breakpoint + | OP.JMPFar | OP.JMPNear -> GeneralLifter.jmp ins insLen ctxt + | OP.JO | OP.JNO | OP.JB | OP.JNB + | OP.JZ | OP.JNZ | OP.JBE | OP.JA + | OP.JS | OP.JNS | OP.JP | OP.JNP + | OP.JL | OP.JNL | OP.JLE | OP.JG + | OP.JECXZ | OP.JRCXZ -> GeneralLifter.jcc ins insLen ctxt + | OP.LAHF -> LiftingUtils.sideEffects insLen ProcessorID + | OP.LEA -> GeneralLifter.lea ins insLen ctxt + | OP.LEAVE -> GeneralLifter.leave ins insLen ctxt + | OP.LODSB | OP.LODSW | OP.LODSD | OP.LODSQ -> + GeneralLifter.lods ins insLen ctxt + | OP.LOOP | OP.LOOPE | OP.LOOPNE -> + GeneralLifter.loop ins insLen ctxt + | OP.LZCNT -> GeneralLifter.lzcnt ins insLen ctxt + | OP.LDS | OP.LES | OP.LFS | OP.LGS | OP.LSS -> + LiftingUtils.sideEffects insLen UnsupportedFAR + | OP.MOV -> GeneralLifter.mov ins insLen ctxt + | OP.MOVBE -> GeneralLifter.movbe ins insLen ctxt + | OP.MOVSB | OP.MOVSW | OP.MOVSQ -> + GeneralLifter.movs ins insLen ctxt + | OP.MOVSX | OP.MOVSXD -> GeneralLifter.movsx ins insLen ctxt + | OP.MOVZX -> GeneralLifter.movzx ins insLen ctxt + | OP.MUL -> GeneralLifter.mul ins insLen ctxt + | OP.NEG -> GeneralLifter.neg ins insLen ctxt + | OP.NOP -> GeneralLifter.nop insLen + | OP.NOT -> GeneralLifter.not ins insLen ctxt + | OP.OR -> GeneralLifter.logOr ins insLen ctxt + | OP.OUTSB | OP.OUTSW | OP.OUTSD -> + GeneralLifter.outs ins insLen ctxt + | OP.POP -> GeneralLifter.pop ins insLen ctxt + | OP.POPA -> GeneralLifter.popa insLen ctxt 16 + | OP.POPAD -> GeneralLifter.popa insLen ctxt 32 + | OP.POPCNT -> GeneralLifter.popcnt ins insLen ctxt + | OP.POPF | OP.POPFD | OP.POPFQ -> + GeneralLifter.popf ins insLen ctxt + | OP.PUSH -> GeneralLifter.push ins insLen ctxt + | OP.PUSHA -> GeneralLifter.pusha ins insLen ctxt 16 + | OP.PUSHAD -> GeneralLifter.pusha ins insLen ctxt 32 + | OP.PUSHF | OP.PUSHFD | OP.PUSHFQ -> + GeneralLifter.pushf ins insLen ctxt + | OP.RCL -> GeneralLifter.rcl ins insLen ctxt + | OP.RCR -> GeneralLifter.rcr ins insLen ctxt + | OP.RDMSR | OP.RSM -> + LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.RDPKRU -> GeneralLifter.rdpkru ins insLen ctxt + | OP.RDPMC -> LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.RDRAND -> LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.RDSSPD | OP.RDSSPQ -> GeneralLifter.nop insLen + | OP.RDTSC -> LiftingUtils.sideEffects insLen ClockCounter + | OP.RDTSCP -> LiftingUtils.sideEffects insLen ClockCounter + | OP.RETNear -> GeneralLifter.ret ins insLen ctxt + | OP.RETNearImm -> GeneralLifter.retWithImm ins insLen ctxt + | OP.RETFar -> LiftingUtils.sideEffects insLen UnsupportedFAR + | OP.RETFarImm -> LiftingUtils.sideEffects insLen UnsupportedFAR + | OP.ROL -> GeneralLifter.rol ins insLen ctxt + | OP.ROR -> GeneralLifter.ror ins insLen ctxt + | OP.RORX -> GeneralLifter.rorx ins insLen ctxt + | OP.RSTORSSP -> GeneralLifter.nop insLen + | OP.SAHF -> GeneralLifter.sahf ins insLen ctxt + | OP.SAR | OP.SHR | OP.SHL -> + GeneralLifter.shift ins insLen ctxt + | OP.SAVEPREVSSP -> GeneralLifter.nop insLen + | OP.SBB -> GeneralLifter.sbb ins insLen ctxt + | OP.SCASB | OP.SCASW | OP.SCASD | OP.SCASQ -> + GeneralLifter.scas ins insLen ctxt + | OP.SETO | OP.SETNO | OP.SETB | OP.SETNB + | OP.SETZ | OP.SETNZ | OP.SETBE | OP.SETA + | OP.SETS | OP.SETNS | OP.SETP | OP.SETNP + | OP.SETL | OP.SETNL | OP.SETLE | OP.SETG -> + GeneralLifter.setcc ins insLen ctxt + | OP.SETSSBSY -> GeneralLifter.nop insLen + | OP.SHLD -> GeneralLifter.shld ins insLen ctxt + | OP.SHLX -> GeneralLifter.shlx ins insLen ctxt + | OP.SHRD -> GeneralLifter.shrd ins insLen ctxt + | OP.STC -> GeneralLifter.stc insLen ctxt + | OP.STD -> GeneralLifter.std insLen ctxt + | OP.STI -> GeneralLifter.sti insLen ctxt + | OP.STOSB | OP.STOSW | OP.STOSD | OP.STOSQ -> + GeneralLifter.stos ins insLen ctxt + | OP.SUB -> GeneralLifter.sub ins insLen ctxt + | OP.SYSCALL | OP.SYSENTER -> LiftingUtils.sideEffects insLen SysCall + | OP.SYSEXIT | OP.SYSRET -> + LiftingUtils.sideEffects insLen UnsupportedPrivInstr + | OP.TEST -> GeneralLifter.test ins insLen ctxt + | OP.TZCNT -> GeneralLifter.tzcnt ins insLen ctxt + | OP.UD2 -> LiftingUtils.sideEffects insLen UndefinedInstr + | OP.WBINVD -> LiftingUtils.sideEffects insLen UnsupportedPrivInstr + | OP.WRFSBASE -> GeneralLifter.wrfsbase ins insLen ctxt + | OP.WRGSBASE -> GeneralLifter.wrgsbase ins insLen ctxt + | OP.WRPKRU -> GeneralLifter.wrpkru ins insLen ctxt + | OP.WRMSR -> LiftingUtils.sideEffects insLen UnsupportedPrivInstr + | OP.WRSSD | OP.WRSSQ -> GeneralLifter.nop insLen + | OP.WRUSSD | OP.WRUSSQ -> GeneralLifter.nop insLen + | OP.XABORT -> LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.XADD -> GeneralLifter.xadd ins insLen ctxt + | OP.XBEGIN -> LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.XCHG -> GeneralLifter.xchg ins insLen ctxt + | OP.XEND -> LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.XGETBV -> LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.XLATB -> GeneralLifter.xlatb ins insLen ctxt + | OP.XOR -> GeneralLifter.xor ins insLen ctxt + | OP.XRSTOR | OP.XRSTORS | OP.XSAVE | OP.XSAVEC + | OP.XSAVEC64 | OP.XSAVEOPT | OP.XSAVES | OP.XSAVES64 -> + LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.XTEST -> LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.IN | OP.INVD | OP.INVLPG | OP.IRET | OP.IRETQ | OP.IRETW | OP.IRETD + | OP.LAR | OP.LGDT | OP.LIDT | OP.LLDT + | OP.LMSW | OP.LSL | OP.LTR | OP.OUT | OP.SGDT + | OP.SIDT | OP.SLDT | OP.SMSW | OP.STR | OP.VERR -> + LiftingUtils.sideEffects insLen UnsupportedPrivInstr + | OP.MOVD -> MMXLifter.movd ins insLen ctxt + | OP.MOVQ -> MMXLifter.movq ins insLen ctxt + | OP.PACKSSDW -> MMXLifter.packssdw ins insLen ctxt + | OP.PACKSSWB -> MMXLifter.packsswb ins insLen ctxt + | OP.PACKUSWB -> MMXLifter.packuswb ins insLen ctxt + | OP.PUNPCKHBW -> MMXLifter.punpckhbw ins insLen ctxt + | OP.PUNPCKHWD -> MMXLifter.punpckhwd ins insLen ctxt + | OP.PUNPCKHDQ -> MMXLifter.punpckhdq ins insLen ctxt + | OP.PUNPCKLBW -> MMXLifter.punpcklbw ins insLen ctxt + | OP.PUNPCKLWD -> MMXLifter.punpcklwd ins insLen ctxt + | OP.PUNPCKLDQ -> MMXLifter.punpckldq ins insLen ctxt + | OP.PADDB -> MMXLifter.paddb ins insLen ctxt + | OP.PADDW -> MMXLifter.paddw ins insLen ctxt + | OP.PADDD -> MMXLifter.paddd ins insLen ctxt + | OP.PADDSB -> MMXLifter.paddsb ins insLen ctxt + | OP.PADDSW -> MMXLifter.paddsw ins insLen ctxt + | OP.PADDUSB -> MMXLifter.paddusb ins insLen ctxt + | OP.PADDUSW -> MMXLifter.paddusw ins insLen ctxt + | OP.PSUBB -> MMXLifter.psubb ins insLen ctxt + | OP.PSUBW -> MMXLifter.psubw ins insLen ctxt + | OP.PSUBD -> MMXLifter.psubd ins insLen ctxt + | OP.PSUBSB -> MMXLifter.psubsb ins insLen ctxt + | OP.PSUBSW -> MMXLifter.psubsw ins insLen ctxt + | OP.PSUBUSB -> MMXLifter.psubusb ins insLen ctxt + | OP.PSUBUSW -> MMXLifter.psubusw ins insLen ctxt + | OP.PMULHW -> MMXLifter.pmulhw ins insLen ctxt + | OP.PMULLW -> MMXLifter.pmullw ins insLen ctxt + | OP.PMADDWD -> MMXLifter.pmaddwd ins insLen ctxt + | OP.PCMPEQB -> MMXLifter.pcmpeqb ins insLen ctxt + | OP.PCMPEQW -> MMXLifter.pcmpeqw ins insLen ctxt + | OP.PCMPEQD -> MMXLifter.pcmpeqd ins insLen ctxt + | OP.PCMPGTB -> MMXLifter.pcmpgtb ins insLen ctxt + | OP.PCMPGTW -> MMXLifter.pcmpgtw ins insLen ctxt + | OP.PCMPGTD -> MMXLifter.pcmpgtd ins insLen ctxt + | OP.PAND -> MMXLifter.pand ins insLen ctxt + | OP.PANDN -> MMXLifter.pandn ins insLen ctxt + | OP.POR -> MMXLifter.por ins insLen ctxt + | OP.PXOR -> MMXLifter.pxor ins insLen ctxt + | OP.PSLLW -> MMXLifter.psllw ins insLen ctxt + | OP.PSLLD -> MMXLifter.pslld ins insLen ctxt + | OP.PSLLQ -> MMXLifter.psllq ins insLen ctxt + | OP.PSRLW -> MMXLifter.psrlw ins insLen ctxt + | OP.PSRLD -> MMXLifter.psrld ins insLen ctxt + | OP.PSRLQ -> MMXLifter.psrlq ins insLen ctxt + | OP.PSRAW -> MMXLifter.psraw ins insLen ctxt + | OP.PSRAD -> MMXLifter.psrad ins insLen ctxt + | OP.EMMS -> MMXLifter.emms ins insLen ctxt + | OP.MOVAPS -> SSELifter.movaps ins insLen ctxt + | OP.MOVAPD -> SSELifter.movapd ins insLen ctxt (* SSE2 *) + | OP.MOVUPS -> SSELifter.movups ins insLen ctxt + | OP.MOVUPD -> SSELifter.movupd ins insLen ctxt (* SSE2 *) + | OP.MOVHPS -> SSELifter.movhps ins insLen ctxt + | OP.MOVHPD -> SSELifter.movhpd ins insLen ctxt (* SSE2 *) + | OP.MOVHLPS -> SSELifter.movhlps ins insLen ctxt + | OP.MOVLPS -> SSELifter.movlps ins insLen ctxt + | OP.MOVLPD -> SSELifter.movlpd ins insLen ctxt (* SSE2 *) + | OP.MOVLHPS -> SSELifter.movlhps ins insLen ctxt + | OP.MOVMSKPS -> SSELifter.movmskps ins insLen ctxt + | OP.MOVMSKPD -> SSELifter.movmskpd ins insLen ctxt (* SSE2 *) + | OP.MOVSS -> SSELifter.movss ins insLen ctxt + | OP.MOVSD -> SSELifter.movsd ins insLen ctxt (* SSE2 *) + | OP.ADDPS -> SSELifter.addps ins insLen ctxt + | OP.ADDPD -> SSELifter.addpd ins insLen ctxt (* SSE2 *) + | OP.ADDSS -> SSELifter.addss ins insLen ctxt + | OP.ADDSD -> SSELifter.addsd ins insLen ctxt (* SSE2 *) + | OP.SUBPS -> SSELifter.subps ins insLen ctxt + | OP.SUBPD -> SSELifter.subpd ins insLen ctxt (* SSE2 *) + | OP.SUBSS -> SSELifter.subss ins insLen ctxt + | OP.SUBSD -> SSELifter.subsd ins insLen ctxt (* SSE2 *) + | OP.MULPS -> SSELifter.mulps ins insLen ctxt + | OP.MULPD -> SSELifter.mulpd ins insLen ctxt (* SSE2 *) + | OP.MULSS -> SSELifter.mulss ins insLen ctxt + | OP.MULSD -> SSELifter.mulsd ins insLen ctxt (* SSE2 *) + | OP.DIVPS -> SSELifter.divps ins insLen ctxt + | OP.DIVPD -> SSELifter.divpd ins insLen ctxt (* SSE2 *) + | OP.DIVSS -> SSELifter.divss ins insLen ctxt + | OP.DIVSD -> SSELifter.divsd ins insLen ctxt (* SSE2 *) + | OP.RCPPS -> SSELifter.rcpps ins insLen ctxt + | OP.RCPSS -> SSELifter.rcpss ins insLen ctxt + | OP.SQRTPS -> SSELifter.sqrtps ins insLen ctxt + | OP.SQRTPD -> SSELifter.sqrtpd ins insLen ctxt (* SSE2 *) + | OP.SQRTSS -> SSELifter.sqrtss ins insLen ctxt + | OP.SQRTSD -> SSELifter.sqrtsd ins insLen ctxt (* SSE2 *) + | OP.RSQRTPS -> SSELifter.rsqrtps ins insLen ctxt + | OP.RSQRTSS -> SSELifter.rsqrtss ins insLen ctxt + | OP.MAXPS -> SSELifter.maxps ins insLen ctxt + | OP.MAXPD -> SSELifter.maxpd ins insLen ctxt (* SSE2 *) + | OP.MAXSS -> SSELifter.maxss ins insLen ctxt + | OP.MAXSD -> SSELifter.maxsd ins insLen ctxt (* SSE2 *) + | OP.MINPS -> SSELifter.minps ins insLen ctxt + | OP.MINPD -> SSELifter.minpd ins insLen ctxt (* SSE2 *) + | OP.MINSS -> SSELifter.minss ins insLen ctxt + | OP.MINSD -> SSELifter.minsd ins insLen ctxt (* SSE2 *) + | OP.CMPPS -> SSELifter.cmpps ins insLen ctxt + | OP.CMPPD -> SSELifter.cmppd ins insLen ctxt (* SSE2 *) + | OP.CMPSS -> SSELifter.cmpss ins insLen ctxt + | OP.CMPSD -> SSELifter.cmpsd ins insLen ctxt (* SSE2 *) + | OP.COMISS | OP.VCOMISS -> + SSELifter.comiss ins insLen ctxt + | OP.COMISD | OP.VCOMISD -> (* SSE2 *) + SSELifter.comisd ins insLen ctxt + | OP.UCOMISS | OP.VUCOMISS -> + SSELifter.ucomiss ins insLen ctxt + | OP.UCOMISD | OP.VUCOMISD -> (* SSE2 *) + SSELifter.ucomisd ins insLen ctxt + | OP.ANDPS -> SSELifter.andps ins insLen ctxt + | OP.ANDPD -> SSELifter.andpd ins insLen ctxt (* SSE2 *) + | OP.ANDNPS -> SSELifter.andnps ins insLen ctxt + | OP.ANDNPD -> SSELifter.andnpd ins insLen ctxt (* SSE2 *) + | OP.ORPS -> SSELifter.orps ins insLen ctxt + | OP.ORPD -> SSELifter.orpd ins insLen ctxt (* SSE2 *) + | OP.XORPS -> SSELifter.xorps ins insLen ctxt + | OP.XORPD -> SSELifter.xorpd ins insLen ctxt (* SSE2 *) + | OP.XSETBV -> LiftingUtils.sideEffects insLen UnsupportedPrivInstr + | OP.SHUFPS -> SSELifter.shufps ins insLen ctxt + | OP.SHUFPD -> SSELifter.shufpd ins insLen ctxt (* SSE2 *) + | OP.UNPCKHPS -> SSELifter.unpckhps ins insLen ctxt + | OP.UNPCKHPD -> SSELifter.unpckhpd ins insLen ctxt (* SSE2 *) + | OP.UNPCKLPS -> SSELifter.unpcklps ins insLen ctxt + | OP.UNPCKLPD -> SSELifter.unpcklpd ins insLen ctxt (* SSE2 *) + | OP.CVTPI2PS -> SSELifter.cvtpi2ps ins insLen ctxt + | OP.CVTPI2PD -> SSELifter.cvtpi2pd ins insLen ctxt (* SSE2 *) + | OP.CVTSI2SS -> SSELifter.cvtsi2ss ins insLen ctxt + | OP.CVTSI2SD -> SSELifter.cvtsi2sd ins insLen ctxt (* SSE2 *) + | OP.CVTPS2PI -> SSELifter.cvtps2pi ins insLen ctxt true + | OP.CVTPS2PD -> SSELifter.cvtps2pd ins insLen ctxt (* SSE2 *) + | OP.CVTPD2PS -> SSELifter.cvtpd2ps ins insLen ctxt (* SSE2 *) + | OP.CVTPD2PI -> SSELifter.cvtpd2pi ins insLen ctxt true (* SSE2 *) + | OP.CVTPD2DQ -> SSELifter.cvtpd2dq ins insLen ctxt true (* SSE2 *) + | OP.CVTTPD2DQ -> SSELifter.cvtpd2dq ins insLen ctxt false (* SSE2 *) + | OP.CVTDQ2PS -> SSELifter.cvtdq2ps ins insLen ctxt (* SSE2 *) + | OP.CVTDQ2PD -> SSELifter.cvtdq2pd ins insLen ctxt (* SSE2 *) + | OP.CVTPS2DQ -> SSELifter.cvtps2dq ins insLen ctxt true (* SSE2 *) + | OP.CVTTPS2DQ -> SSELifter.cvtps2dq ins insLen ctxt false (* SSE2 *) + | OP.CVTTPS2PI -> SSELifter.cvtps2pi ins insLen ctxt false + | OP.CVTTPD2PI -> SSELifter.cvtpd2pi ins insLen ctxt false (* SSE2 *) + | OP.CVTSS2SI | OP.VCVTSS2SI -> + SSELifter.cvtss2si ins insLen ctxt true + | OP.CVTSS2SD -> SSELifter.cvtss2sd ins insLen ctxt (* SSE2 *) + | OP.CVTSD2SS -> SSELifter.cvtsd2ss ins insLen ctxt (* SSE2 *) + | OP.CVTSD2SI | OP.VCVTSD2SI -> (* SSE2 *) + SSELifter.cvtsd2si ins insLen ctxt true + | OP.CVTTSS2SI | OP.VCVTTSS2SI -> + SSELifter.cvtss2si ins insLen ctxt false + | OP.CVTTSD2SI | OP.VCVTTSD2SI -> (* SSE2 *) + SSELifter.cvtsd2si ins insLen ctxt false + | OP.LDMXCSR -> SSELifter.ldmxcsr ins insLen ctxt + | OP.STMXCSR -> SSELifter.stmxcsr ins insLen ctxt + | OP.PAVGB -> SSELifter.pavgb ins insLen ctxt + | OP.PAVGW -> SSELifter.pavgw ins insLen ctxt + | OP.PEXTRW -> SSELifter.pextrw ins insLen ctxt + | OP.PINSRW -> SSELifter.pinsrw ins insLen ctxt + | OP.PMAXUB -> SSELifter.pmaxub ins insLen ctxt + | OP.PMAXSW -> SSELifter.pmaxsw ins insLen ctxt + | OP.PMAXSB -> SSELifter.pmaxsb ins insLen ctxt (* SSE4 *) + | OP.PMINUB -> SSELifter.pminub ins insLen ctxt + | OP.PMINSW -> SSELifter.pminsw ins insLen ctxt + | OP.PMINUD -> SSELifter.pminud ins insLen ctxt (* SSE4 *) + | OP.PMINSB -> SSELifter.pminsb ins insLen ctxt (* SSE4 *) + | OP.PMOVMSKB -> SSELifter.pmovmskb ins insLen ctxt + | OP.PMULHUW -> SSELifter.pmulhuw ins insLen ctxt + | OP.PSADBW -> SSELifter.psadbw ins insLen ctxt + | OP.PSHUFW -> SSELifter.pshufw ins insLen ctxt + | OP.PSHUFD -> SSELifter.pshufd ins insLen ctxt (* SSE2 *) + | OP.PSHUFLW -> SSELifter.pshuflw ins insLen ctxt (* SSE2 *) + | OP.PSHUFHW -> SSELifter.pshufhw ins insLen ctxt (* SSE2 *) + | OP.PSHUFB -> SSELifter.pshufb ins insLen ctxt (* SSE3 *) + | OP.MOVDQA -> SSELifter.movdqa ins insLen ctxt (* SSE2 *) + | OP.MOVDQU -> SSELifter.movdqu ins insLen ctxt (* SSE2 *) + | OP.MOVQ2DQ -> SSELifter.movq2dq ins insLen ctxt (* SSE2 *) + | OP.MOVDQ2Q -> SSELifter.movdq2q ins insLen ctxt (* SSE2 *) + | OP.PMULUDQ -> SSELifter.pmuludq ins insLen ctxt (* SSE2 *) + | OP.PADDQ -> SSELifter.paddq ins insLen ctxt (* SSE2 *) + | OP.PSUBQ -> SSELifter.psubq ins insLen ctxt (* SSE2 *) + | OP.PSLLDQ -> SSELifter.pslldq ins insLen ctxt (* SSE2 *) + | OP.PSRLDQ -> SSELifter.psrldq ins insLen ctxt (* SSE2 *) + | OP.PUNPCKHQDQ -> SSELifter.punpckhqdq ins insLen ctxt (* SSE2 *) + | OP.PUNPCKLQDQ -> SSELifter.punpcklqdq ins insLen ctxt (* SSE2 *) + | OP.MOVNTQ -> SSELifter.movntq ins insLen ctxt + | OP.MOVNTPS -> SSELifter.movntps ins insLen ctxt + | OP.PREFETCHNTA + | OP.PREFETCHT0 | OP.PREFETCHT1 + | OP.PREFETCHW | OP.PREFETCHT2 -> GeneralLifter.nop insLen + | OP.SFENCE -> LiftingUtils.sideEffects insLen Fence + | OP.CLFLUSH -> GeneralLifter.nop insLen (* SSE2 *) + | OP.LFENCE -> LiftingUtils.sideEffects insLen Fence (* SSE2 *) + | OP.MFENCE -> LiftingUtils.sideEffects insLen Fence (* SSE2 *) + | OP.PAUSE -> LiftingUtils.sideEffects insLen Delay (* SSE2 *) + | OP.MOVNTPD -> SSELifter.movntpd ins insLen ctxt (* SSE2 *) + | OP.MOVNTDQ -> SSELifter.movntdq ins insLen ctxt (* SSE2 *) + | OP.MOVNTI -> SSELifter.movnti ins insLen ctxt (* SSE2 *) + | OP.LDDQU -> SSELifter.lddqu ins insLen ctxt (* SSE3 *) + | OP.MOVSHDUP -> SSELifter.movshdup ins insLen ctxt (* SSE3 *) + | OP.MOVSLDUP -> SSELifter.movsldup ins insLen ctxt (* SSE3 *) + | OP.MOVDDUP -> SSELifter.movddup ins insLen ctxt (* SSE3 *) + | OP.PALIGNR -> SSELifter.palignr ins insLen ctxt (* SSE3 *) + | OP.ROUNDSD -> SSELifter.roundsd ins insLen ctxt (* SSE4 *) + | OP.PINSRB -> SSELifter.pinsrb ins insLen ctxt (* SSE4 *) + | OP.PTEST -> SSELifter.ptest ins insLen ctxt (* SSE4 *) + | OP.PCMPEQQ -> SSELifter.pcmpeqq ins insLen ctxt (* SSE4 *) + | OP.PCMPESTRI | OP.PCMPESTRM | OP.PCMPISTRI | OP.PCMPISTRM -> + SSELifter.pcmpstr ins insLen ctxt (* SSE4 *) + | OP.VSQRTPS -> AVXLifter.vsqrtps ins insLen ctxt + | OP.VSQRTPD -> AVXLifter.vsqrtpd ins insLen ctxt + | OP.VSQRTSS -> AVXLifter.vsqrtss ins insLen ctxt + | OP.VSQRTSD -> AVXLifter.vsqrtsd ins insLen ctxt + | OP.VADDPS -> AVXLifter.vaddps ins insLen ctxt + | OP.VADDPD -> AVXLifter.vaddpd ins insLen ctxt + | OP.VADDSS -> AVXLifter.vaddss ins insLen ctxt + | OP.VADDSD -> AVXLifter.vaddsd ins insLen ctxt + | OP.VSUBPS -> AVXLifter.vsubps ins insLen ctxt + | OP.VSUBPD -> AVXLifter.vsubpd ins insLen ctxt + | OP.VSUBSS -> AVXLifter.vsubss ins insLen ctxt + | OP.VSUBSD -> AVXLifter.vsubsd ins insLen ctxt + | OP.VMULPS -> AVXLifter.vmulps ins insLen ctxt + | OP.VMULPD -> AVXLifter.vmulpd ins insLen ctxt + | OP.VMULSS -> AVXLifter.vmulss ins insLen ctxt + | OP.VMULSD -> AVXLifter.vmulsd ins insLen ctxt + | OP.VDIVPS -> AVXLifter.vdivps ins insLen ctxt + | OP.VDIVPD -> AVXLifter.vdivpd ins insLen ctxt + | OP.VDIVSS -> AVXLifter.vdivss ins insLen ctxt + | OP.VDIVSD -> AVXLifter.vdivsd ins insLen ctxt + | OP.VCVTSI2SS -> AVXLifter.vcvtsi2ss ins insLen ctxt + | OP.VCVTSI2SD -> AVXLifter.vcvtsi2sd ins insLen ctxt + | OP.VCVTSD2SS -> AVXLifter.vcvtsd2ss ins insLen ctxt + | OP.VCVTSS2SD -> AVXLifter.vcvtss2sd ins insLen ctxt + | OP.VMOVD -> AVXLifter.vmovd ins insLen ctxt + | OP.VMOVQ -> AVXLifter.vmovq ins insLen ctxt + | OP.VMOVAPS -> AVXLifter.vmovdqu ins insLen ctxt + | OP.VMOVAPD -> AVXLifter.vmovdqu ins insLen ctxt + | OP.VMOVDQU -> AVXLifter.vmovdqu ins insLen ctxt + | OP.VMOVDQU16 -> AVXLifter.vmovdqu16 ins insLen ctxt + | OP.VMOVDQU64 -> AVXLifter.vmovdqu64 ins insLen ctxt + | OP.VMOVDQA -> AVXLifter.vmovdqa ins insLen ctxt + | OP.VMOVDQA64 -> AVXLifter.vmovdqa64 ins insLen ctxt + | OP.VMOVNTDQ -> AVXLifter.vmovntdq ins insLen ctxt + | OP.VMOVUPS -> AVXLifter.vmovups ins insLen ctxt + | OP.VMOVUPD -> AVXLifter.vmovupd ins insLen ctxt + | OP.VMOVDDUP -> AVXLifter.vmovddup ins insLen ctxt + | OP.VMOVNTPS -> AVXLifter.vmovntps ins insLen ctxt + | OP.VMOVNTPD -> AVXLifter.vmovntpd ins insLen ctxt + | OP.VMOVHLPS -> AVXLifter.vmovhlps ins insLen ctxt + | OP.VMOVHPD | OP.VMOVHPS -> AVXLifter.vmovhpd ins insLen ctxt + | OP.VMOVLHPS -> AVXLifter.vmovlhps ins insLen ctxt + | OP.VMOVLPD | OP.VMOVLPS -> AVXLifter.vmovlpd ins insLen ctxt + | OP.VMOVMSKPD -> AVXLifter.vmovmskpd ins insLen ctxt + | OP.VMOVMSKPS -> AVXLifter.vmovmskps ins insLen ctxt + | OP.VMOVSD -> AVXLifter.vmovsd ins insLen ctxt + | OP.VMOVSHDUP -> AVXLifter.vmovshdup ins insLen ctxt + | OP.VMOVSLDUP -> AVXLifter.vmovsldup ins insLen ctxt + | OP.VMOVSS -> AVXLifter.vmovss ins insLen ctxt + | OP.VANDPS -> AVXLifter.vandps ins insLen ctxt + | OP.VANDPD -> AVXLifter.vandpd ins insLen ctxt + | OP.VANDNPS -> AVXLifter.vandnps ins insLen ctxt + | OP.VANDNPD -> AVXLifter.vandnpd ins insLen ctxt + | OP.VORPS -> AVXLifter.vorps ins insLen ctxt + | OP.VORPD -> AVXLifter.vorpd ins insLen ctxt + | OP.VSHUFI32X4 -> AVXLifter.vshufi32x4 ins insLen ctxt + | OP.VSHUFPS -> AVXLifter.vshufps ins insLen ctxt + | OP.VSHUFPD -> AVXLifter.vshufpd ins insLen ctxt + | OP.VUNPCKHPS -> AVXLifter.vunpckhps ins insLen ctxt + | OP.VUNPCKHPD -> AVXLifter.vunpckhpd ins insLen ctxt + | OP.VUNPCKLPS -> AVXLifter.vunpcklps ins insLen ctxt + | OP.VUNPCKLPD -> AVXLifter.vunpcklpd ins insLen ctxt + | OP.VXORPS -> AVXLifter.vxorps ins insLen ctxt + | OP.VXORPD -> AVXLifter.vxorpd ins insLen ctxt + | OP.VBROADCASTI128 -> AVXLifter.vbroadcasti128 ins insLen ctxt + | OP.VBROADCASTSS -> AVXLifter.vbroadcastss ins insLen ctxt + | OP.VEXTRACTF32X8 -> AVXLifter.vextracti32x8 ins insLen ctxt + | OP.VEXTRACTI64X4 -> AVXLifter.vextracti64x4 ins insLen ctxt + | OP.VINSERTI128 -> AVXLifter.vinserti128 ins insLen ctxt + | OP.VMPTRLD -> LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.VPADDB -> AVXLifter.vpaddb ins insLen ctxt + | OP.VPADDD -> AVXLifter.vpaddd ins insLen ctxt + | OP.VPADDQ -> AVXLifter.vpaddq ins insLen ctxt + | OP.VPALIGNR -> AVXLifter.vpalignr ins insLen ctxt + | OP.VPAND -> AVXLifter.vpand ins insLen ctxt + | OP.VPANDN -> AVXLifter.vpandn ins insLen ctxt + | OP.VPBROADCASTB -> AVXLifter.vpbroadcastb ins insLen ctxt + | OP.VPBROADCASTD -> AVXLifter.vpbroadcastd ins insLen ctxt + | OP.VPCMPEQB -> AVXLifter.vpcmpeqb ins insLen ctxt + | OP.VPCMPEQD -> AVXLifter.vpcmpeqd ins insLen ctxt + | OP.VPCMPEQQ -> AVXLifter.vpcmpeqq ins insLen ctxt + | OP.VPCMPESTRI | OP.VPCMPESTRM | OP.VPCMPISTRI + | OP.VPCMPISTRM -> SSELifter.pcmpstr ins insLen ctxt + | OP.VPCMPGTB -> AVXLifter.vpcmpgtb ins insLen ctxt + | OP.VPINSRD -> AVXLifter.vpinsrd ins insLen ctxt + | OP.VPMINUB -> AVXLifter.vpminub ins insLen ctxt + | OP.VPMINUD -> AVXLifter.vpminud ins insLen ctxt + | OP.VPMOVMSKB -> SSELifter.pmovmskb ins insLen ctxt + | OP.VPMULUDQ -> AVXLifter.vpmuludq ins insLen ctxt + | OP.VPOR -> AVXLifter.vpor ins insLen ctxt + | OP.VPSHUFB -> AVXLifter.vpshufb ins insLen ctxt + | OP.VPSHUFD -> AVXLifter.vpshufd ins insLen ctxt + | OP.VPSLLD -> AVXLifter.vpslld ins insLen ctxt + | OP.VPSLLDQ -> AVXLifter.vpslldq ins insLen ctxt + | OP.VPSLLQ -> AVXLifter.vpsllq ins insLen ctxt + | OP.VPSRLD -> AVXLifter.vpsrld ins insLen ctxt + | OP.VPSRLDQ -> AVXLifter.vpsrldq ins insLen ctxt + | OP.VPSRLQ -> AVXLifter.vpsrlq ins insLen ctxt + | OP.VPSUBB -> AVXLifter.vpsubb ins insLen ctxt + | OP.VPTEST -> AVXLifter.vptest ins insLen ctxt + | OP.VPUNPCKHDQ -> AVXLifter.vpunpckhdq ins insLen ctxt + | OP.VPUNPCKHQDQ -> AVXLifter.vpunpckhqdq ins insLen ctxt + | OP.VPUNPCKLDQ -> AVXLifter.vpunpckldq ins insLen ctxt + | OP.VPUNPCKLQDQ -> AVXLifter.vpunpcklqdq ins insLen ctxt + | OP.VPXOR -> AVXLifter.vpxor ins insLen ctxt + | OP.VPXORD -> AVXLifter.vpxord ins insLen ctxt + | OP.VZEROUPPER -> AVXLifter.vzeroupper ins insLen ctxt + | OP.VINSERTI64X4 + | OP.VPMOVWB | OP.VMOVDQU32 | OP.VPMOVZXWD + | OP.VPSRLW | OP.VFMADD213SS -> + GeneralLifter.nop insLen (* FIXME: #196 *) + | OP.VERW -> LiftingUtils.sideEffects insLen UnsupportedPrivInstr + | OP.VFMADD132SD -> AVXLifter.vfmadd132sd ins insLen ctxt + | OP.VFMADD213SD -> AVXLifter.vfmadd213sd ins insLen ctxt + | OP.VFMADD231SD -> AVXLifter.vfmadd231sd ins insLen ctxt + | OP.VBROADCASTSD | OP.VCVTDQ2PD | OP.VCVTPD2PS + | OP.VCVTPS2PD | OP.VEXTRACTF64X2 | OP.VEXTRACTF64X4 + | OP.VFMADD132PD | OP.VFMADD213PS | OP.VFMADD231PD + | OP.VFMSUB132SS | OP.VFMSUB231SD | OP.VFNMADD132PD + | OP.VFNMADD231PD | OP.VFNMADD132SD | OP.VFNMADD213SD + | OP.VFNMADD231SD | OP.VINSERTF128 | OP.VINSERTF64X4 + | OP.VMAXPS | OP.VMAXSD | OP.VMAXSS | OP.VMINSS + | OP.VPERMI2D | OP.VPERMI2PD | OP.VPERMI2W | OP.VPMOVWB + | OP.VPTERNLOGD | OP.VCMPPD | OP.VCMPPS | OP.VGATHERDPS + | OP.VPGATHERDD | OP.VMOVDQU8 -> + GeneralLifter.nop insLen (* FIXME: #196 !211 *) + | OP.VRSQRTSS | OP.VFMSUB213SD | OP.VRSQRT28SD | OP.VRCP28SD | OP.VPEXTRD + | OP.VFMADD213PD | OP.VPBROADCASTQ | OP.VPSUBW | OP.VFMSUB213PD | OP.VPSUBD + | OP.VRCPSS | OP.VGETMANTSD | OP.VGETEXPSD | OP.VRCP14SD | OP.VRNDSCALESD + | OP.VEXTRACTF128 -> GeneralLifter.nop insLen (* FIXME: #277 *) + | OP.VPCMPGTD | OP.MULX | OP.VREDUCESD | OP.VROUNDPD | OP.VMINPD | OP.VRSQRTPS + | OP.VBLENDVPD | OP.VFNMADD213PD | OP.VFMSUB231PD | OP.BLENDVPD | OP.ROUNDPD + | OP.VRCPPS | OP.VGATHERQPD | OP.VPSRAD | OP.VCVTDQ2PS | OP.VCVTTPD2DQ + | OP.VPMULLD | OP.PMULLD | OP.VROUNDPS | OP.ROUNDPS -> + GeneralLifter.nop insLen (* FIXME: #279 *) + | OP.FLD -> X87Lifter.fld ins insLen ctxt + | OP.FST -> X87Lifter.ffst ins insLen ctxt false + | OP.FSTP -> X87Lifter.ffst ins insLen ctxt true + | OP.FILD -> X87Lifter.fild ins insLen ctxt + | OP.FIST -> X87Lifter.fist ins insLen ctxt false + | OP.FISTP -> X87Lifter.fist ins insLen ctxt true + | OP.FISTTP -> X87Lifter.fisttp ins insLen ctxt (* SSE3 *) + | OP.FBLD -> X87Lifter.fbld ins insLen ctxt + | OP.FBSTP -> X87Lifter.fbstp ins insLen ctxt + | OP.FXCH -> X87Lifter.fxch ins insLen ctxt + | OP.FCMOVE -> X87Lifter.fcmove ins insLen ctxt + | OP.FCMOVNE -> X87Lifter.fcmovne ins insLen ctxt + | OP.FCMOVB -> X87Lifter.fcmovb ins insLen ctxt + | OP.FCMOVBE -> X87Lifter.fcmovbe ins insLen ctxt + | OP.FCMOVNB -> X87Lifter.fcmovnb ins insLen ctxt + | OP.FCMOVNBE -> X87Lifter.fcmovnbe ins insLen ctxt + | OP.FCMOVU -> X87Lifter.fcmovu ins insLen ctxt + | OP.FCMOVNU -> X87Lifter.fcmovnu ins insLen ctxt + | OP.FADD -> X87Lifter.fpuadd ins insLen ctxt false + | OP.FADDP -> X87Lifter.fpuadd ins insLen ctxt true + | OP.FIADD -> X87Lifter.fiadd ins insLen ctxt + | OP.FSUB -> X87Lifter.fpusub ins insLen ctxt false + | OP.FSUBP -> X87Lifter.fpusub ins insLen ctxt true + | OP.FISUB -> X87Lifter.fisub ins insLen ctxt + | OP.FSUBR -> X87Lifter.fsubr ins insLen ctxt false + | OP.FSUBRP -> X87Lifter.fsubr ins insLen ctxt true + | OP.FISUBR -> X87Lifter.fisubr ins insLen ctxt + | OP.FMUL -> X87Lifter.fpumul ins insLen ctxt false + | OP.FMULP -> X87Lifter.fpumul ins insLen ctxt true + | OP.FIMUL -> X87Lifter.fimul ins insLen ctxt + | OP.FDIV -> X87Lifter.fpudiv ins insLen ctxt false + | OP.FDIVP -> X87Lifter.fpudiv ins insLen ctxt true + | OP.FIDIV -> X87Lifter.fidiv ins insLen ctxt + | OP.FDIVR -> X87Lifter.fdivr ins insLen ctxt false + | OP.FDIVRP -> X87Lifter.fdivr ins insLen ctxt true + | OP.FIDIVR -> X87Lifter.fidivr ins insLen ctxt + | OP.FPREM -> X87Lifter.fprem ins insLen ctxt false + | OP.FPREM1 -> X87Lifter.fprem ins insLen ctxt true + | OP.FABS -> X87Lifter.fabs ins insLen ctxt + | OP.FCHS -> X87Lifter.fchs ins insLen ctxt + | OP.FRNDINT -> X87Lifter.frndint ins insLen ctxt + | OP.FSCALE -> X87Lifter.fscale ins insLen ctxt + | OP.FSQRT -> X87Lifter.fsqrt ins insLen ctxt + | OP.FXTRACT -> X87Lifter.fxtract ins insLen ctxt + | OP.FCOM -> X87Lifter.fcom ins insLen ctxt 0 false + | OP.FCOMP -> X87Lifter.fcom ins insLen ctxt 1 false + | OP.FCOMPP -> X87Lifter.fcom ins insLen ctxt 2 false + | OP.FUCOM -> X87Lifter.fcom ins insLen ctxt 0 true + | OP.FUCOMP -> X87Lifter.fcom ins insLen ctxt 1 true + | OP.FUCOMPP -> X87Lifter.fcom ins insLen ctxt 2 true + | OP.FICOM -> X87Lifter.ficom ins insLen ctxt false + | OP.FICOMP -> X87Lifter.ficom ins insLen ctxt true + | OP.FCOMI -> X87Lifter.fcomi ins insLen ctxt false + | OP.FUCOMI -> X87Lifter.fcomi ins insLen ctxt false + | OP.FCOMIP -> X87Lifter.fcomi ins insLen ctxt true + | OP.FUCOMIP -> X87Lifter.fcomi ins insLen ctxt true + | OP.FTST -> X87Lifter.ftst ins insLen ctxt + | OP.FXAM -> X87Lifter.fxam ins insLen ctxt + | OP.FSIN -> X87Lifter.fsin ins insLen ctxt + | OP.FCOS -> X87Lifter.fcos ins insLen ctxt + | OP.FSINCOS -> X87Lifter.fsincos ins insLen ctxt + | OP.FPTAN -> X87Lifter.fptan ins insLen ctxt + | OP.FPATAN -> X87Lifter.fpatan ins insLen ctxt + | OP.F2XM1 -> X87Lifter.f2xm1 ins insLen ctxt + | OP.FYL2X -> X87Lifter.fyl2x ins insLen ctxt + | OP.FYL2XP1 -> X87Lifter.fyl2xp1 ins insLen ctxt + | OP.FLD1 -> X87Lifter.fld1 ins insLen ctxt + | OP.FLDZ -> X87Lifter.fldz ins insLen ctxt + | OP.FLDPI -> X87Lifter.fldpi ins insLen ctxt + | OP.FLDL2E -> X87Lifter.fldl2e ins insLen ctxt + | OP.FLDLN2 -> X87Lifter.fldln2 ins insLen ctxt + | OP.FLDL2T -> X87Lifter.fldl2t ins insLen ctxt + | OP.FLDLG2 -> X87Lifter.fldlg2 ins insLen ctxt + | OP.FINCSTP -> X87Lifter.fincstp ins insLen ctxt + | OP.FDECSTP -> X87Lifter.fdecstp ins insLen ctxt + | OP.FFREE -> X87Lifter.ffree ins insLen ctxt + | OP.FINIT -> X87Lifter.finit ins insLen ctxt + | OP.FNINIT -> X87Lifter.fninit ins insLen ctxt + | OP.FCLEX -> X87Lifter.fclex ins insLen ctxt + | OP.FSTCW -> X87Lifter.fstcw ins insLen ctxt + | OP.FNSTCW -> X87Lifter.fnstcw ins insLen ctxt + | OP.FLDCW -> X87Lifter.fldcw ins insLen ctxt + | OP.FSTENV -> X87Lifter.fstenv ins insLen ctxt + | OP.FLDENV -> X87Lifter.fldenv ins insLen ctxt + | OP.FSAVE -> X87Lifter.fsave ins insLen ctxt + | OP.FRSTOR -> X87Lifter.frstor ins insLen ctxt + | OP.FSTSW -> X87Lifter.fstsw ins insLen ctxt + | OP.FNSTSW -> X87Lifter.fnstsw ins insLen ctxt + | OP.WAIT -> X87Lifter.wait ins insLen ctxt + | OP.FNOP -> X87Lifter.fnop ins insLen ctxt + | OP.FXSAVE | OP.FXSAVE64 -> X87Lifter.fxsave ins insLen ctxt + | OP.FXRSTOR | OP.FXRSTOR64 -> X87Lifter.fxrstor ins insLen ctxt + | o -> +#if DEBUG + eprintfn "%A" o + eprintfn "%A" ins +#endif + raise <| NotImplementedIRException (Disasm.opCodeToString o) + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Intel/IntelLiftingUtils.fs b/src/FrontEnd/BinLifter/Intel/IntelLiftingUtils.fs new file mode 100644 index 00000000..938799d5 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelLiftingUtils.fs @@ -0,0 +1,376 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.Intel.LiftingUtils + +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators +open B2R2.FrontEnd.BinLifter.Intel.Helper + +open type BinOpType + +let inline ( !. ) (ctxt: TranslationContext) name = + Register.toRegID name |> ctxt.GetRegVar + +let inline getPseudoRegVar (ctxt: TranslationContext) name pos = + ctxt.GetPseudoRegVar (Register.toRegID name) pos + +let inline numU32 n t = BitVector.ofUInt32 n t |> AST.num + +let inline numI32 n t = BitVector.ofInt32 n t |> AST.num + +let inline numU64 n t = BitVector.ofUInt64 n t |> AST.num + +let inline numI64 n t = BitVector.ofInt64 n t |> AST.num + +let numInsLen insLen (ctxt: TranslationContext) = numU32 insLen ctxt.WordBitSize + +let numOprSize = function + | 8 | 16 | 32 | 64 | 128 | 256 | 512 as rt -> + numI32 (int rt) rt + | _ -> raise InvalidOperandSizeException + +let inline is64bit (ctxt: TranslationContext) = ctxt.WordBitSize = 64 + +let is64REXW ctxt (ins: InsInfo) = + is64bit ctxt && hasREXW ins.REXPrefix + +#if DEBUG +let assert32 ctxt = + if is64bit ctxt then raise InvalidISAException else () +#endif + +let inline tmpVars2 ir t = + struct (!*ir t, !*ir t) + +let inline tmpVars3 ir t = + struct (!*ir t, !*ir t, !*ir t) + +let inline tmpVars4 ir t = + struct (!*ir t, !*ir t, !*ir t, !*ir t) + +let inline getOperationSize (i: InsInfo) = i.MainOperationSize + +let inline getEffAddrSz (i: InsInfo) = i.PointerSize + +let private getMemExpr128 expr = + match expr.E with + | Load (e, 128, expr, _) -> + AST.load e 64 (expr .+ numI32 8 (TypeCheck.typeOf expr)), + AST.load e 64 expr + | _ -> raise InvalidOperandException + +let private getMemExpr256 expr = + match expr.E with + | Load (e, 256, expr, _) -> + AST.load e 64 (expr .+ numI32 24 (TypeCheck.typeOf expr)), + AST.load e 64 (expr .+ numI32 16 (TypeCheck.typeOf expr)), + AST.load e 64 (expr .+ numI32 8 (TypeCheck.typeOf expr)), + AST.load e 64 expr + | _ -> raise InvalidOperandException + +let private getMemExpr512 expr = + match expr.E with + | Load (e, 512, expr, _) -> + AST.load e 64 (expr .+ numI32 56 (TypeCheck.typeOf expr)), + AST.load e 64 (expr .+ numI32 48 (TypeCheck.typeOf expr)), + AST.load e 64 (expr .+ numI32 40 (TypeCheck.typeOf expr)), + AST.load e 64 (expr .+ numI32 32 (TypeCheck.typeOf expr)), + AST.load e 64 (expr .+ numI32 24 (TypeCheck.typeOf expr)), + AST.load e 64 (expr .+ numI32 16 (TypeCheck.typeOf expr)), + AST.load e 64 (expr .+ numI32 8 (TypeCheck.typeOf expr)), + AST.load e 64 expr + | _ -> raise InvalidOperandException + +let private getMemExprs expr = + match expr.E with + | Load (e, 128, expr, _) -> + [ AST.load e 64 expr + AST.load e 64 (expr .+ numI32 8 (TypeCheck.typeOf expr)) ] + | Load (e, 256, expr, _) -> + [ AST.load e 64 expr + AST.load e 64 (expr .+ numI32 8 (TypeCheck.typeOf expr)) + AST.load e 64 (expr .+ numI32 16 (TypeCheck.typeOf expr)) + AST.load e 64 (expr .+ numI32 24 (TypeCheck.typeOf expr)) ] + | Load (e, 512, expr, _) -> + [ AST.load e 64 expr + AST.load e 64 (expr .+ numI32 8 (TypeCheck.typeOf expr)) + AST.load e 64 (expr .+ numI32 16 (TypeCheck.typeOf expr)) + AST.load e 64 (expr .+ numI32 24 (TypeCheck.typeOf expr)) + AST.load e 64 (expr .+ numI32 32 (TypeCheck.typeOf expr)) + AST.load e 64 (expr .+ numI32 40 (TypeCheck.typeOf expr)) + AST.load e 64 (expr .+ numI32 48 (TypeCheck.typeOf expr)) + AST.load e 64 (expr .+ numI32 56 (TypeCheck.typeOf expr)) ] + | _ -> raise InvalidOperandException + +let getPseudoRegVar128 ctxt r = + getPseudoRegVar ctxt r 2, getPseudoRegVar ctxt r 1 + +let getPseudoRegVar256 ctxt r = + getPseudoRegVar ctxt r 4, getPseudoRegVar ctxt r 3, + getPseudoRegVar ctxt r 2, getPseudoRegVar ctxt r 1 + +let getPseudoRegVar512 ctxt r = + getPseudoRegVar ctxt r 8, getPseudoRegVar ctxt r 7, + getPseudoRegVar ctxt r 6, getPseudoRegVar ctxt r 5, + getPseudoRegVar ctxt r 4, getPseudoRegVar ctxt r 3, + getPseudoRegVar ctxt r 2, getPseudoRegVar ctxt r 1 + +let private getPseudoRegVars ctxt r = + match Register.getKind r with + | Register.Kind.XMM -> [ getPseudoRegVar ctxt r 1; getPseudoRegVar ctxt r 2 ] + | Register.Kind.YMM -> [ getPseudoRegVar ctxt r 1; getPseudoRegVar ctxt r 2 + getPseudoRegVar ctxt r 3; getPseudoRegVar ctxt r 4 ] + | Register.Kind.ZMM -> [ getPseudoRegVar ctxt r 1; getPseudoRegVar ctxt r 2 + getPseudoRegVar ctxt r 3; getPseudoRegVar ctxt r 4 + getPseudoRegVar ctxt r 5; getPseudoRegVar ctxt r 6 + getPseudoRegVar ctxt r 7; getPseudoRegVar ctxt r 8 ] + | _ -> raise InvalidOperandException + +let isSegReg = function + | Register.CS + | Register.DS + | Register.SS + | Register.ES + | Register.FS + | Register.GS -> true + | _ -> false + +let private segRegToBase = function + | R.CS -> R.CSBase + | R.DS -> R.DSBase + | R.ES -> R.ESBase + | R.FS -> R.FSBase + | R.GS -> R.GSBase + | R.SS -> R.SSBase + | _ -> Utils.impossible () + +let private ldMem (ins: InsInfo) ctxt oprSize e = + match getSegment ins.Prefixes with + | Some s -> !.ctxt (segRegToBase s) .+ e + | None -> e + |> AST.loadLE oprSize + +let private numOfAddrSz (ins: InsInfo) (ctxt: TranslationContext) n = + let pref = ins.Prefixes + let sz = + if ctxt.WordBitSize = 32 then if hasAddrSz pref then 16 else 32 + else if hasAddrSz pref then 32 else 64 + numI64 n sz + +let inline private sIdx ins ctxt (r, s: Scale) = + (!.ctxt r) .* (numOfAddrSz ins ctxt (int64 s)) + +let private transMem ins insLen ctxt b index disp oprSize = + match b, index, (disp: Disp option) with + | None, None, Some d -> + numOfAddrSz ins ctxt d + |> ldMem ins ctxt oprSize + | None, Some i, Some d -> + (sIdx ins ctxt i) .+ (numOfAddrSz ins ctxt d) + |> ldMem ins ctxt oprSize + | Some b, None, None -> + !.ctxt b + |> ldMem ins ctxt oprSize + | Some R.RIP, None, Some d -> (* RIP-relative addressing *) + !.ctxt R.RIP .+ numOfAddrSz ins ctxt (d + int64 (insLen: uint32)) + |> ldMem ins ctxt oprSize + | Some b, None, Some d -> + !.ctxt b .+ (numOfAddrSz ins ctxt d) + |> ldMem ins ctxt oprSize + | Some b, Some i, None -> + !.ctxt b .+ (sIdx ins ctxt i) + |> ldMem ins ctxt oprSize + | Some b, Some i, Some d -> + !.ctxt b .+ (sIdx ins ctxt i) .+ (numOfAddrSz ins ctxt d) + |> ldMem ins ctxt oprSize + | _, _, _ -> raise InvalidOperandException + +let transOprToExpr ins insLen ctxt = function + | OprReg reg -> !.ctxt reg + | OprMem (b, index, disp, oprSize) -> + transMem ins insLen ctxt b index disp oprSize + | OprImm (imm, _) -> numI64 imm (getOperationSize ins) + | OprDirAddr (Relative offset) -> numI64 offset ctxt.WordBitSize + | OprDirAddr (Absolute (_, addr, _)) -> numU64 addr ctxt.WordBitSize + | _ -> Utils.impossible () + +let transOprToExprVec ins insLen ctxt opr = + match opr with + | OprReg r -> getPseudoRegVars ctxt r + | OprMem (b, index, disp, oprSize) -> + transMem ins insLen ctxt b index disp oprSize |> getMemExprs + | OprImm (imm, _) -> [ numI64 imm (getOperationSize ins) ] + | _ -> raise InvalidOperandException + +let transOprToExpr32 ins insLen ctxt opr = + match opr with + | OprReg r when Register.toRegType r > 64 -> + getPseudoRegVar ctxt r 1 |> AST.xtlo 32 + | OprReg r -> !.ctxt r + | OprMem (b, index, disp, 32) -> + transMem ins insLen ctxt b index disp 32 + | _ -> raise InvalidOperandException + +let transOprToExpr64 ins insLen ctxt opr = + match opr with + | OprReg r when Register.toRegType r > 64 -> getPseudoRegVar ctxt r 1 + | OprReg r -> !.ctxt r + | OprMem (b, index, disp, 64) -> + transMem ins insLen ctxt b index disp 64 + | _ -> raise InvalidOperandException + +let transOprToExpr128 ins insLen ctxt opr = + match opr with + | OprReg r -> getPseudoRegVar128 ctxt r + | OprMem (b, index, disp, oprSize) -> + transMem ins insLen ctxt b index disp oprSize |> getMemExpr128 + | _ -> raise InvalidOperandException + +let transOprToExpr256 ins insLen ctxt opr = + match opr with + | OprReg r -> getPseudoRegVar256 ctxt r + | OprMem (b, index, disp, oprSize) -> + transMem ins insLen ctxt b index disp oprSize |> getMemExpr256 + | _ -> raise InvalidOperandException + +let transOprToExpr512 ins insLen ctxt opr = + match opr with + | OprReg r -> getPseudoRegVar512 ctxt r + | OprMem (b, index, disp, oprSize) -> + transMem ins insLen ctxt b index disp oprSize |> getMemExpr512 + | _ -> raise InvalidOperandException + +let transOprToFloat80 ins insLen ctxt opr = + match opr with + | OprReg r when Register.toRegType r = 80 -> !.ctxt r + | OprReg r -> + !.ctxt r |> AST.cast CastKind.FloatCast 80 + | OprMem (b, index, disp, 80) -> + transMem ins insLen ctxt b index disp 80 + | OprMem (b, index, disp, len) -> + transMem ins insLen ctxt b index disp len + |> AST.cast CastKind.FloatCast 80 + | _ -> raise InvalidOperandException + +/// Return a tuple (jump target expr, is pc-relative?) +let transJumpTargetOpr (ins: InsInfo) pc insLen (ctxt: TranslationContext) = + match ins.Operands with + | OneOperand (OprDirAddr (Absolute (_, addr, _))) -> + struct (numU64 addr ctxt.WordBitSize, false) + | OneOperand (OprDirAddr (Relative offset)) -> + let wordSize = ctxt.WordBitSize + let offset = numI64 offset wordSize |> AST.sext wordSize + struct (pc .+ offset, true) + | OneOperand (OprReg reg) -> struct (!.ctxt reg, false) + | OneOperand (OprMem (b, index, disp, oprSize)) -> + struct (transMem ins insLen ctxt b index disp oprSize, false) + | _ -> raise InvalidOperandException + +let getTwoOprs (ins: InsInfo) = + match ins.Operands with + | TwoOperands (o1, o2) -> struct (o1, o2) + | _ -> raise InvalidOperandException + +let getThreeOprs (ins: InsInfo) = + match ins.Operands with + | ThreeOperands (o1, o2, o3) -> struct (o1, o2, o3) + | _ -> raise InvalidOperandException + +let getFourOprs (ins: InsInfo) = + match ins.Operands with + | FourOperands (o1, o2, o3, o4) -> struct (o1, o2, o3, o4) + | _ -> raise InvalidOperandException + +let transOneOpr (ins: InsInfo) insLen ctxt = + match ins.Operands with + | OneOperand opr -> transOprToExpr ins insLen ctxt opr + | _ -> raise InvalidOperandException + +let transTwoOprs (ins: InsInfo) insLen ctxt = + match ins.Operands with + | TwoOperands (o1, o2) -> + struct (transOprToExpr ins insLen ctxt o1, + transOprToExpr ins insLen ctxt o2) + | _ -> raise InvalidOperandException + +let transThreeOprs (ins: InsInfo) insLen ctxt = + match ins.Operands with + | ThreeOperands (o1, o2, o3) -> + struct (transOprToExpr ins insLen ctxt o1, + transOprToExpr ins insLen ctxt o2, + transOprToExpr ins insLen ctxt o3) + | _ -> raise InvalidOperandException + +/// This is an Intel-specific assignment to a destination operand. +/// Unlike typical assignments, this function performs zero-padding when +/// necessary (See Intel Manual 3.4.1.1). +/// In 64-bit mode, operand size determines the number of valid bits. +/// 64-bit operands generate a 64-bit result in the destination general-purpose +/// register. 32-bit operands generate a 32-bit result, zero-extended to a +/// 64-bit result in the destination general-purpose register. 8-bit and 16-bit +/// operands generate 8-bit or 16-bit result. The upper 56 or 48 bits +/// (respectively) of the destination general-purpose register are not modified. +let dstAssign oprSize dst src = + match oprSize with + | 8 | 16 -> dst := src (* No extension for 8- and 16-bit operands *) + | _ -> let dst = AST.unwrap dst + let dstOrigSz = dst |> TypeCheck.typeOf + let oprBitSize = RegType.toBitWidth oprSize + let dstBitSize = RegType.toBitWidth dstOrigSz + if dstBitSize > oprBitSize then dst := AST.zext dstOrigSz src + elif dstBitSize = oprBitSize then dst := src + else raise InvalidOperandSizeException + +let maxNum rt = + match rt with + | 8 -> BitVector.maxUInt8 + | 16 -> BitVector.maxUInt16 + | 32 -> BitVector.maxUInt32 + | 64 -> BitVector.maxUInt64 + | _ -> raise InvalidOperandSizeException + |> AST.num + +let castNum newType e = + match e.E with + | Num n -> BitVector.cast n newType |> AST.num + | _ -> raise InvalidOperandException + +let getMask oprSize = + match oprSize with + | 8 -> numI64 0xffL oprSize + | 16 -> numI64 0xffffL oprSize + | 32 -> numI64 0xffffffffL oprSize + | 64 -> numI64 0xffffffffffffffffL oprSize + | _ -> raise InvalidOperandSizeException + +let sideEffects insLen name = + let ir = IRBuilder (4) + !ir insLen diff --git a/src/FrontEnd/BinLifter/Intel/IntelMMXLifter.fs b/src/FrontEnd/BinLifter/Intel/IntelMMXLifter.fs new file mode 100644 index 00000000..8f17caa8 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelMMXLifter.fs @@ -0,0 +1,527 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.Intel.MMXLifter + +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.FrontEnd.BinLifter.Intel.LiftingUtils + +let private movdRegToReg ctxt r1 r2 ir = + let tmp = !*ir 32 + match Register.getKind r1, Register.getKind r2 with + | Register.Kind.XMM, _ -> + !!ir (getPseudoRegVar ctxt r1 1 := AST.zext 64 (!.ctxt r2)) + !!ir (getPseudoRegVar ctxt r1 2 := AST.num0 64) + | _, Register.Kind.XMM -> + !!ir (tmp := AST.xtlo 32 (getPseudoRegVar ctxt r2 1)) + !!ir (dstAssign 32 (!.ctxt r1) tmp) + | Register.Kind.MMX, _ -> + !!ir (!.ctxt r1 := AST.zext 64 (!.ctxt r2)) + | _, Register.Kind.MMX -> + !!ir (tmp := AST.xtlo 32 (!.ctxt r2)) + !!ir (dstAssign 32 (!.ctxt r1) tmp) + | _, _ -> Utils.impossible () + +let private movdRegToMem ctxt dst r ir = + match Register.getKind r with + | Register.Kind.XMM -> + !!ir (dst := AST.xtlo 32 (getPseudoRegVar ctxt r 1)) + | Register.Kind.MMX -> !!ir (dst := AST.xtlo 32 (!.ctxt r)) + | _ -> Utils.impossible () + +let private movdMemToReg ctxt src r ir = + match Register.getKind r with + | Register.Kind.XMM -> + !!ir (getPseudoRegVar ctxt r 1 := AST.zext 64 src) + !!ir (getPseudoRegVar ctxt r 2 := AST.num0 64) + | Register.Kind.MMX -> !!ir (!.ctxt r := AST.zext 64 src) + | _ -> Utils.impossible () + +let movd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + ! movdRegToReg ctxt r1 r2 ir + | OprMem _, OprReg r -> let dst = transOprToExpr ins insLen ctxt dst + movdRegToMem ctxt dst r ir + | OprReg r, OprMem _ -> let src = transOprToExpr ins insLen ctxt src + movdMemToReg ctxt src r ir + | _, _ -> raise InvalidOperandException + !>ir insLen + +let private movqRegToReg ctxt r1 r2 ir = + match Register.getKind r1, Register.getKind r2 with + | Register.Kind.XMM, Register.Kind.XMM -> + !!ir (getPseudoRegVar ctxt r1 1 := getPseudoRegVar ctxt r2 1 ) + !!ir (getPseudoRegVar ctxt r1 2 := AST.num0 64) + | Register.Kind.XMM, _ -> + !!ir (getPseudoRegVar ctxt r1 1 := !.ctxt r2) + !!ir (getPseudoRegVar ctxt r1 2 := AST.num0 64) + | Register.Kind.GP, Register.Kind.XMM -> + !!ir (!.ctxt r1 := getPseudoRegVar ctxt r2 1) + | Register.Kind.MMX, Register.Kind.MMX + | Register.Kind.MMX, Register.Kind.GP + | Register.Kind.GP, Register.Kind.MMX -> + !!ir (!.ctxt r1 := !.ctxt r2) + | _, _ -> Utils.impossible () + +let private movqRegToMem ctxt dst r ir = + match Register.getKind r with + | Register.Kind.XMM -> !!ir (dst := getPseudoRegVar ctxt r 1) + | Register.Kind.MMX -> !!ir (dst := !.ctxt r) + | _ -> Utils.impossible () + +let private movqMemToReg ctxt src r ir = + match Register.getKind r with + | Register.Kind.XMM -> + !!ir (getPseudoRegVar ctxt r 1 := src) + !!ir (getPseudoRegVar ctxt r 2 := AST.num0 64) + | Register.Kind.MMX -> !!ir (!.ctxt r := src) + | _ -> Utils.impossible () + +let movq ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + ! movqRegToReg ctxt r1 r2 ir + | OprMem _, OprReg r -> let dst = transOprToExpr ins insLen ctxt dst + movqRegToMem ctxt dst r ir + | OprReg r, OprMem _ -> let src = transOprToExpr ins insLen ctxt src + movqMemToReg ctxt src r ir + | _, _ -> raise InvalidOperandException + !>ir insLen + +let private saturateSignedDwordToSignedWord expr = + let checkMin = AST.slt expr (numI32 -32768 32) + let checkMax = AST.sgt expr (numI32 32767 32) + let minNum = numI32 -32768 16 + let maxNum = numI32 32767 16 + AST.ite checkMin minNum (AST.ite checkMax maxNum (AST.xtlo 16 expr)) + +let private saturateSignedWordToSignedByte expr = + let checkMin = AST.slt expr (numI32 -128 16) + let checkMax = AST.sgt expr (numI32 127 16) + let minNum = numI32 -128 8 + let maxNum = numI32 127 8 + AST.ite checkMin minNum (AST.ite checkMax maxNum (AST.xtlo 8 expr)) + +let private saturateSignedWordToUnsignedByte expr = + let checkMin = AST.slt expr (numI32 0 16) + let checkMax = AST.sgt expr (numI32 255 16) + let minNum = numU32 0u 8 + let maxNum = numU32 0xffu 8 + AST.ite checkMin minNum (AST.ite checkMax maxNum (AST.xtlo 8 expr)) + +let private saturateToSignedByte expr = + let checkMin = AST.slt expr (numI32 -128 8) + let checkMax = AST.sgt expr (numI32 127 8) + let minNum = numI32 -128 8 + let maxNum = numI32 127 8 + AST.ite checkMin minNum (AST.ite checkMax maxNum expr) + +let private saturateToSignedWord expr = + let checkMin = AST.slt expr (numI32 -32768 16) + let checkMax = AST.sgt expr (numI32 32767 16) + let minNum = numI32 -32768 16 + let maxNum = numI32 32767 16 + AST.ite checkMin minNum (AST.ite checkMax maxNum expr) + +let private saturateToUnsignedByte expr = + let checkMin = AST.lt expr (numU32 0u 8) + let checkMax = AST.gt expr (numU32 0xffu 8) + let minNum = numU32 0u 8 + let maxNum = numU32 0xffu 8 + AST.ite checkMin minNum (AST.ite checkMax maxNum expr) + +let private saturateToUnsignedWord expr = + let checkMin = AST.lt expr (numU32 0u 16) + let checkMax = AST.gt expr (numU32 0xffffu 16) + let minNum = numU32 0u 16 + let maxNum = numU32 0xffu 16 + AST.ite checkMin minNum (AST.ite checkMax maxNum expr) + +let private makeSrc ir packSize packNum src = + let tSrc = Array.init packNum (fun _ -> !*ir packSize) + for i in 0 .. packNum - 1 do + !!ir (tSrc.[i] := AST.extract src packSize (i * (int packSize))) + tSrc + +let private buildPackedTwoOprs ins insLen ctxt packSz opFn bufSz dst src = + let ir = IRBuilder (bufSz) + let oprSize = getOperationSize ins + let packNum = oprSize / packSz + let makeSrc = makeSrc ir packSz + ! -> + let dst = transOprToExpr ins insLen ctxt dst + let src = transOprToExpr ins insLen ctxt src + let src1 = makeSrc packNum dst + let src2 = match src.E with + | Load (_, rt, _, _) -> makeSrc (rt / packSz) src + | _ -> makeSrc packNum src + !!ir (dst := opFn oprSize src1 src2 |> AST.concatArr) + | 128 -> + let packNum = packNum / (oprSize / 64) + let srcAppend src = + let src = transOprToExprVec ins insLen ctxt src + List.map (makeSrc packNum) src |> List.fold Array.append [||] + let tSrc = opFn oprSize (srcAppend dst) (srcAppend src) + let dst = transOprToExprVec ins insLen ctxt dst + let packNum = Array.length tSrc / List.length dst + let assign idx dst = + !!ir (dst := Array.sub tSrc (packNum * idx) packNum |> AST.concatArr) + List.iteri assign dst + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let private buildPackedThreeOprs ins iLen ctxt packSz opFn bufSz dst s1 s2 = + let ir = IRBuilder (bufSz) + let oprSize = getOperationSize ins + let packNum = oprSize / packSz + let makeSrc = makeSrc ir packSz + ! -> + let dst = transOprToExpr ins iLen ctxt dst + let src1 = transOprToExpr ins iLen ctxt s1 + let src2 = transOprToExpr ins iLen ctxt s2 + let src1 = makeSrc packNum src1 + let src2 = makeSrc packNum src2 + !!ir (dst := opFn oprSize src1 src2 |> AST.concatArr) + | 128 | 256 -> + let packNum = packNum / (oprSize / 64) + let dst = transOprToExprVec ins iLen ctxt dst + let srcAppend src = + let src = transOprToExprVec ins iLen ctxt src + List.map (makeSrc packNum) src |> List.fold Array.append [||] + let tSrc = opFn oprSize (srcAppend s1) (srcAppend s2) + let assign idx dst = + !!ir (dst := Array.sub tSrc (packNum * idx) packNum |> AST.concatArr) + List.iteri assign dst + | _ -> raise InvalidOperandSizeException + !>ir iLen + +let buildPackedInstr (ins: InsInfo) insLen ctxt packSz opFn bufSz = + match ins.Operands with + | TwoOperands (o1, o2) -> + buildPackedTwoOprs ins insLen ctxt packSz opFn bufSz o1 o2 + | ThreeOperands (o1, o2, o3) -> + buildPackedThreeOprs ins insLen ctxt packSz opFn bufSz o1 o2 o3 + | _ -> raise InvalidOperandException + +let private opPackssdw _ src1 src2 = + Array.append src1 src2 |> Array.map saturateSignedDwordToSignedWord + +let packssdw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPackssdw 16 + +let private opPacksswb _ src1 src2 = + Array.append src1 src2 |> Array.map saturateSignedWordToSignedByte + +let packsswb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPacksswb 16 + +let private opPackuswb _ src1 src2 = + Array.append src1 src2 |> Array.map saturateSignedWordToUnsignedByte + +let packuswb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPackuswb 16 + +let private opPunpck oprSize src1 src2 isHigh = + match oprSize with + | 64 | 128 -> + let half = Array.length src1 / 2 + let sPos = if isHigh then half else 0 + let src1 = Array.sub src1 sPos half + let src2 = Array.sub src2 sPos half + Array.fold2 (fun acc e1 e2 -> e2 :: e1 :: acc) [] src1 src2 + |> List.rev |> List.toArray + | 256 -> + let half = Array.length src1 / 2 + let src1A = Array.sub src1 0 half + let src1B = Array.sub src1 half half + let src2A = Array.sub src2 0 half + let src2B = Array.sub src2 half half + let half = Array.length src1A / 2 + let sPos = if isHigh then half else 0 + let src1A = Array.sub src1A sPos half + let src2A = Array.sub src2A sPos half + let src1B = Array.sub src1B sPos half + let src2B = Array.sub src2B sPos half + List.append + (Array.fold2 (fun acc e1 e2 -> e2 :: e1 :: acc) [] src1B src2B) + (Array.fold2 (fun acc e1 e2 -> e2 :: e1 :: acc) [] src1A src2A) + |> List.rev |> List.toArray + | _ -> raise InvalidOperandSizeException + +let opPunpckHigh oprSize src1 src2 = opPunpck oprSize src1 src2 true + +let opPunpckLow oprSize src1 src2 = opPunpck oprSize src1 src2 false + +let punpckhbw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPunpckHigh 64 + +let punpckhwd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPunpckHigh 32 + +let punpckhdq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPunpckHigh 16 + +let punpcklbw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPunpckLow 64 + +let punpcklwd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPunpckLow 32 + +let punpckldq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPunpckLow 16 + +let opP op _ = Array.map2 (op) + +let paddb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 (opP (.+)) 8 + +let paddw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 (opP (.+)) 8 + +let paddd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 (opP (.+)) 8 + +let private opPaddsb oprSize src1 src2 = + (opP (.+)) oprSize src1 src2 |> Array.map saturateToSignedByte + +let paddsb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPaddsb 16 + +let private opPaddsw oprSize src1 src2 = + (opP (.+)) oprSize src1 src2 |> Array.map saturateToSignedWord + +let paddsw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPaddsw 16 + +let private opPaddusb oprSize src1 src2 = + (opP (.+)) oprSize src1 src2 |> Array.map saturateToUnsignedByte + +let paddusb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPaddusb 16 + +let private opPaddusw oprSize src1 src2 = + (opP (.+)) oprSize src1 src2 |> Array.map saturateToUnsignedWord + +let paddusw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPaddusw 16 + +let opPsub _ = Array.map2 (.-) + +let psubb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPsub 8 + +let psubw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPsub 8 + +let psubd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPsub 8 + +let private opPsubsb oprSize src1 src2 = + opPsub oprSize src1 src2 |> Array.map saturateToSignedByte + +let psubsb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPsubsb 8 + +let private opPsubsw oprSize src1 src2 = + opPsub oprSize src1 src2 |> Array.map saturateToSignedWord + +let psubsw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPsubsw 8 + +let private opPsubusb oprSize src1 src2 = + opPsub oprSize src1 src2 |> Array.map saturateToUnsignedByte + +let psubusb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPsubusb 8 + +let private opPsubusw oprSize src1 src2 = + opPsub oprSize src1 src2 |> Array.map saturateToUnsignedWord + +let psubusw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPsubusw 8 + +let opPmul resType extr extSz packSz src1 src2 = + Array.map2 (fun e1 e2 -> extr extSz e1 .* extr extSz e2) src1 src2 + |> Array.map (resType packSz) + +let private opPmulhw _ = opPmul AST.xthi AST.sext 32 16 + +let pmulhw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPmulhw 32 + +let private opPmullw _ = opPmul AST.xtlo AST.sext 32 16 + +let pmullw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPmullw 32 + +let private opPmaddwd _ = + let lowAndSExt expr = AST.xtlo 16 expr |> AST.sext 32 + let highAndSExt expr = AST.xthi 16 expr |> AST.sext 32 + let mulLow e1 e2 = lowAndSExt e1 .* lowAndSExt e2 + let mulHigh e1 e2 = highAndSExt e1 .* highAndSExt e2 + let packAdd e1 e2 = mulLow e1 e2 .+ mulHigh e1 e2 + Array.map2 packAdd + +let pmaddwd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPmaddwd 16 + +let opPcmp packSz cmpOp = + Array.map2 (fun e1 e2 -> + AST.ite (cmpOp e1 e2) (getMask packSz) (AST.num0 packSz)) + +let opPcmpeqb _ = opPcmp 8 (==) + +let pcmpeqb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPcmpeqb 32 + +let private opPcmpeqw _ = opPcmp 16 (==) + +let pcmpeqw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPcmpeqw 32 + +let opPcmpeqd _ = opPcmp 32 (==) + +let pcmpeqd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPcmpeqd 16 + +let opPcmpgtb _ = opPcmp 8 AST.sgt + +let pcmpgtb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPcmpgtb 32 + +let private opPcmpgtw _ = opPcmp 16 AST.sgt + +let pcmpgtw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPcmpgtw 32 + +let private opPcmpgtd _ = opPcmp 32 AST.sgt + +let pcmpgtd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPcmpgtd 16 + +let opPand _ = Array.map2 (.&) + +let pand ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPand 8 + +let opPandn _ = Array.map2 (fun e1 e2 -> (AST.not e1) .& e2) + +let pandn ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPandn 8 + +let opPor _ = Array.map2 (.|) + +let por ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPor 8 + +let pxor ins insLen ctxt = + let ir = IRBuilder (4) + let oprSize = getOperationSize ins + ! -> + let struct (dst, src) = transTwoOprs ins insLen ctxt + !!ir (dst := dst <+> src) + | 128 -> + let struct (dst, src) = getTwoOprs ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + !!ir (dstA := dstA <+> srcA) + !!ir (dstB := dstB <+> srcB) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let private opShiftPackedDataLogical oprSize packSz shift src1 src2 = + let count = AST.concatArr src2 |> AST.zext oprSize + let cond = AST.gt count (numI32 ((int packSz) - 1) oprSize) + let shifted expr = AST.extract (shift (AST.zext oprSize expr) count) packSz 0 + Array.map (fun e -> AST.ite cond (AST.num0 packSz) (shifted e)) src1 + +let private opPsllw oprSize = opShiftPackedDataLogical oprSize 16 (<<) + +let psllw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPsllw 8 + +let private opPslld oprSize = opShiftPackedDataLogical oprSize 32 (<<) + +let pslld ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPslld 8 + +let private opPsllq oprSize = opShiftPackedDataLogical oprSize 64 (<<) + +let psllq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPsllq 8 + +let private opPsrlw oprSize = opShiftPackedDataLogical oprSize 16 (>>) + +let psrlw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPsrlw 32 + +let private opPsrld oprSize = opShiftPackedDataLogical oprSize 32 (>>) + +let psrld ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPsrld 16 + +let private opPsrlq oprSize = opShiftPackedDataLogical oprSize 64 (>>) + +let psrlq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPsrlq 8 + +let private opShiftPackedDataRightArith oprSize packSz src1 src2 = + let count = AST.concatArr src2 |> AST.zext oprSize + let cond = AST.gt count (numI32 ((int packSz) - 1) oprSize) + let count = AST.ite cond (numI32 (int packSz) oprSize) count + let shifted expr = AST.extract ((AST.sext oprSize expr) ?>> count) packSz 0 + Array.map shifted src1 + +let private opPsraw oprSize = opShiftPackedDataRightArith oprSize 16 + +let psraw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPsraw 32 + +let private opPsrad oprSize = opShiftPackedDataRightArith oprSize 32 + +let psrad ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPsrad 16 + +let emms _ins insLen ctxt = + let ir = IRBuilder (4) + !) + !>ir insLen diff --git a/src/FrontEnd/Intel/IntelTypes.fs b/src/FrontEnd/BinLifter/Intel/IntelOpcodes.fs similarity index 74% rename from src/FrontEnd/Intel/IntelTypes.fs rename to src/FrontEnd/BinLifter/Intel/IntelOpcodes.fs index 517646c8..4f530144 100644 --- a/src/FrontEnd/Intel/IntelTypes.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelOpcodes.fs @@ -22,75 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.Intel - -open B2R2 - -/// This is a fatal error that happens when B2R2 tries to access non-existing -/// register symbol. This exception should not happen in general. -exception internal InvalidRegAccessException - -exception internal InvalidPrefixException - -exception internal InvalidOn64Exception - -/// Instruction prefixes. -type Prefix = - | PrxNone = 0x0 (* No prefix *) - | PrxLOCK = 0x1 (* Group 1 *) - /// REPNE/REPNZ prefix is encoded using F2H. - | PrxREPNZ = 0x2 - /// Bound prefix is encoded using F2H if the following conditions are true. - | PrxBND = 0x4 - /// REP or REPE/REPZ is encoded using F3H. - | PrxREPZ = 0x8 - | PrxCS = 0x10 (* Group 2 *) - | PrxSS = 0x20 - | PrxDS = 0x40 - | PrxES = 0x80 - | PrxFS = 0x100 - | PrxGS = 0x200 - /// Operand-size override prefix is encoded using 66H. - | PrxOPSIZE = 0x400 (* Group 3 *) - /// 67H - Address-size override prefix. - | PrxADDRSIZE = 0x800 (* Group 4 *) - -/// REX prefixes. -type REXPrefix = - /// No REX: this is to represent the case where there is no REX - | NOREX = 0b0000000 - /// Extension of the ModR/M reg, Opcode reg field (SPL, BPL, ...). - | REX = 0b1000000 - /// Extension of the ModR/M rm, SIB base, Opcode reg field. - | REXB = 0b1000001 - /// Extension of the SIB index field. - | REXX = 0b1000010 - /// Extension of the ModR/M SIB index, base field. - | REXXB = 0b1000011 - /// Extension of the ModR/M reg field. - | REXR = 0b1000100 - /// Extension of the ModR/M reg, r/m field. - | REXRB = 0b1000101 - /// Extension of the ModR/M reg, SIB index field. - | REXRX = 0b1000110 - /// Extension of the ModR/M reg, SIB index, base. - | REXRXB = 0b1000111 - /// Operand 64bit. - | REXW = 0b1001000 - /// REX.B + Operand 64bit. - | REXWB = 0b1001001 - /// REX.X + Operand 64bit. - | REXWX = 0b1001010 - /// REX.XB + Operand 64bit. - | REXWXB = 0b1001011 - /// REX.R + Operand 64bit. - | REXWR = 0b1001100 - /// REX.RB + Operand 64bit. - | REXWRB = 0b1001101 - /// REX.RX + Operand 64bit. - | REXWRX = 0b1001110 - /// REX.RXB + Operand 64bit. - | REXWRXB = 0b1001111 +namespace B2R2.FrontEnd.BinLifter.Intel /// /// Intel opcodes. This type should be generated using @@ -613,9 +545,9 @@ type Opcode = | INSW = 256 /// Call to Interrupt (Interrupt vector specified by immediate byte). | INT = 257 - /// Call to Interrupt (Interrupt 3?trap to debugger). + /// Call to Interrupt (Interrupt 3-trap to debugger). | INT3 = 258 - /// Call to Interrupt (InteInterrupt 4?if overflow flag is 1). + /// Call to Interrupt (InteInterrupt 4-if overflow flag is 1). | INTO = 259 /// Invalidate Internal Caches. | INVD = 260 @@ -635,57 +567,57 @@ type Opcode = | IRETQ = 267 /// Interrupt return (16-bit operand size). | IRETW = 268 - /// Jump if Condition Is Met (Jump short if above, CF = 0 and ZF = 0). - | JNBE = 269 - | JA = 269 + /// Jump if Condition Is Met (Jump near if not below, CF = 0). + | JAE = 269 + | JNC = 269 + | JNB = 269 /// Jump if Condition Is Met (Jump short if below, CF = 1). | JC = 270 | JNAE = 270 | JB = 270 - /// Jump if Condition Is Met (Jump short if below or equal, CF = 1 or ZF). - | JNA = 271 - | JBE = 271 /// Jump if Condition Is Met (Jump short if CX register is 0). - | JCXZ = 272 + | JCXZ = 271 /// Jump if Condition Is Met (Jump short if ECX register is 0). - | JECXZ = 273 - /// Jump if Condition Is Met (Jump short if RCX register is 0). - | JRCXZ = 274 - /// Jump if Condition Is Met (Jump short if greater, ZF = 0 and SF = OF). - | JNLE = 275 - | JG = 275 - /// Jump if Condition Is Met (Jump short if less, SF <> OF). - | JNGE = 276 - | JL = 276 - /// Jump if Cond Is Met (Jump short if less or equal, ZF = 1 or SF <> OF). - | JNG = 277 - | JLE = 277 + | JECXZ = 272 + /// Jump if Condition Is Met (Jump near if not less, SF = OF). + | JGE = 273 + | JNL = 273 /// Far jmp. - | JMPFar = 278 + | JMPFar = 274 /// Near jmp. - | JMPNear = 279 - /// Jump if Condition Is Met (Jump near if not below, CF = 0). - | JAE = 280 - | JNC = 280 - | JNB = 280 - /// Jump if Condition Is Met (Jump near if not less, SF = OF). - | JGE = 281 - | JNL = 281 + | JMPNear = 275 + /// Jump if Condition Is Met (Jump short if below or equal, CF = 1 or ZF). + | JNA = 276 + | JBE = 276 + /// Jump if Condition Is Met (Jump short if above, CF = 0 and ZF = 0). + | JNBE = 277 + | JA = 277 + /// Jump if Cond Is Met (Jump short if less or equal, ZF = 1 or SF <> OF). + | JNG = 278 + | JLE = 278 + /// Jump if Condition Is Met (Jump short if less, SF <> OF). + | JNGE = 279 + | JL = 279 + /// Jump if Condition Is Met (Jump short if greater, ZF = 0 and SF = OF). + | JNLE = 280 + | JG = 280 /// Jump if Condition Is Met (Jump near if not overflow, OF = 0). - | JNO = 282 - /// Jump if Condition Is Met (Jump near if not parity, PF = 0). - | JPO = 283 - | JNP = 283 + | JNO = 281 /// Jump if Condition Is Met (Jump near if not sign, SF = 0). - | JNS = 284 + | JNS = 282 /// Jump if Condition Is Met (Jump near if not zero, ZF = 0). - | JNZ = 285 - | JNE = 285 + | JNZ = 283 + | JNE = 283 /// Jump if Condition Is Met (Jump near if overflow, OF = 1). - | JO = 286 + | JO = 284 /// Jump if Condition Is Met (Jump near if parity, PF = 1). - | JP = 287 - | JPE = 287 + | JP = 285 + | JPE = 285 + /// Jump if Condition Is Met (Jump near if not parity, PF = 0). + | JPO = 286 + | JNP = 286 + /// Jump if Condition Is Met (Jump short if RCX register is 0). + | JRCXZ = 287 /// Jump if Condition Is Met (Jump short if sign, SF = 1). | JS = 288 /// Jump if Condition Is Met (Jump short if zero, ZF = 1). @@ -1525,1277 +1457,985 @@ type Opcode = | VBLENDMPD = 705 /// Replace the VBLENDVPS instructions (using opmask as select control). | VBLENDMPS = 706 + /// Variable Blend Packed Double-Precision Floats. + | VBLENDVPD = 707 /// Broadcast 128 bits of int data in mem to low and high 128-bits in ymm1. - | VBROADCASTI128 = 707 + | VBROADCASTI128 = 708 + /// Broadcast low double-precision floating-point element. + | VBROADCASTSD = 709 /// Broadcast Floating-Point Data. - | VBROADCASTSS = 708 + | VBROADCASTSS = 710 + /// Compare Packed Double-Precision Floating-Point Values. + | VCMPPD = 711 + /// Compare Packed Single-Precision Floating-Point Values. + | VCMPPS = 712 + /// Compare Scalar Double-Precision Floating-Point Values. + | VCMPSD = 713 + /// Scalar Single-Precision Floating-Point Values. + | VCMPSS = 714 /// Compare Scalar Ordered Double-Precision FP Values and Set EFLAGS. - | VCOMISD = 709 + | VCOMISD = 715 /// Compare Scalar Ordered Single-Precision FP Values and Set EFLAGS. - | VCOMISS = 710 + | VCOMISS = 716 /// Compress packed DP elements of a vector. - | VCOMPRESSPD = 711 + | VCOMPRESSPD = 717 /// Compress packed SP elements of a vector. - | VCOMPRESSPS = 712 + | VCOMPRESSPS = 718 + /// Convert two packed signed doubleword integers. + | VCVTDQ2PD = 719 + /// Convert Packed Dword Integers to Packed Single-Precision FP Values. + | VCVTDQ2PS = 720 + /// Convert two packed double-precision floating-point values. + | VCVTPD2PS = 721 /// Convert Packed Double-Precision FP Values to Packed Quadword Integers. - | VCVTPD2QQ = 713 + | VCVTPD2QQ = 722 /// Convert Packed DP FP Values to Packed Unsigned DWord Integers. - | VCVTPD2UDQ = 714 + | VCVTPD2UDQ = 723 /// Convert Packed DP FP Values to Packed Unsigned QWord Integers. - | VCVTPD2UQQ = 715 + | VCVTPD2UQQ = 724 /// Convert 16-bit FP values to Single-Precision FP values. - | VCVTPH2PS = 716 + | VCVTPH2PS = 725 + /// Convert Packed Single-Precision FP Values to Packed Dbl-Precision FP Values. + | VCVTPS2PD = 726 /// Convert Single-Precision FP value to 16-bit FP value. - | VCVTPS2PH = 717 + | VCVTPS2PH = 727 /// Convert Packed SP FP Values to Packed Signed QWord Int Values. - | VCVTPS2QQ = 718 + | VCVTPS2QQ = 728 /// Convert Packed SP FP Values to Packed Unsigned DWord Int Values. - | VCVTPS2UDQ = 719 + | VCVTPS2UDQ = 729 /// Convert Packed SP FP Values to Packed Unsigned QWord Int Values. - | VCVTPS2UQQ = 720 + | VCVTPS2UQQ = 730 /// Convert Packed Quadword Integers to Packed Double-Precision FP Values. - | VCVTQQ2PD = 721 + | VCVTQQ2PD = 731 /// Convert Packed Quadword Integers to Packed Single-Precision FP Values. - | VCVTQQ2PS = 722 + | VCVTQQ2PS = 732 /// Convert Scalar Double-Precision FP Value to Integer. - | VCVTSD2SI = 723 + | VCVTSD2SI = 733 /// Convert Scalar Double-Precision FP Val to Scalar Single-Precision FP Val. - | VCVTSD2SS = 724 + | VCVTSD2SS = 734 /// Convert Scalar Double-Precision FP Value to Unsigned Doubleword Integer. - | VCVTSD2USI = 725 + | VCVTSD2USI = 735 /// Convert Dword Integer to Scalar Double-Precision FP Value. - | VCVTSI2SD = 726 + | VCVTSI2SD = 736 /// Convert Dword Integer to Scalar Single-Precision FP Value. - | VCVTSI2SS = 727 + | VCVTSI2SS = 737 /// Convert Scalar Single-Precision FP Val to Scalar Double-Precision FP Val. - | VCVTSS2SD = 728 + | VCVTSS2SD = 738 /// Convert Scalar Single-Precision FP Value to Dword Integer. - | VCVTSS2SI = 729 + | VCVTSS2SI = 739 /// Convert Scalar Single-Precision FP Value to Unsigned Doubleword Integer. - | VCVTSS2USI = 730 + | VCVTSS2USI = 740 + /// Convert with Trunc Packed Double-Precision FP Val to Packed Dword Integers. + | VCVTTPD2DQ = 741 /// Convert with Truncation Packed DP FP Values to Packed QWord Integers. - | VCVTTPD2QQ = 731 + | VCVTTPD2QQ = 742 /// Convert with Truncation Packed DP FP Values to Packed Unsigned DWord Int. - | VCVTTPD2UDQ = 732 + | VCVTTPD2UDQ = 743 /// Convert with Truncation Packed DP FP Values to Packed Unsigned QWord Int. - | VCVTTPD2UQQ = 733 + | VCVTTPD2UQQ = 744 /// Convert with Truncation Packed SP FP Values to Packed Signed QWord Int. - | VCVTTPS2QQ = 734 + | VCVTTPS2QQ = 745 /// Convert with Truncation Packed SP FP Values to Packed Unsigned DWord Int. - | VCVTTPS2UDQ = 735 + | VCVTTPS2UDQ = 746 /// Convert with Truncation Packed SP FP Values to Packed Unsigned QWord Int. - | VCVTTPS2UQQ = 736 + | VCVTTPS2UQQ = 747 /// Convert with Truncation Scalar Double-Precision FP Value to Signed. - | VCVTTSD2SI = 737 + | VCVTTSD2SI = 748 /// Convert with Truncation Scalar DP FP Value to Unsigned Integer. - | VCVTTSD2USI = 738 + | VCVTTSD2USI = 749 /// Convert with Truncation Scalar Single-Precision FP Value to Dword Integer. - | VCVTTSS2SI = 739 + | VCVTTSS2SI = 750 /// Convert with Truncation Scalar Single-Precision FP Value to Unsigned Int. - | VCVTTSS2USI = 740 + | VCVTTSS2USI = 751 /// Convert Packed Unsigned DWord Integers to Packed DP FP Values. - | VCVTUDQ2PD = 741 + | VCVTUDQ2PD = 752 /// Convert Packed Unsigned DWord Integers to Packed SP FP Values. - | VCVTUDQ2PS = 742 + | VCVTUDQ2PS = 753 /// Convert Packed Unsigned QWord Integers to Packed DP FP Values. - | VCVTUQQ2PD = 743 + | VCVTUQQ2PD = 754 /// Convert Packed Unsigned QWord Integers to Packed SP FP Values. - | VCVTUQQ2PS = 744 + | VCVTUQQ2PS = 755 /// Convert an unsigned integer to the low DP FP elem and merge to a vector. - | VCVTUSI2USD = 745 + | VCVTUSI2USD = 756 /// Convert an unsigned integer to the low SP FP elem and merge to a vector. - | VCVTUSI2USS = 746 + | VCVTUSI2USS = 757 /// Double Block Packed Sum-Absolute-Differences (SAD) on Unsigned Bytes. - | VDBPSADBW = 747 + | VDBPSADBW = 758 /// Divide Packed Double-Precision Floating-Point Values. - | VDIVPD = 748 + | VDIVPD = 759 /// Divide Packed Single-Precision Floating-Point Values. - | VDIVPS = 749 + | VDIVPS = 760 /// Divide Scalar Double-Precision Floating-Point Values. - | VDIVSD = 750 + | VDIVSD = 761 /// Divide Scalar Single-Precision Floating-Point Values. - | VDIVSS = 751 + | VDIVSS = 762 /// Verify a Segment for Reading. - | VERR = 752 + | VERR = 763 /// Verify a Segment for Writing. - | VERW = 753 + | VERW = 764 /// Compute approximate base-2 exponential of packed DP FP elems of a vector. - | VEXP2PD = 754 + | VEXP2PD = 765 /// Compute approximate base-2 exponential of packed SP FP elems of a vector. - | VEXP2PS = 755 + | VEXP2PS = 766 /// Compute approximate base-2 exponential of the low DP FP elem of a vector. - | VEXP2SD = 756 + | VEXP2SD = 767 /// Compute approximate base-2 exponential of the low SP FP elem of a vector. - | VEXP2SS = 757 + | VEXP2SS = 768 /// Load Sparse Packed Double-Precision FP Values from Dense Memory. - | VEXPANDPD = 758 + | VEXPANDPD = 769 /// Load Sparse Packed Single-Precision FP Values from Dense Memory. - | VEXPANDPS = 759 + | VEXPANDPS = 770 + /// Extract Packed Floating-Point Values. + | VEXTRACTF128 = 771 + /// Extract a vector from a full-length vector with 32-bit granular update. + | VEXTRACTF32X4 = 772 /// Extract a vector from a full-length vector with 32-bit granular update. - | VEXTRACTF32X4 = 760 + | VEXTRACTF32X8 = 773 /// Extract a vector from a full-length vector with 64-bit granular update. - | VEXTRACTF64X2 = 761 + | VEXTRACTF64X2 = 774 /// Extract a vector from a full-length vector with 64-bit granular update. - | VEXTRACTF64X4 = 762 + | VEXTRACTF64X4 = 775 /// Extract a vector from a full-length vector with 32-bit granular update. - | VEXTRACTI32X4 = 763 + | VEXTRACTI32X4 = 776 + /// Extract a vector from a full-length vector with 32-bit granular update. + | VEXTRACTI32X8 = 777 /// Extract a vector from a full-length vector with 64-bit granular update. - | VEXTRACTI64X2 = 764 + | VEXTRACTI64X2 = 778 /// Extract a vector from a full-length vector with 64-bit granular update. - | VEXTRACTI64X4 = 765 + | VEXTRACTI64X4 = 779 /// Fix Up Special Packed Float64 Values. - | VFIXUPIMMPD = 766 + | VFIXUPIMMPD = 780 /// Fix Up Special Packed Float32 Values. - | VFIXUPIMMPS = 767 + | VFIXUPIMMPS = 781 /// Fix Up Special Scalar Float64 Value. - | VFIXUPIMMSD = 768 + | VFIXUPIMMSD = 782 /// Fix Up Special Scalar Float32 Value. - | VFIXUPIMMSS = 769 + | VFIXUPIMMSS = 783 + /// Fused Multiply-Add of Packed Double-Precision Floating-Point Values. + | VFMADD132PD = 784 /// Fused Multiply-Add of Scalar Double-Precision Floating-Point Values. - | VFMADD132SD = 770 + | VFMADD132SD = 785 /// Fused Multiply-Add of Scalar Single-Precision Floating-Point Values. - | VFMADD132SS = 771 + | VFMADD132SS = 786 + /// Fused Multiply-Add of Packed Double-Precision Floating-Point Values. + | VFMADD213PD = 787 + /// Fused Multiply-Add of Packed Single-Precision Floating-Point Values. + | VFMADD213PS = 788 /// Fused Multiply-Add of Scalar Double-Precision Floating-Point Values. - | VFMADD213SD = 772 + | VFMADD213SD = 789 /// Fused Multiply-Add of Scalar Single-Precision Floating-Point Values. - | VFMADD213SS = 773 + | VFMADD213SS = 790 + /// Fused Multiply-Add of Packed Double-Precision Floating-Point Value. + | VFMADD231PD = 791 /// Fused Multiply-Add of Scalar Double-Precision Floating-Point Values. - | VFMADD231SD = 774 + | VFMADD231SD = 792 /// Fused Multiply-Add of Scalar Single-Precision Floating-Point Values. - | VFMADD231SS = 775 + | VFMADD231SS = 793 + /// Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values. + | VFMSUB132SS = 794 + /// Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values. + | VFMSUB213PD = 795 + /// Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values. + | VFMSUB213SD = 796 + /// Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values. + | VFMSUB231PD = 797 + /// Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values. + | VFMSUB231SD = 798 + /// Fused Negative Multiply-Add of Packed Double-Precision FP Values. + | VFNMADD132PD = 799 + /// Fused Negative Multiply-Add of Scalar Double-Precision FP Values. + | VFNMADD132SD = 800 + /// Fused Negative Multiply-Add of Packed Double-Precision FP Values. + | VFNMADD213PD = 801 + /// Fused Negative Multiply-Add of Scalar Double-Precision FP Values. + | VFNMADD213SD = 802 + /// Fused Negative Multiply-Add of Packed Double-Precision FP Values. + | VFNMADD231PD = 803 + /// Fused Negative Multiply-Add of Scalar Double-Precision FP Values. + | VFNMADD231SD = 804 /// Tests Types Of a Packed Float64 Values. - | VFPCLASSPD = 776 + | VFPCLASSPD = 805 /// Tests Types Of a Packed Float32 Values. - | VFPCLASSPS = 777 + | VFPCLASSPS = 806 /// Tests Types Of a Scalar Float64 Values. - | VFPCLASSSD = 778 + | VFPCLASSSD = 807 /// Tests Types Of a Scalar Float32 Values. - | VFPCLASSSS = 779 + | VFPCLASSSS = 808 + /// Gather Packed SP FP values Using Signed Dword/Qword Indices. + | VGATHERDPS = 809 + /// Gather Packed DP FP Values Using Signed Dword/Qword Indices. + | VGATHERQPD = 810 /// Convert Exponents of Packed DP FP Values to DP FP Values. - | VGETEXPPD = 780 + | VGETEXPPD = 811 /// Convert Exponents of Packed SP FP Values to SP FP Values. - | VGETEXPPS = 781 + | VGETEXPPS = 812 /// Convert Exponents of Scalar DP FP Values to DP FP Value. - | VGETEXPSD = 782 + | VGETEXPSD = 813 /// Convert Exponents of Scalar SP FP Values to SP FP Value. - | VGETEXPSS = 783 + | VGETEXPSS = 814 /// Extract Float64 Vector of Normalized Mantissas from Float64 Vector. - | VGETMANTPD = 784 + | VGETMANTPD = 815 /// Extract Float32 Vector of Normalized Mantissas from Float32 Vector. - | VGETMANTPS = 785 + | VGETMANTPS = 816 /// Extract Float64 of Normalized Mantissas from Float64 Scalar. - | VGETMANTSD = 786 + | VGETMANTSD = 817 /// Extract Float32 Vector of Normalized Mantissa from Float32 Vector. - | VGETMANTSS = 787 + | VGETMANTSS = 818 + /// Insert Packed Floating-Point Values. + | VINSERTF128 = 819 /// Insert Packed Floating-Point Values. - | VINSERTF32X4 = 788 + | VINSERTF32X4 = 820 /// Insert Packed Floating-Point Values. - | VINSERTF64X2 = 789 + | VINSERTF64X2 = 821 /// Insert Packed Floating-Point Values. - | VINSERTF64X4 = 790 + | VINSERTF64X4 = 822 /// Insert Packed Integer Values. - | VINSERTI128 = 791 + | VINSERTI128 = 823 + /// Insert 256 bits of packed doubleword integer values. + | VINSERTI32X8 = 824 /// Insert Packed Floating-Point Values. - | VINSERTI64X2 = 792 + | VINSERTI64X2 = 825 + /// Insert 256 bits of packed quadword integer values. + | VINSERTI64X4 = 826 /// Load Unaligned Integer 128 Bits. - | VLDDQU = 793 + | VLDDQU = 827 + /// Return Maximum Packed Double-Precision Floating-Point Values. + | VMAXPD = 828 + /// Maximum of Packed Single-Precision Floating-Point Values. + | VMAXPS = 829 + /// Return Maximum Scalar Double-Precision Floating-Point Value. + | VMAXSD = 830 + /// Return Maximum Scalar Single-Precision Floating-Point Value. + | VMAXSS = 831 /// Call to VM Monitor. - | VMCALL = 794 + | VMCALL = 832 /// Clear Virtual-Machine Control Structure. - | VMCLEAR = 795 + | VMCLEAR = 833 /// Invoke VM function. - | VMFUNC = 796 + | VMFUNC = 834 + /// Return Minimum Packed Double-Precision Floating-Point Values. + | VMINPD = 835 + /// Return Minimum Packed Single-Precision Floating-Point Values. + | VMINPS = 836 + /// Return Minimum Scalar Double-Precision Floating-Point Value. + | VMINSD = 837 + /// Return Minimum Scalar Single-Precision Floating-Point Value. + | VMINSS = 838 /// Launch Virtual Machine. - | VMLAUNCH = 797 + | VMLAUNCH = 839 /// Move Aligned Packed Double-Precision Floating-Point Values. - | VMOVAPD = 798 + | VMOVAPD = 840 /// Move Aligned Packed Single-Precision Floating-Point Values. - | VMOVAPS = 799 + | VMOVAPS = 841 /// Move Doubleword. - | VMOVD = 800 + | VMOVD = 842 /// Move One Double-FP and Duplicate. - | VMOVDDUP = 801 + | VMOVDDUP = 843 /// Move Aligned Double Quadword. - | VMOVDQA = 802 + | VMOVDQA = 844 /// Move Aligned Double Quadword. - | VMOVDQA32 = 803 + | VMOVDQA32 = 845 /// Move Aligned Double Quadword. - | VMOVDQA64 = 804 + | VMOVDQA64 = 846 /// Move Unaligned Double Quadword. - | VMOVDQU = 805 + | VMOVDQU = 847 /// VMOVDQU with 16-bit granular conditional update. - | VMOVDQU16 = 806 + | VMOVDQU16 = 848 /// Move Unaligned Double Quadword. - | VMOVDQU32 = 807 + | VMOVDQU32 = 849 /// Move Unaligned Double Quadword. - | VMOVDQU64 = 808 + | VMOVDQU64 = 850 /// VMOVDQU with 8-bit granular conditional update. - | VMOVDQU8 = 809 + | VMOVDQU8 = 851 /// Move Packed Single-Precision Floating-Point Values High to Low. - | VMOVHLPS = 810 + | VMOVHLPS = 852 /// Move High Packed Double-Precision Floating-Point Value. - | VMOVHPD = 811 + | VMOVHPD = 853 /// Move High Packed Single-Precision Floating-Point Values. - | VMOVHPS = 812 + | VMOVHPS = 854 /// Move Packed Single-Precision Floating-Point Values Low to High. - | VMOVLHPS = 813 + | VMOVLHPS = 855 /// Move Low Packed Double-Precision Floating-Point Value. - | VMOVLPD = 814 + | VMOVLPD = 856 /// Move Low Packed Single-Precision Floating-Point Values. - | VMOVLPS = 815 + | VMOVLPS = 857 /// Extract Packed Double-Precision Floating-Point Sign Mask. - | VMOVMSKPD = 816 + | VMOVMSKPD = 858 /// Extract Packed Single-Precision Floating-Point Sign Mask. - | VMOVMSKPS = 817 + | VMOVMSKPS = 859 /// Load Double Quadword Non-Temporal Aligned Hint. - | VMOVNTDQ = 818 + | VMOVNTDQ = 860 /// Store Packed Double-Precision FP Values Using Non-Temporal Hint. - | VMOVNTPD = 819 + | VMOVNTPD = 861 /// Store Packed Single-Precision FP Values Using Non-Temporal Hint. - | VMOVNTPS = 820 + | VMOVNTPS = 862 /// Move Quadword. - | VMOVQ = 821 + | VMOVQ = 863 /// Move Data from String to String (doubleword). - | VMOVSD = 822 + | VMOVSD = 864 /// Move Packed Single-FP High and Duplicate. - | VMOVSHDUP = 823 + | VMOVSHDUP = 865 /// Move Packed Single-FP Low and Duplicate. - | VMOVSLDUP = 824 + | VMOVSLDUP = 866 /// Move Scalar Single-Precision Floating-Point Values. - | VMOVSS = 825 + | VMOVSS = 867 /// Move Unaligned Packed Double-Precision Floating-Point Values. - | VMOVUPD = 826 + | VMOVUPD = 868 /// Move Unaligned Packed Single-Precision Floating-Point Values. - | VMOVUPS = 827 + | VMOVUPS = 869 /// Load Pointer to Virtual-Machine Control Structure. - | VMPTRLD = 828 + | VMPTRLD = 870 /// Store Pointer to Virtual-Machine Control Structure. - | VMPTRST = 829 + | VMPTRST = 871 /// Reads a component from the VMCS and stores it into a destination operand. - | VMREAD = 830 + | VMREAD = 872 /// Resume Virtual Machine. - | VMRESUME = 831 + | VMRESUME = 873 /// Multiply Packed Double-Precision Floating-Point Values. - | VMULPD = 832 + | VMULPD = 874 /// Multiply Packed Single-Precision Floating-Point Values. - | VMULPS = 833 + | VMULPS = 875 /// Multiply Scalar Double-Precision Floating-Point Values. - | VMULSD = 834 + | VMULSD = 876 /// Multiply Scalar Single-Precision Floating-Point Values. - | VMULSS = 835 + | VMULSS = 877 /// Writes a component to the VMCS from a source operand. - | VMWRITE = 836 + | VMWRITE = 878 /// Leave VMX Operation. - | VMXOFF = 837 + | VMXOFF = 879 /// Enter VMX Operation. - | VMXON = 838 + | VMXON = 880 /// Bitwise Logical OR of Double-Precision Floating-Point Values. - | VORPD = 839 + | VORPD = 881 /// Bitwise Logical OR of Single-Precision Floating-Point Values. - | VORPS = 840 + | VORPS = 882 /// Packed Absolute Value (byte). - | VPABSB = 841 + | VPABSB = 883 /// Packed Absolute Value (dword). - | VPABSD = 842 + | VPABSD = 884 /// Packed Absolute Value (word). - | VPABSW = 843 + | VPABSW = 885 /// Pack with Signed Saturation. - | VPACKSSDW = 844 + | VPACKSSDW = 886 /// Pack with Signed Saturation. - | VPACKSSWB = 845 + | VPACKSSWB = 887 /// Pack with Unsigned Saturation. - | VPACKUSDW = 846 + | VPACKUSDW = 888 /// Pack with Unsigned Saturation. - | VPACKUSWB = 847 + | VPACKUSWB = 889 /// Add Packed byte Integers. - | VPADDB = 848 + | VPADDB = 890 /// Add Packed Doubleword Integers. - | VPADDD = 849 + | VPADDD = 891 /// Add Packed Quadword Integers. - | VPADDQ = 850 + | VPADDQ = 892 /// Add Packed Signed Integers with Signed Saturation (byte). - | VPADDSB = 851 + | VPADDSB = 893 /// Add Packed Signed Integers with Signed Saturation (word). - | VPADDSW = 852 + | VPADDSW = 894 /// Add Packed Unsigned Integers with Unsigned Saturation (byte). - | VPADDUSB = 853 + | VPADDUSB = 895 /// Add Packed Unsigned Integers with Unsigned Saturation (word). - | VPADDUSW = 854 + | VPADDUSW = 896 /// Add Packed word Integers. - | VPADDW = 855 + | VPADDW = 897 /// Packed Align Right. - | VPALIGNR = 856 + | VPALIGNR = 898 /// Logical AND. - | VPAND = 857 + | VPAND = 899 /// Logical AND NOT. - | VPANDN = 858 + | VPANDN = 900 /// Average Packed Integers (byte). - | VPAVGB = 859 + | VPAVGB = 901 /// Average Packed Integers (word). - | VPAVGW = 860 + | VPAVGW = 902 /// Blend Byte/Word Vectors Using an Opmask Control. - | VPBLENDMB = 861 + | VPBLENDMB = 903 /// Blend Int32/Int64 Vectors Using an OpMask Control. - | VPBLENDMD = 862 + | VPBLENDMD = 904 /// Blend qword elements using opmask as select control. - | VPBLENDMQ = 863 + | VPBLENDMQ = 905 /// Blend word elements using opmask as select control. - | VPBLENDMW = 864 + | VPBLENDMW = 906 /// Broadcast Integer Data. - | VPBROADCASTB = 865 + | VPBROADCASTB = 907 /// Broadcast from general-purpose register to vector register. - | VPBROADCASTD = 866 + | VPBROADCASTD = 908 /// Broadcast Mask to Vector Register. - | VPBROADCASTM = 867 + | VPBROADCASTM = 909 /// Broadcast from general-purpose register to vector register. - | VPBROADCASTQ = 868 + | VPBROADCASTQ = 910 /// Broadcast from general-purpose register to vector register. - | VPBROADCASTW = 869 + | VPBROADCASTW = 911 /// Compare packed signed bytes using specified primitive. - | VPCMPB = 870 + | VPCMPB = 912 /// Compare packed signed dwords using specified primitive. - | VPCMPD = 871 + | VPCMPD = 913 /// Compare Packed Data for Equal (byte). - | VPCMPEQB = 872 + | VPCMPEQB = 914 /// Compare Packed Data for Equal (doubleword). - | VPCMPEQD = 873 + | VPCMPEQD = 915 /// Compare Packed Data for Equal (quadword). - | VPCMPEQQ = 874 + | VPCMPEQQ = 916 /// Compare Packed Data for Equal (word). - | VPCMPEQW = 875 + | VPCMPEQW = 917 /// Packed Compare Explicit Length Strings, Return Index. - | VPCMPESTRI = 876 + | VPCMPESTRI = 918 /// Packed Compare Explicit Length Strings, Return Mask. - | VPCMPESTRM = 877 + | VPCMPESTRM = 919 /// Compare Packed Signed Integers for Greater Than (byte). - | VPCMPGTB = 878 + | VPCMPGTB = 920 /// Compare Packed Signed Integers for Greater Than (doubleword). - | VPCMPGTD = 879 + | VPCMPGTD = 921 /// Compare Packed Data for Greater Than (qword). - | VPCMPGTQ = 880 + | VPCMPGTQ = 922 /// Compare Packed Signed Integers for Greater Than (word). - | VPCMPGTW = 881 + | VPCMPGTW = 923 /// Packed Compare Implicit Length Strings, Return Index. - | VPCMPISTRI = 882 + | VPCMPISTRI = 924 /// Packed Compare Implicit Length Strings, Return Mask. - | VPCMPISTRM = 883 + | VPCMPISTRM = 925 /// Compare packed signed quadwords using specified primitive. - | VPCMPQ = 884 + | VPCMPQ = 926 /// Compare packed signed words using specified primitive. - | VPCMPW = 885 + | VPCMPW = 927 /// Compare packed unsigned bytes using specified primitive. - | VPCMUB = 886 + | VPCMUB = 928 /// Compare packed unsigned dwords using specified primitive. - | VPCMUD = 887 + | VPCMUD = 929 /// Compare packed unsigned quadwords using specified primitive. - | VPCMUQ = 888 + | VPCMUQ = 930 /// Compare packed unsigned words using specified primitive. - | VPCMUW = 889 + | VPCMUW = 931 /// Store Sparse Packed Doubleword Integer Values into Dense Memory/Register. - | VPCOMPRESSD = 890 + | VPCOMPRESSD = 932 /// Store Sparse Packed Quadword Integer Values into Dense Memory/Register. - | VPCOMPRESSQ = 891 + | VPCOMPRESSQ = 933 /// Detect conflicts within a vector of packed 32/64-bit integers. - | VPCONFLICTD = 892 + | VPCONFLICTD = 934 /// Detect conflicts within a vector of packed 64-bit integers. - | VPCONFLICTQ = 893 + | VPCONFLICTQ = 935 /// Full Permute of Bytes from Two Tables Overwriting the Index. - | VPERMI2B = 894 + | VPERMI2B = 936 /// Full permute of two tables of dword elements overwriting the index vector. - | VPERMI2D = 895 + | VPERMI2D = 937 /// Full permute of two tables of DP elements overwriting the index vector. - | VPERMI2PD = 896 + | VPERMI2PD = 938 /// Full permute of two tables of SP elements overwriting the index vector. - | VPERMI2PS = 897 + | VPERMI2PS = 939 /// Full permute of two tables of qword elements overwriting the index vector. - | VPERMI2Q = 898 + | VPERMI2Q = 940 /// Full Permute From Two Tables Overwriting the Index. - | VPERMI2W = 899 + | VPERMI2W = 941 /// Full permute of two tables of dword elements overwriting one source table. - | VPERMT2D = 900 + | VPERMT2D = 942 /// Full permute of two tables of DP elements overwriting one source table. - | VPERMT2PD = 901 + | VPERMT2PD = 943 /// Full permute of two tables of SP elements overwriting one source table. - | VPERMT2PS = 902 + | VPERMT2PS = 944 /// Full permute of two tables of qword elements overwriting one source table. - | VPERMT2Q = 903 + | VPERMT2Q = 945 /// Permute packed word elements. - | VPERMW = 904 + | VPERMW = 946 /// Load Sparse Packed Doubleword Integer Values from Dense Memory / Register. - | VPEXPANDD = 905 + | VPEXPANDD = 947 /// Load Sparse Packed Quadword Integer Values from Dense Memory / Register. - | VPEXPANDQ = 906 + | VPEXPANDQ = 948 + /// Extract DWord. + | VPEXTRD = 949 /// Extract Word. - | VPEXTRW = 907 + | VPEXTRW = 950 + /// Gather packed dword values using signed Dword/Qword indices. + | VPGATHERDD = 951 /// Packed Horizontal Add (32-bit). - | VPHADDD = 908 + | VPHADDD = 952 /// Packed Horizontal Add and Saturate (16-bit). - | VPHADDSW = 909 + | VPHADDSW = 953 /// Packed Horizontal Add (16-bit). - | VPHADDW = 910 + | VPHADDW = 954 /// Packed Horizontal Word Minimum. - | VPHMINPOSUW = 911 + | VPHMINPOSUW = 955 /// Packed Horizontal Subtract (32-bit). - | VPHSUBD = 912 - /// Packed Horizontal Subtract and Saturate (16-bit) - | VPHSUBSW = 913 + | VPHSUBD = 956 + /// Packed Horizontal Subtract and Saturate (16-bit). + | VPHSUBSW = 957 /// Packed Horizontal Subtract (16-bit). - | VPHSUBW = 914 + | VPHSUBW = 958 /// Insert Byte. - | VPINSRB = 915 + | VPINSRB = 959 + /// Insert Dword. + | VPINSRD = 960 + /// Insert Qword. + | VPINSRQ = 961 /// Insert Word. - | VPINSRW = 916 + | VPINSRW = 962 /// Count the number of leading zero bits of packed dword elements. - | VPLZCNTD = 917 + | VPLZCNTD = 963 /// Count the number of leading zero bits of packed qword elements. - | VPLZCNTQ = 918 + | VPLZCNTQ = 964 /// Multiply and Add Packed Integers. - | VPMADDWD = 919 + | VPMADDWD = 965 /// Maximum of Packed Signed Integers (byte). - | VPMAXSB = 920 + | VPMAXSB = 966 /// Maximum of Packed Signed Integers (dword). - | VPMAXSD = 921 + | VPMAXSD = 967 /// Compute maximum of packed signed 64-bit integer elements. - | VPMAXSQ = 922 + | VPMAXSQ = 968 /// Maximum of Packed Signed Word Integers. - | VPMAXSW = 923 + | VPMAXSW = 969 /// Maximum of Packed Unsigned Byte Integers. - | VPMAXUB = 924 + | VPMAXUB = 970 /// Maximum of Packed Unsigned Integers (dword). - | VPMAXUD = 925 + | VPMAXUD = 971 /// Compute maximum of packed unsigned 64-bit integer elements. - | VPMAXUQ = 926 + | VPMAXUQ = 972 /// Maximum of Packed Unsigned Integers (word). - | VPMAXUW = 927 + | VPMAXUW = 973 /// Minimum of Packed Signed Integers (byte). - | VPMINSB = 928 + | VPMINSB = 974 /// Minimum of Packed Signed Integers (dword). - | VPMINSD = 929 + | VPMINSD = 975 /// Compute minimum of packed signed 64-bit integer elements. - | VPMINSQ = 930 + | VPMINSQ = 976 /// Minimum of Packed Signed Word Integers. - | VPMINSW = 931 + | VPMINSW = 977 /// Minimum of Packed Unsigned Byte Integers. - | VPMINUB = 932 + | VPMINUB = 978 /// Minimum of Packed Dword Integers. - | VPMINUD = 933 + | VPMINUD = 979 /// Compute minimum of packed unsigned 64-bit integer elements. - | VPMINUQ = 934 + | VPMINUQ = 980 /// Minimum of Packed Unsigned Integers (word). - | VPMINUW = 935 + | VPMINUW = 981 /// Convert a vector register in 32/64-bit granularity to an opmask register. - | VPMOVB2D = 936 + | VPMOVB2D = 982 /// Convert a Vector Register to a Mask. - | VPMOVB2M = 937 + | VPMOVB2M = 983 /// Down Convert DWord to Byte. - | VPMOVDB = 938 + | VPMOVDB = 984 /// Down Convert DWord to Word. - | VPMOVDW = 939 + | VPMOVDW = 985 /// Convert opmask register to vector register in 8-bit granularity. - | VPMOVM2B = 940 + | VPMOVM2B = 986 /// Convert opmask register to vector register in 32-bit granularity. - | VPMOVM2D = 941 + | VPMOVM2D = 987 /// Convert opmask register to vector register in 64-bit granularity. - | VPMOVM2Q = 942 + | VPMOVM2Q = 988 /// Convert opmask register to vector register in 16-bit granularity. - | VPMOVM2W = 943 + | VPMOVM2W = 989 /// Move Byte Mask. - | VPMOVMSKB = 944 + | VPMOVMSKB = 990 /// Convert a Vector Register to a Mask. - | VPMOVQ2M = 945 + | VPMOVQ2M = 991 /// Down Convert QWord to Byte. - | VPMOVQB = 946 + | VPMOVQB = 992 /// Down Convert QWord to DWord. - | VPMOVQD = 947 + | VPMOVQD = 993 /// Down Convert QWord to Word. - | VPMOVQW = 948 + | VPMOVQW = 994 /// Down Convert DWord to Byte. - | VPMOVSDB = 949 + | VPMOVSDB = 995 /// Down Convert DWord to Word. - | VPMOVSDW = 950 + | VPMOVSDW = 996 /// Down Convert QWord to Byte. - | VPMOVSQB = 951 + | VPMOVSQB = 997 /// Down Convert QWord to Dword. - | VPMOVSQD = 952 + | VPMOVSQD = 998 /// Down Convert QWord to Word. - | VPMOVSQW = 953 + | VPMOVSQW = 999 /// Down Convert Word to Byte. - | VPMOVSWB = 954 + | VPMOVSWB = 1000 /// Packed Move with Sign Extend (8-bit to 32-bit). - | VPMOVSXBD = 955 + | VPMOVSXBD = 1001 /// Packed Move with Sign Extend (8-bit to 64-bit). - | VPMOVSXBQ = 956 + | VPMOVSXBQ = 1002 /// Packed Move with Sign Extend (8-bit to 16-bit). - | VPMOVSXBW = 957 + | VPMOVSXBW = 1003 /// Packed Move with Sign Extend (32-bit to 64-bit). - | VPMOVSXDQ = 958 + | VPMOVSXDQ = 1004 /// Packed Move with Sign Extend (16-bit to 32-bit). - | VPMOVSXWD = 959 + | VPMOVSXWD = 1005 /// Packed Move with Sign Extend (16-bit to 64-bit). - | VPMOVSXWQ = 960 + | VPMOVSXWQ = 1006 /// Down Convert DWord to Byte. - | VPMOVUSDB = 961 + | VPMOVUSDB = 1007 /// Down Convert DWord to Word. - | VPMOVUSDW = 962 + | VPMOVUSDW = 1008 /// Down Convert QWord to Byte. - | VPMOVUSQB = 963 - /// Down Convert QWord to DWord - | VPMOVUSQD = 964 - /// Down Convert QWord to Dword. - | VPMOVUSQW = 965 + | VPMOVUSQB = 1009 + /// Down Convert QWord to DWord. + | VPMOVUSQD = 1010 + /// Down Convert QWord to Word. + | VPMOVUSQW = 1011 /// Down Convert Word to Byte. - | VPMOVUSWB = 966 + | VPMOVUSWB = 1012 /// Convert a vector register in 16-bit granularity to an opmask register. - | VPMOVW2M = 967 + | VPMOVW2M = 1013 /// Down convert word elements in a vector to byte elements using truncation. - | VPMOVWB = 968 + | VPMOVWB = 1014 /// Packed Move with Zero Extend (8-bit to 32-bit). - | VPMOVZXBD = 969 + | VPMOVZXBD = 1015 /// Packed Move with Zero Extend (8-bit to 64-bit). - | VPMOVZXBQ = 970 + | VPMOVZXBQ = 1016 /// Packed Move with Zero Extend (8-bit to 16-bit). - | VPMOVZXBW = 971 + | VPMOVZXBW = 1017 /// Packed Move with Zero Extend (32-bit to 64-bit). - | VPMOVZXDQ = 972 + | VPMOVZXDQ = 1018 /// Packed Move with Zero Extend (16-bit to 32-bit). - | VPMOVZXWD = 973 + | VPMOVZXWD = 1019 /// Packed Move with Zero Extend (16-bit to 64-bit). - | VPMOVZXWQ = 974 + | VPMOVZXWQ = 1020 /// Multiply Packed Doubleword Integers. - | VPMULDQ = 975 + | VPMULDQ = 1021 /// Packed Multiply High with Round and Scale. - | VPMULHRSW = 976 + | VPMULHRSW = 1022 /// Multiply Packed Unsigned Integers and Store High Result. - | VPMULHUW = 977 + | VPMULHUW = 1023 /// Multiply Packed Signed Integers and Store High Result. - | VPMULHW = 978 + | VPMULHW = 1024 /// Multiply Packed Integers and Store Low Result. - | VPMULLD = 979 + | VPMULLD = 1025 /// Multiply Packed Integers and Store Low Result. - | VPMULLQ = 980 + | VPMULLQ = 1026 /// Multiply Packed Signed Integers and Store Low Result. - | VPMULLW = 981 + | VPMULLW = 1027 /// Multiply Packed Unsigned Doubleword Integers. - | VPMULUDQ = 982 + | VPMULUDQ = 1028 /// Bitwise Logical OR. - | VPOR = 983 + | VPOR = 1029 /// Rotate dword elem left by a constant shift count with conditional update. - | VPROLD = 984 + | VPROLD = 1030 /// Rotate qword elem left by a constant shift count with conditional update. - | VPROLQ = 985 + | VPROLQ = 1031 /// Rotate dword element left by shift counts specified. - | VPROLVD = 986 + | VPROLVD = 1032 /// Rotate qword element left by shift counts specified. - | VPROLVQ = 987 + | VPROLVQ = 1033 /// Rotate dword element right by a constant shift count. - | VPRORD = 988 + | VPRORD = 1034 /// Rotate qword element right by a constant shift count. - | VPRORQ = 989 + | VPRORQ = 1035 /// Rotate dword element right by shift counts specified. - | VPRORRD = 990 + | VPRORRD = 1036 /// Rotate qword element right by shift counts specified. - | VPRORRQ = 991 + | VPRORRQ = 1037 /// Compute Sum of Absolute Differences. - | VPSADBW = 992 + | VPSADBW = 1038 /// Scatter dword elements in a vector to memory using dword indices. - | VPSCATTERDD = 993 + | VPSCATTERDD = 1039 /// Scatter qword elements in a vector to memory using dword indices. - | VPSCATTERDQ = 994 + | VPSCATTERDQ = 1040 /// Scatter dword elements in a vector to memory using qword indices. - | VPSCATTERQD = 995 + | VPSCATTERQD = 1041 /// Scatter qword elements in a vector to memory using qword indices. - | VPSCATTERQQ = 996 + | VPSCATTERQQ = 1042 /// Packed Shuffle Bytes. - | VPSHUFB = 997 + | VPSHUFB = 1043 /// Shuffle Packed Doublewords. - | VPSHUFD = 998 + | VPSHUFD = 1044 /// Shuffle Packed High Words. - | VPSHUFHW = 999 + | VPSHUFHW = 1045 /// Shuffle Packed Low Words. - | VPSHUFLW = 1000 + | VPSHUFLW = 1046 /// Packed SIGN (byte). - | VPSIGNB = 1001 + | VPSIGNB = 1047 /// Packed SIGN (doubleword). - | VPSIGND = 1002 + | VPSIGND = 1048 /// Packed SIGN (word). - | VPSIGNW = 1003 + | VPSIGNW = 1049 /// Shift Packed Data Left Logical (doubleword). - | VPSLLD = 1004 + | VPSLLD = 1050 /// Shift Double Quadword Left Logical. - | VPSLLDQ = 1005 + | VPSLLDQ = 1051 /// Shift Packed Data Left Logical (quadword). - | VPSLLQ = 1006 + | VPSLLQ = 1052 /// Variable Bit Shift Left Logical. - | VPSLLVW = 1007 + | VPSLLVW = 1053 /// Shift Packed Data Left Logical (word). - | VPSLLW = 1008 + | VPSLLW = 1054 /// Shift Packed Data Right Arithmetic (doubleword). - | VPSRAD = 1009 + | VPSRAD = 1055 /// Shift qwords right by a constant shift count and shifting in sign bits. - | VPSRAQ = 1010 + | VPSRAQ = 1056 /// Shift qwords right by shift counts in a vector and shifting in sign bits. - | VPSRAVQ = 1011 + | VPSRAVQ = 1057 /// Variable Bit Shift Right Arithmetic. - | VPSRAVW = 1012 + | VPSRAVW = 1058 /// Shift Packed Data Right Arithmetic (word). - | VPSRAW = 1013 + | VPSRAW = 1059 /// Shift Packed Data Right Logical (doubleword). - | VPSRLD = 1014 + | VPSRLD = 1060 /// Shift Double Quadword Right Logical. - | VPSRLDQ = 1015 + | VPSRLDQ = 1061 /// Shift Packed Data Right Logical (quadword). - | VPSRLQ = 1016 + | VPSRLQ = 1062 /// Variable Bit Shift Right Logical. - | VPSRLVW = 1017 + | VPSRLVW = 1063 /// Shift Packed Data Right Logical (word). - | VPSRLW = 1018 + | VPSRLW = 1064 /// Subtract Packed Integers (byte). - | VPSUBB = 1019 + | VPSUBB = 1065 /// Subtract Packed Integers (doubleword). - | VPSUBD = 1020 + | VPSUBD = 1066 /// Subtract Packed Integers (quadword). - | VPSUBQ = 1021 + | VPSUBQ = 1067 /// Subtract Packed Signed Integers with Signed Saturation (byte). - | VPSUBSB = 1022 + | VPSUBSB = 1068 /// Subtract Packed Signed Integers with Signed Saturation (word). - | VPSUBSW = 1023 + | VPSUBSW = 1069 /// Subtract Packed Unsigned Integers with Unsigned Saturation (byte). - | VPSUBUSB = 1024 + | VPSUBUSB = 1070 /// Subtract Packed Unsigned Integers with Unsigned Saturation (word). - | VPSUBUSW = 1025 + | VPSUBUSW = 1071 /// Subtract Packed Integers (word). - | VPSUBW = 1026 + | VPSUBW = 1072 /// Perform bitwise ternary logic operation of three vectors. - | VPTERLOGD = 1027 + | VPTERLOGD = 1073 /// Perform bitwise ternary logic operation of three vectors. - | VPTERLOGQ = 1028 + | VPTERLOGQ = 1074 + /// Bitwise Ternary Logic. + | VPTERNLOGD = 1075 /// Logical Compare. - | VPTEST = 1029 + | VPTEST = 1076 /// Perform bitwise AND of byte elems of two vecs and write results to opmask. - | VPTESTMB = 1030 + | VPTESTMB = 1077 /// Perform bitwise AND of dword elems of 2-vecs and write results to opmask. - | VPTESTMD = 1031 + | VPTESTMD = 1078 /// Perform bitwise AND of qword elems of 2-vecs and write results to opmask. - | VPTESTMQ = 1032 + | VPTESTMQ = 1079 /// Perform bitwise AND of word elems of two vecs and write results to opmask. - | VPTESTMW = 1033 + | VPTESTMW = 1080 /// Perform bitwise NAND of byte elems of 2-vecs and write results to opmask. - | VPTESTNMB = 1034 + | VPTESTNMB = 1081 /// Perform bitwise NAND of dword elems of 2-vecs and write results to opmask. - | VPTESTNMD = 1035 + | VPTESTNMD = 1082 /// Perform bitwise NAND of qword elems of 2-vecs and write results to opmask. - | VPTESTNMQ = 1036 + | VPTESTNMQ = 1083 /// Perform bitwise NAND of word elems of 2-vecs and write results to opmask. - | VPTESTNMW = 1037 + | VPTESTNMW = 1084 /// Unpack High Data. - | VPUNPCKHBW = 1038 + | VPUNPCKHBW = 1085 /// Unpack High Data. - | VPUNPCKHDQ = 1039 + | VPUNPCKHDQ = 1086 /// Unpack High Data. - | VPUNPCKHQDQ = 1040 + | VPUNPCKHQDQ = 1087 /// Unpack High Data. - | VPUNPCKHWD = 1041 + | VPUNPCKHWD = 1088 /// Unpack Low Data. - | VPUNPCKLBW = 1042 + | VPUNPCKLBW = 1089 /// Unpack Low Data. - | VPUNPCKLDQ = 1043 + | VPUNPCKLDQ = 1090 /// Unpack Low Data. - | VPUNPCKLQDQ = 1044 + | VPUNPCKLQDQ = 1091 /// Unpack Low Data. - | VPUNPCKLWD = 1045 + | VPUNPCKLWD = 1092 /// Logical Exclusive OR. - | VPXOR = 1046 + | VPXOR = 1093 + /// Bitwise XOR of packed doubleword integers. + | VPXORD = 1094 + /// Bitwise XOR of packed quadword integers. + | VPXORQ = 1095 /// Range Restriction Calculation For Packed Pairs of Float64 Values. - | VRANGEPD = 1047 + | VRANGEPD = 1096 /// Range Restriction Calculation For Packed Pairs of Float32 Values. - | VRANGEPS = 1048 + | VRANGEPS = 1097 /// Range Restriction Calculation From a pair of Scalar Float64 Values. - | VRANGESD = 1049 + | VRANGESD = 1098 /// Range Restriction Calculation From a Pair of Scalar Float32 Values. - | VRANGESS = 1050 + | VRANGESS = 1099 /// Compute Approximate Reciprocals of Packed Float64 Values. - | VRCP14PD = 1051 + | VRCP14PD = 1100 /// Compute Approximate Reciprocals of Packed Float32 Values. - | VRCP14PS = 1052 + | VRCP14PS = 1101 /// Compute Approximate Reciprocal of Scalar Float64 Value. - | VRCP14SD = 1053 + | VRCP14SD = 1102 /// Compute Approximate Reciprocal of Scalar Float32 Value. - | VRCP14SS = 1054 + | VRCP14SS = 1103 /// Computes the reciprocal approximation of the float64 values. - | VRCP28PD = 1055 + | VRCP28PD = 1104 /// Computes the reciprocal approximation of the float32 values. - | VRCP28PS = 1056 + | VRCP28PS = 1105 /// Computes the reciprocal approximation of the low float64 value. - | VRCP28SD = 1057 + | VRCP28SD = 1106 /// Computes the reciprocal approximation of the low float32 value. - | VRCP28SS = 1058 + | VRCP28SS = 1107 + /// Compute reciprocals of packed single-precision floating-point values. + | VRCPPS = 1108 + /// Compute Reciprocal of Scalar Single-Precision Floating-Point Values. + | VRCPSS = 1109 /// Perform Reduction Transformation on Packed Float64 Values. - | VREDUCEPD = 1059 + | VREDUCEPD = 1110 /// Perform Reduction Transformation on Packed Float32 Values. - | VREDUCEPS = 1060 + | VREDUCEPS = 1111 /// Perform a Reduction Transformation on a Scalar Float64 Value. - | VREDUCESD = 1061 + | VREDUCESD = 1112 /// Perform a Reduction Transformation on a Scalar Float32 Value. - | VREDUCESS = 1062 + | VREDUCESS = 1113 /// Round Packed Float64 Values To Include A Given Number Of Fraction Bits. - | VRNDSCALEPD = 1063 + | VRNDSCALEPD = 1114 /// Round Packed Float32 Values To Include A Given Number Of Fraction Bits. - | VRNDSCALEPS = 1064 + | VRNDSCALEPS = 1115 /// Round Scalar Float64 Value To Include A Given Number Of Fraction Bits. - | VRNDSCALESD = 1065 + | VRNDSCALESD = 1116 /// Round Scalar Float32 Value To Include A Given Number Of Fraction Bits. - | VRNDSCALESS = 1066 + | VRNDSCALESS = 1117 + /// Round Packed Double-Precision Values. + | VROUNDPD = 1118 + /// Round Packed Single-Precision Values. + | VROUNDPS = 1119 + /// Round Scalar Double-Precision Value. + | VROUNDSD = 1120 /// Compute Approximate Reciprocals of Square Roots of Packed Float64 Values. - | VRSQRT14PD = 1067 + | VRSQRT14PD = 1121 /// Compute Approximate Reciprocals of Square Roots of Packed Float32 Values. - | VRSQRT14PS = 1068 + | VRSQRT14PS = 1122 /// Compute Approximate Reciprocal of Square Root of Scalar Float64 Value. - | VRSQRT14SD = 1069 + | VRSQRT14SD = 1123 /// Compute Approximate Reciprocal of Square Root of Scalar Float32 Value. - | VRSQRT14SS = 1070 + | VRSQRT14SS = 1124 /// Computes the reciprocal square root of the float64 values. - | VRSQRT28PD = 1071 + | VRSQRT28PD = 1125 /// Computes the reciprocal square root of the float32 values. - | VRSQRT28PS = 1072 + | VRSQRT28PS = 1126 /// Computes the reciprocal square root of the low float64 value. - | VRSQRT28SD = 1073 + | VRSQRT28SD = 1127 /// Computes the reciprocal square root of the low float32 value. - | VRSQRT28SS = 1074 + | VRSQRT28SS = 1128 + /// Compute Reciprocals of Square Roots of Packed Single-Precision FP Values. + | VRSQRTPS = 1129 + /// Compute Reciprocal of Square Root of Scalar Single-Precision FP Value. + | VRSQRTSS = 1130 /// Multiply packed DP FP elements of a vector by powers. - | VSCALEPD = 1075 + | VSCALEPD = 1131 /// Multiply packed SP FP elements of a vector by powers. - | VSCALEPS = 1076 + | VSCALEPS = 1132 /// Multiply the low DP FP element of a vector by powers. - | VSCALESD = 1077 + | VSCALESD = 1133 /// Multiply the low SP FP element of a vector by powers. - | VSCALESS = 1078 + | VSCALESS = 1134 /// Scatter SP/DP FP elements in a vector to memory using dword indices. - | VSCATTERDD = 1079 + | VSCATTERDD = 1135 /// Scatter SP/DP FP elements in a vector to memory using dword indices. - | VSCATTERDQ = 1080 + | VSCATTERDQ = 1136 /// Scatter SP/DP FP elements in a vector to memory using qword indices. - | VSCATTERQD = 1081 + | VSCATTERQD = 1137 /// Scatter SP/DP FP elements in a vector to memory using qword indices. - | VSCATTERQQ = 1082 + | VSCATTERQQ = 1138 /// Shuffle 128-bit lanes of a vector with 32 bit granular conditional update. - | VSHUFF32X4 = 1083 + | VSHUFF32X4 = 1139 /// Shuffle 128-bit lanes of a vector with 64 bit granular conditional update. - | VSHUFF64X2 = 1084 + | VSHUFF64X2 = 1140 /// Shuffle 128-bit lanes of a vector with 32 bit granular conditional update. - | VSHUFI32X4 = 1085 + | VSHUFI32X4 = 1141 /// Shuffle 128-bit lanes of a vector with 64 bit granular conditional update. - | VSHUFI64X2 = 1086 + | VSHUFI64X2 = 1142 /// Shuffle Packed Double-Precision Floating-Point Values. - | VSHUFPD = 1087 + | VSHUFPD = 1143 /// Shuffle Packed Single-Precision Floating-Point Values. - | VSHUFPS = 1088 + | VSHUFPS = 1144 /// Compute packed square roots of packed double-precision FP values. - | VSQRTPD = 1089 + | VSQRTPD = 1145 /// Compute square roots of packed single-precision floating-point values. - | VSQRTPS = 1090 + | VSQRTPS = 1146 /// Compute scalar square root of scalar double-precision FP values. - | VSQRTSD = 1091 + | VSQRTSD = 1147 /// Compute square root of scalar single-precision floating-point values. - | VSQRTSS = 1092 + | VSQRTSS = 1148 /// Subtract Packed Double-Precision Floating-Point Values. - | VSUBPD = 1093 + | VSUBPD = 1149 /// Subtract Packed Single-Precision Floating-Point Values. - | VSUBPS = 1094 + | VSUBPS = 1150 /// Subtract Scalar Double-Precision Floating-Point Values. - | VSUBSD = 1095 + | VSUBSD = 1151 /// Subtract Scalar Single-Precision Floating-Point Values. - | VSUBSS = 1096 + | VSUBSS = 1152 /// Unordered Compare Scalar Double-Precision FP Values and Set EFLAGS. - | VUCOMISD = 1097 + | VUCOMISD = 1153 /// Unordered Compare Scalar Single-Precision FPValues and Set EFLAGS. - | VUCOMISS = 1098 + | VUCOMISS = 1154 /// Unpack and Interleave High Packed Double-Precision Floating-Point Values. - | VUNPCKHPD = 1099 + | VUNPCKHPD = 1155 /// Unpack and Interleave High Packed Single-Precision Floating-Point Values. - | VUNPCKHPS = 1100 + | VUNPCKHPS = 1156 /// Unpack and Interleave Low Packed Double-Precision Floating-Point Values. - | VUNPCKLPD = 1101 + | VUNPCKLPD = 1157 /// Unpack and Interleave Low Packed Single-Precision Floating-Point Values. - | VUNPCKLPS = 1102 + | VUNPCKLPS = 1158 /// Bitwise Logical XOR for Double-Precision Floating-Point Values. - | VXORPD = 1103 + | VXORPD = 1159 /// Bitwise Logical XOR for Single-Precision Floating-Point Values. - | VXORPS = 1104 + | VXORPS = 1160 /// Zero Upper Bits of YMM Registers. - | VZEROUPPER = 1105 + | VZEROUPPER = 1161 /// Wait. - | WAIT = 1106 + | WAIT = 1162 /// Write Back and Invalidate Cache. - | WBINVD = 1107 + | WBINVD = 1163 /// Write FS Segment Base. - | WRFSBASE = 1108 + | WRFSBASE = 1164 /// Write GS Segment Base. - | WRGSBASE = 1109 + | WRGSBASE = 1165 /// Write to Model Specific Register. - | WRMSR = 1110 + | WRMSR = 1166 /// Write Data to User Page Key Register. - | WRPKRU = 1111 + | WRPKRU = 1167 /// Write to a shadow stack. - | WRSSD = 1112 + | WRSSD = 1168 /// Write to a shadow stack. - | WRSSQ = 1113 + | WRSSQ = 1169 /// Write to a user mode shadow stack. - | WRUSSD = 1114 + | WRUSSD = 1170 /// Write to a user mode shadow stack. - | WRUSSQ = 1115 + | WRUSSQ = 1171 /// Transactional Abort. - | XABORT = 1116 + | XABORT = 1172 /// Prefix hint to the beginning of an HLE transaction region. - | XACQUIRE = 1117 + | XACQUIRE = 1173 /// Exchange and Add. - | XADD = 1118 + | XADD = 1174 /// Transactional Begin. - | XBEGIN = 1119 + | XBEGIN = 1175 /// Exchange Register/Memory with Register. - | XCHG = 1120 + | XCHG = 1176 /// Transactional End. - | XEND = 1121 + | XEND = 1177 /// Value of Extended Control Register. - | XGETBV = 1122 + | XGETBV = 1178 /// Table lookup translation. - | XLAT = 1123 + | XLAT = 1179 /// Table Look-up Translation. - | XLATB = 1124 + | XLATB = 1180 /// Logical Exclusive OR. - | XOR = 1125 + | XOR = 1181 /// Bitwise Logical XOR for Double-Precision Floating-Point Values. - | XORPD = 1126 + | XORPD = 1182 /// Bitwise Logical XOR for Single-Precision Floating-Point Values. - | XORPS = 1127 + | XORPS = 1183 /// Prefix hint to the end of an HLE transaction region. - | XRELEASE = 1128 + | XRELEASE = 1184 /// Restore Processor Extended States. - | XRSTOR = 1129 + | XRSTOR = 1185 /// Restore processor supervisor-mode extended states from memory. - | XRSTORS = 1130 + | XRSTORS = 1186 /// Restore processor supervisor-mode extended states from memory. - | XRSTORS64 = 1131 + | XRSTORS64 = 1187 /// Save Processor Extended States. - | XSAVE = 1132 + | XSAVE = 1188 /// Save processor extended states with compaction to memory. - | XSAVEC = 1133 + | XSAVEC = 1189 /// Save processor extended states with compaction to memory. - | XSAVEC64 = 1134 + | XSAVEC64 = 1190 /// Save Processor Extended States Optimized. - | XSAVEOPT = 1135 + | XSAVEOPT = 1191 /// Save processor supervisor-mode extended states to memory. - | XSAVES = 1136 + | XSAVES = 1192 /// Save processor supervisor-mode extended states to memory. - | XSAVES64 = 1137 + | XSAVES64 = 1193 /// Set Extended Control Register. - | XSETBV = 1138 + | XSETBV = 1194 /// Test If In Transactional Execution. - | XTEST = 1139 + | XTEST = 1195 /// Invalid Opcode. - | InvalOP = 1140 - -/// We define 8 different RegGrp types. Intel instructions use an integer value -/// such as a REG field of a ModR/M value. -type RegGrp = - /// AL/AX/EAX/... - | RG0 = 0 - /// CL/CX/ECX/... - | RG1 = 1 - /// DL/DX/EDX/... - | RG2 = 2 - /// BL/BX/EBX/... - | RG3 = 3 - /// AH/SP/ESP/... - | RG4 = 4 - /// CH/BP/EBP/... - | RG5 = 5 - /// DH/SI/ESI/... - | RG6 = 6 - /// BH/DI/EDI/... - | RG7 = 7 - -/// Opcode Group. -type OpGroup = - | G1 = 0 - | G1Inv64 = 1 - | G1A = 2 - | G2 = 3 - | G3A = 4 - | G3B = 5 - | G4 = 6 - | G5 = 7 - | G6 = 8 - | G7 = 9 - | G8 = 10 - | G9 = 11 - | G10 = 12 - | G11A = 13 - | G11B = 14 - | G12 = 15 - | G13 = 16 - | G14 = 17 - | G15 = 18 - | G16 = 19 - | G17 = 20 - -/// Specifies the kind of operand. See Appendix A.2 of Volume 2 (Intel Manual) -type OprMode = - /// Direct address - | A = 0x1 - /// The VEX.vvvv field of the VEX prefix selects a general purpose register - | B = 0x2 - /// Bound Register - | BndR = 0x3 - /// Bound Register or memory - | BndM = 0x4 - /// The reg field of the ModR/M byte selects a control register - | C = 0x5 - /// The reg field of the ModR/M byte selects a debug register - | D = 0x6 - /// General Register or Memory - | E = 0x7 - /// General Register - | G = 0x8 - /// The VEX.vvvv field of the VEX prefix selects a 128-bit XMM register or a - /// 256-bit YMM regerister, determined by operand type - | H = 0x9 - /// Unsigned Immediate - | I = 0xa - /// Signed Immediate - | SI = 0xb - /// EIP relative offset - | J = 0xc - /// Memory - | M = 0xd - /// A ModR/M follows the opcode and specifies the operand. The operand is - /// either a 128-bit, 256-bit or 512-bit memory location. - | MZ = 0xe - /// The R/M field of the ModR/M byte selects a packed-quadword, MMX - /// technology register - | N = 0xf - /// No ModR/M byte. No base register, index register, or scaling factor - | O = 0x10 - /// The reg field of the ModR/M byte selects a packed quadword MMX technology - /// register - | P = 0x11 - /// A ModR/M byte follows the opcode and specifies the operand. The operand - /// is either an MMX technology register of a memory address - | Q = 0x12 - /// The R/M field of the ModR/M byte may refer only to a general register - | R = 0x13 - /// The reg field of the ModR/M byte selects a segment register - | S = 0x14 - /// The R/M field of the ModR/M byte selects a 128-bit XMM register or a - /// 256-bit YMM register, determined by operand type - | U = 0x15 - /// The reg field of the ModR/M byte selects a 128-bit XMM register or a - /// 256-bit YMM register, determined by operand type - | V = 0x16 - /// The reg field of the ModR/M byte selects a 128-bit XMM register or a - /// 256-bit YMM register, 512-bit ZMM register determined by operand type - | VZ = 0x17 - /// A ModR/M follows the opcode and specifies the operand. The operand is - /// either a 128-bit XMM register, a 256-bit YMM register, or a memory address - | W = 0x18 - /// A ModR/M follows the opcode and specifies the operand. The operand is - /// either a 128-bit XMM register, a 256-bit YMM register, a 512-bit ZMM - /// register or a memory address - | WZ = 0x19 - /// Memory addressed by the DS:rSI register pair. - | X = 0x1a - /// Memory addressed by the ES:rDI register pair. - | Y = 0x1b - /// The reg field of the ModR/M byte is 0b000 - | E0 = 0x1c - -/// Specifies the size of operand. See Appendix A.2 of Volume 2 -type OprSize = - /// Word/DWord depending on operand-size attribute - | A = 0x40 - /// Byte size - | B = 0x80 - /// 64-bit or 128-bit : Bound Register or Memory - | Bnd = 0xc0 - /// Doubleword, regardless of operand-size attribute - | D = 0x100 - /// Register size = Doubledword, Pointer size = Byte - | DB = 0x140 - /// Double-quadword, regardless of operand-size attribute - | DQ = 0x180 - /// Register size = Double-quadword, Pointer size = Doubleword - | DQD = 0x1c0 - /// Register size = Double-quadword, Pointer size depending on operand-size - /// attribute. If the operand-size is 128-bit, the pointer size is doubleword; - /// If the operand-size is 256-bit, the pointer size is quadword. - | DQDQ = 0x200 - /// Register size = Double-quadword, Pointer size = Quadword - | DQQ = 0x240 - /// Register size = Double-quadword, Pointer size depending on operand-size - /// attribute. If the operand-size is 128-bit, the pointer size is quadword; - /// If the operand-size is 256-bit, the pointer size is double-quadword. - | DQQDQ = 0x280 - /// Register size = Double-quadword, Pointer size = Word - | DQW = 0x2c0 - /// Register size = Doubledword, Pointer size = Word - | DW = 0x300 - /// Register size = Double-quadword, Pointer size depending on operand-size - /// attribute. If the operand-size is 128-bit, the pointer size is word; - /// If the operand-size is 256-bit, the pointer size is doubleword. - | DQWD = 0x340 - /// 32-bit, 48 bit, or 80-bit pointer, depending on operand-size attribute - | P = 0x380 - /// 128-bit or 256-bit packed double-precision floating-point data - | PD = 0x3c0 - /// Quadword MMX techonolgy register - | PI = 0x400 - /// 128-bit or 256-bit packed single-precision floating-point data - | PS = 0x440 - /// 128-bit or 256-bit packed single-precision floating-point data, pointer - /// size : Quadword - | PSQ = 0x480 - /// Quadword, regardless of operand-size attribute - | Q = 0x4c0 - /// Quad-Quadword (256-bits), regardless of operand-size attribute - | QQ = 0x500 - /// 6-byte or 10-byte pseudo-descriptor - | S = 0x540 - /// Scalar element of a 128-bit double-precision floating data - | SD = 0x580 - /// Scalar element of a 128-bit double-precision floating data, but the - /// pointer size is quadword - | SDQ = 0x5c0 - /// Scalar element of a 128-bit single-precision floating data - | SS = 0x600 - /// Scalar element of a 128-bit single-precision floating data, but the - /// pointer size is doubleword - | SSD = 0x640 - /// Scalar element of a 128-bit single-precision floating data, but the - /// pointer size is quadword - | SSQ = 0x680 - /// Word/DWord/QWord depending on operand-size attribute - | V = 0x6c0 - /// Word, regardless of operand-size attribute - | W = 0x700 - /// dq or qq based on the operand-size attribute - | X = 0x740 - /// 128-bit, 256-bit or 512-bit depending on operand-size attribute - | XZ = 0x780 - /// Doubleword or quadword (in 64-bit mode), depending on operand-size - /// attribute - | Y = 0x7c0 - /// Word for 16-bit operand-size or DWord for 32 or 64-bit operand size - | Z = 0x800 - -/// Defines attributes for registers to apply register conversion rules. -type RGrpAttr = - /// This represents the case where there is no given attribute. - | ANone = 0x0 - /// Registers defined by the 4th row of Table 2-2. Vol. 2A. - | AMod11 = 0x1 - /// Registers defined by REG bit of the opcode: some instructions such as PUSH - /// make use of its opcode to represent the REG bit. REX bits can change the - /// symbol. - | ARegInOpREX = 0x2 - /// Registers defined by REG bit of the opcode: some instructions such as PUSH - /// make use of its opcode to represent the REG bit. REX bits cannot change - /// the symbol. - | ARegInOpNoREX = 0x4 - /// Registers defined by REG field of the ModR/M byte. - | ARegBits = 0x8 - /// Base registers defined by the RM field: first three rows of Table 2-2. - | ABaseRM = 0x10 - /// Registers defined by the SIB index field. - | ASIBIdx = 0x20 - /// Registers defined by the SIB base field. - | ASIBBase = 0x40 - -/// -/// Defines four different descriptions of an instruction operand. Most of these -/// descriptions are found in Appendix A. (Opcode Map) of the manual Vol. 2D. We -/// also introduce several new descriptors for our own purpose. -/// -type OperandDesc = - /// The most generic operand kind which can be described with OprMode - /// and OprSize. - | ODModeSize of struct (OprMode * OprSize) - /// This operand is represented as a single register. - /// (e.g., mov al, 1) - | ODReg of Register - /// This operand is represented as a single opcode, and the symbol of the - /// register symbol must be resolved by looking at the register mapping table - /// (see GrpEAX for instance). - | ODRegGrp of RegGrp * OprSize * RGrpAttr - /// This operand is represented as an immediate value (of one). - | ODImmOne - -/// The scale of Scaled Index. -type Scale = - /// Times 1 - | X1 = 1 - /// Times 2 - | X2 = 2 - /// Times 4 - | X4 = 4 - /// Times 8 - | X8 = 8 - -/// Scaled index. -type ScaledIndex = Register * Scale - -/// Jump target of a branch instruction. -type JumpTarget = - | Absolute of Selector * Addr * OperandSize - | Relative of Offset -and Selector = int16 -and Offset = int64 -and OperandSize = RegType - -/// We define four different types of X86 operands: -/// register, memory, direct address, and immediate. -type Operand = - | OprReg of Register - | OprMem of Register option * ScaledIndex option * Disp option * OperandSize - | OprDirAddr of JumpTarget - | OprImm of int64 - | Label of string * RegType -/// Displacement. -and Disp = int64 - -/// A set of operands in an X86 instruction. -type Operands = - | NoOperand - | OneOperand of Operand - | TwoOperands of Operand * Operand - | ThreeOperands of Operand * Operand * Operand - | FourOperands of Operand * Operand * Operand * Operand - -/// Specific conditions for determining the size of operands. -/// (See Appendix A.2.5 of Vol. 2D). -type SizeCond = - /// Use 32-bit operands as default in 64-bit mode. - | SzDef32 - /// Use 64-bit operands as default in 64-bit mode = d64. - | SzDef64 - /// Use 64-bit operands in 64-bit mode (even with a 66 prefix) = f64. - | Sz64 - /// Only available when in 64-bit mode = o64. - | SzOnly64 - /// Invalid or not encodable in 64-bit mode = i64. - | SzInv64 - -/// Types of VEX (Vector Extension). -type VEXType = - /// Original VEX that refers to two-byte opcode map. - | VEXTwoByteOp = 0x1 - /// Original VEX that refers to three-byte opcode map #1. - | VEXThreeByteOpOne = 0x2 - /// Original VEX that refers to three-byte opcode map #2. - | VEXThreeByteOpTwo = 0x4 - /// EVEX Mask - | EVEX = 0x10 - /// Enhanced VEX that refers to two-byte opcode map. - | EVEXTwoByteOp = 0x11 - /// Original VEX that refers to three-byte opcode map #1. - | EVEXThreeByteOpOne = 0x12 - /// Original VEX that refers to three-byte opcode map #2. - | EVEXThreeByteOpTwo = 0x14 - -module internal VEXType = begin - let isOriginal (vt: VEXType) = int vt &&& 0x10 = 0 - let isEnhanced (vt: VEXType) = int vt &&& 0x10 <> 0 - let isTwoByteOp (vt: VEXType) = int vt &&& 0x1 <> 0 - let isThreeByteOpOne (vt: VEXType) = int vt &&& 0x2 <> 0 - let isThreeByteOpTwo (vt: VEXType) = int vt &&& 0x4 <> 0 -end - -/// Represents the size information of an instruction. -type InsSize = { - MemSize : MemorySize - RegSize : RegType - OperationSize : RegType - SizeCond : SizeCond -} -and MemorySize = { - EffOprSize : RegType - EffAddrSize : RegType - EffRegSize : RegType -} - -/// Intel's memory operand is represented by two tables (ModR/M and SIB table). -/// Some memory operands do need SIB table lookups, whereas some memory operands -/// only need to look up the ModR/M table. -type internal MemLookupType = - | SIB (* Need SIB lookup *) - | NOSIB of RegGrp option (* No need *) - -/// Vector destination merging/zeroing: P[23] encodes the destination result -/// behavior which either zeroes the masked elements or leave masked element -/// unchanged. -type ZeroingOrMerging = - | Zeroing - | Merging - -type EVEXPrefix = { - Z : ZeroingOrMerging - AAA : uint8 (* Embedded opmask register specifier *) -} - -/// Information about Intel vector extension. -type VEXInfo = { - VVVV : byte - VectorLength : RegType - VEXType : VEXType - VPrefixes : Prefix - VREXPrefix : REXPrefix - EVEXPrx : EVEXPrefix option -} - -/// Temporary information needed for parsing the opcode and the operands. This -/// includes prefixes, rexprefix, VEX information, and the word size. -type internal TemporaryInfo = { - /// Prefixes. - TPrefixes : Prefix - /// REX prefixes. - TREXPrefix : REXPrefix - /// VEX information. - TVEXInfo : VEXInfo option - /// Current architecture word size. - TWordSize : WordSize -} - -/// Basic information obtained by parsing an Intel instruction. -[] -type InsInfo = { - /// Prefixes. - Prefixes : Prefix - /// REX Prefix. - REXPrefix : REXPrefix - /// VEX information. - VEXInfo : VEXInfo option - /// Opcode. - Opcode : Opcode - /// Operands. - Operands : Operands - /// Instruction size information. - InsSize : InsSize -} -with - override __.GetHashCode () = - hash (__.Prefixes, - __.REXPrefix, - __.VEXInfo, - __.Opcode, - __.Operands, - __.InsSize) - override __.Equals (i) = - match i with - | :? InsInfo as i -> - i.Prefixes = __.Prefixes - && i.REXPrefix = __.REXPrefix - && i.VEXInfo = __.VEXInfo - && i.Opcode = __.Opcode - && i.Operands = __.Operands - && i.InsSize = __.InsSize - | _ -> false + | InvalOP = 1196 // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Intel/IntelOperands.fs b/src/FrontEnd/BinLifter/Intel/IntelOperands.fs new file mode 100644 index 00000000..2d839118 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelOperands.fs @@ -0,0 +1,1211 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.Intel + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.Intel.RegGroup +open B2R2.FrontEnd.BinLifter.Intel.Helper + +/// Operand descriptor, which describes the shape of operands in an instruction. +type OprDesc = + | RmGpr = 0 + | RmSeg = 1 + | RmCtrl = 2 + | RmDbg = 3 + | RMMmx = 4 + | MmMmx = 5 + | BmBnd = 6 + | RmBnd = 7 + | GprRm = 8 + | GprM = 9 + | SegRm = 10 + | BndBm = 11 + | BndRm = 12 + | CtrlRm = 13 + | DbgRm = 14 + | MmxRm = 15 + | MmxMm = 16 + | GprRMm = 17 + | RegImm8 = 18 + | Imm8Reg = 19 + | Imm8 = 20 + | Imm16 = 21 + | RegImm = 22 + | SImm8 = 23 + | Imm = 24 + | Es = 25 + | Cs = 26 + | Ss = 27 + | Ds = 28 + | Fs = 29 + | Gs = 30 + | ALDx = 31 + | EaxDx = 32 + | DxEax = 33 + | DxAL = 34 + | No = 35 + | Eax = 36 + | Ecx = 37 + | Edx = 38 + | Ebx = 39 + | Esp = 40 + | Ebp = 41 + | Esi = 42 + | Edi = 43 + | Rax = 44 + | Rcx = 45 + | Rdx = 46 + | Rbx = 47 + | Rsp = 48 + | Rbp = 49 + | Rsi = 50 + | Rdi = 51 + | RaxRax = 52 + | RaxRcx = 53 + | RaxRdx = 54 + | RaxRbx = 55 + | RaxRsp = 56 + | RaxRbp = 57 + | RaxRsi = 58 + | RaxRdi = 59 + | GprRmImm8 = 60 + | GprRmImm = 61 + | Rel8 = 62 + | Rel = 63 + | Dir = 64 + | RaxFar = 65 + | FarRax = 66 + | ALImm8 = 67 + | CLImm8 = 68 + | DLImm8 = 69 + | BLImm8 = 70 + | AhImm8 = 71 + | ChImm8 = 72 + | DhImm8 = 73 + | BhImm8 = 74 + | RaxImm = 75 + | RcxImm = 76 + | RdxImm = 77 + | RbxImm = 78 + | RspImm = 79 + | RbpImm = 80 + | RsiImm = 81 + | RdiImm = 82 + | ImmImm = 83 + | RmImm = 84 + | RmImm8 = 85 + | MmxImm8 = 86 + | Mem = 87 + | M1 = 88 + | RmCL = 89 + | XmmVvXm = 90 + | GprVvRm = 91 + | XmVvXmm = 92 + | Gpr = 93 + | XmmRmImm8 = 94 + | MmxMmImm8 = 95 + | MmxRmImm8 = 96 + | GprMmxImm8 = 97 + | XmmVvXmImm8 = 98 + | XmmVvXmXmm = 99 + | XmRegImm8 = 100 + | GprRmVv = 101 + | VvRmImm8 = 102 + | RmGprCL = 103 + | XmmXmXmm0 = 104 + | XmmXmVv = 105 + +module internal OperandParsingHelper = + /// Find a specific reg. The bitmask will be used to extract a specific REX + /// bit (R/X/B). + let inline private findReg sz rex bitmask (n: int) = + let r = int (grpEAX sz) + n + let r = + if rex = REXPrefix.NOREX then r + else + if (int rex &&& bitmask) > 0 then r + 8 + elif sz > 8 || ((n &&& 4) = 0) then r + else r + 12 + LanguagePrimitives.EnumOfValue r + + /// Registers defined by the SIB index field. + let findRegSIBIdx sz rex (n: int) = findReg sz rex 2 n + + /// Registers defined by the SIB base field, or base registers defined by the + /// RM field (first three rows of Table 2-2), or registers defined by REG bit + /// of the opcode, which can change the symbol by REX bits. + let findRegRmAndSIBBase sz rex (n: int) = findReg sz rex 1 n + + /// Registers defined by REG field of the ModR/M byte. + let findRegRBits sz rex (n: int): Register = findReg sz rex 4 n + + /// Registers defined by REG bit of the opcode: some instructions such as PUSH + /// make use of its opcode to represent the REG bit. REX bits *cannot* change + /// the symbol. + let findRegNoREX sz rex (n: int): Register = + let r = int (grpEAX sz) + n + let r = + if rex = REXPrefix.NOREX then r + else + if sz > 8 || ((n &&& 4) = 0) then r + else r + 12 + LanguagePrimitives.EnumOfValue r + + let inline getOprFromRegGrpNoREX rgrp (rhlp: ReadHelper) = + findRegNoREX rhlp.RegSize rhlp.REXPrefix rgrp |> OprReg + + let inline getOprFromRegGrpREX rgrp (rhlp: ReadHelper) = + findRegRmAndSIBBase rhlp.RegSize rhlp.REXPrefix rgrp |> OprReg + + let parseSignedImm (rhlp: ReadHelper) = function + | 1 -> rhlp.ReadInt8 () |> int64 + | 2 -> rhlp.ReadInt16 () |> int64 + | 4 -> rhlp.ReadInt32 () |> int64 + | 8 -> rhlp.ReadInt64 () + | _ -> raise ParsingFailureException + + let parseUnsignedImm (rhlp: ReadHelper) = function + | 1 -> rhlp.ReadUInt8 () |> uint64 + | 2 -> rhlp.ReadUInt16 () |> uint64 + | 4 -> rhlp.ReadUInt32 () |> uint64 + | 8 -> rhlp.ReadUInt64 () + | _ -> raise ParsingFailureException + + /// EVEX uses compressed displacement. See the manual Chap. 15 of Vol. 1. + let compressDisp vInfo disp = + match vInfo with + | None -> disp + | Some { VectorLength = 128; VEXType = t } + when t &&& VEXType.EVEX = VEXType.EVEX -> disp * 16L + | Some { VectorLength = 256; VEXType = t } + when t &&& VEXType.EVEX = VEXType.EVEX -> disp * 32L + | Some { VectorLength = 512; VEXType = t } + when t &&& VEXType.EVEX = VEXType.EVEX -> disp * 64L + | _ -> disp + + let parseOprMem (rhlp: ReadHelper) b s dispSz = + let memSz = rhlp.MemEffOprSize + if dispSz = 0 then OprMem (b, s, None, memSz) + else +#if LCACHE + rhlp.MarkHashEnd () +#endif + let disp = parseSignedImm rhlp dispSz + let disp = compressDisp rhlp.VEXInfo disp + OprMem (b, s, Some disp, memSz) + + let parseOprImm (rhlp: ReadHelper) immSize = +#if LCACHE + rhlp.MarkHashEnd () +#endif + let imm = parseUnsignedImm rhlp (RegType.toByteWidth immSize) + OprImm (int64 imm, immSize) + + let parseOprSImm (rhlp: ReadHelper) immSize = +#if LCACHE + rhlp.MarkHashEnd () +#endif + let imm = parseSignedImm rhlp (RegType.toByteWidth immSize) + OprImm (imm, immSize) + + /// The first 24 rows of Table 2-1. of the manual Vol. 2A. + /// The index of this tbl is a number that is a concatenation of (mod) and + /// (r/m) field of the ModR/M byte. Each element is a tuple of base register, + /// scaled index register, and the size of the displacement. + /// Table for scales (of SIB). This tbl is indexbed by the scale value of SIB. + let parseMEM16 rhlp modRM = + let m = getMod modRM + let rm = getRM modRM + match (m <<< 3) ||| rm with (* Concatenation of mod and rm bit *) + | 0 -> parseOprMem rhlp (Some R.BX) (Some (R.SI, Scale.X1)) 0 + | 1 -> parseOprMem rhlp (Some R.BX) (Some (R.DI, Scale.X1)) 0 + | 2 -> parseOprMem rhlp (Some R.BP) (Some (R.SI, Scale.X1)) 0 + | 3 -> parseOprMem rhlp (Some R.BP) (Some (R.DI, Scale.X1)) 0 + | 4 -> parseOprMem rhlp (Some R.SI) None 0 + | 5 -> parseOprMem rhlp (Some R.DI) None 0 + | 6 -> parseOprMem rhlp None None 2 + | 7 -> parseOprMem rhlp (Some R.BX) None 0 + (* Mod 01b *) + | 8 -> parseOprMem rhlp (Some R.BX) (Some (R.SI, Scale.X1)) 1 + | 9 -> parseOprMem rhlp (Some R.BX) (Some (R.DI, Scale.X1)) 1 + | 10 -> parseOprMem rhlp (Some R.BP) (Some (R.SI, Scale.X1)) 1 + | 11 -> parseOprMem rhlp (Some R.BP) (Some (R.DI, Scale.X1)) 1 + | 12 -> parseOprMem rhlp (Some R.SI) None 1 + | 13 -> parseOprMem rhlp (Some R.DI) None 1 + | 14 -> parseOprMem rhlp (Some R.BP) None 1 + | 15 -> parseOprMem rhlp (Some R.BX) None 1 + (* Mod 10b *) + | 16 -> parseOprMem rhlp (Some R.BX) (Some (R.SI, Scale.X1)) 2 + | 17 -> parseOprMem rhlp (Some R.BX) (Some (R.DI, Scale.X1)) 2 + | 18 -> parseOprMem rhlp (Some R.BP) (Some (R.SI, Scale.X1)) 2 + | 19 -> parseOprMem rhlp (Some R.BP) (Some (R.DI, Scale.X1)) 2 + | 20 -> parseOprMem rhlp (Some R.SI) None 2 + | 21 -> parseOprMem rhlp (Some R.DI) None 2 + | 22 -> parseOprMem rhlp (Some R.BP) None 2 + | 23 -> parseOprMem rhlp (Some R.BX) None 2 + | _ -> raise ParsingFailureException + + let inline hasREXX rexPref = rexPref &&& REXPrefix.REXX = REXPrefix.REXX + + let getScaledIndex s i (rhlp: ReadHelper) = + let rexPref = rhlp.REXPrefix + (* Handling a special case with REXX and SIB index = 0b100 (ESP) *) + if i = 0b100 && (not <| hasREXX rexPref) then None + else + let r = findRegSIBIdx rhlp.MemEffAddrSize rexPref i + Some (r, LanguagePrimitives.EnumOfValue (1 <<< s)) + + /// See Notes 1 of Table 2-3 of the manual Vol. 2A + let getSIBBaseReg b (rhlp: ReadHelper) modVal = + let rexPref = rhlp.REXPrefix + if b = int RegGrp.RG5 && modVal = 0b00uy then None + else Some (findRegRmAndSIBBase rhlp.MemEffAddrSize rexPref b) + + let inline private getSIB b = + struct ((b >>> 6) &&& 0b11, (b >>> 3) &&& 0b111, b &&& 0b111) + + let parseSIB (rhlp: ReadHelper) modVal = + let struct (s, i, b) = rhlp.ReadByte () |> int |> getSIB + let si = getScaledIndex s i rhlp + let baseReg = getSIBBaseReg b rhlp modVal + struct (si, baseReg, b) + + let baseRMReg (rhlp: ReadHelper) regGrp = + findRegRmAndSIBBase rhlp.MemEffAddrSize rhlp.REXPrefix (int regGrp) |> Some + + let sibWithDisp (rhlp: ReadHelper) b si dispSz oprSz = + let vInfo = rhlp.VEXInfo +#if LCACHE + rhlp.MarkHashEnd () +#endif + let disp = parseSignedImm rhlp dispSz + let disp = compressDisp vInfo disp + OprMem (b, si, Some disp, oprSz) + + let parseOprMemWithSIB rhlp modVal dispSz = + let struct (si, b, bgrp) = parseSIB rhlp modVal + let oprSize = rhlp.MemEffOprSize + if dispSz > 0 then sibWithDisp rhlp b si dispSz oprSize + else + if (modVal = 0b00000000uy || modVal = 0b10000000uy) + && bgrp = int RegGrp.RG5 then + sibWithDisp rhlp b si 4 oprSize + elif modVal = 0b01000000uy && bgrp = int RegGrp.RG5 then + sibWithDisp rhlp b si 1 oprSize + else OprMem (b, si, None, oprSize) + + /// RIP-relative addressing (see Section 2.2.1.6. of Vol. 2A). + let parseOprRIPRelativeMem (rhlp: ReadHelper) disp = + if rhlp.WordSize = WordSize.Bit64 then + if hasAddrSz rhlp.Prefixes then + parseOprMem rhlp (Some R.EIP) None disp + else parseOprMem rhlp (Some R.RIP) None disp + else parseOprMem rhlp None None disp + + open type RegGrp + + /// The first 24 rows of Table 2-2. of the manual Vol. 2A. + /// The index of this tbl is a number that is a concatenation of (mod) and + /// (r/m) field of the ModR/M byte. Each element is a tuple of (MemLookupType, + /// and the size of the displacement). If the first value of the tuple (register + /// group) is None, it means we need to look up the SIB tbl (Table 2-3). If + /// not, then it represents the reg group of the base reigster. + let parseMEM32 rhlp modRM = + let modVal = modRM &&& 0b11000000uy + match modVal >>> 3 ||| (modRM &&& 0b00000111uy) with + (* Mod 00b *) + | 0uy -> parseOprMem rhlp (baseRMReg rhlp RG0) None 0 + | 1uy -> parseOprMem rhlp (baseRMReg rhlp RG1) None 0 + | 2uy -> parseOprMem rhlp (baseRMReg rhlp RG2) None 0 + | 3uy -> parseOprMem rhlp (baseRMReg rhlp RG3) None 0 + | 4uy -> parseOprMemWithSIB rhlp modVal 0 + | 5uy -> parseOprRIPRelativeMem rhlp 4 + | 6uy -> parseOprMem rhlp (baseRMReg rhlp RG6) None 0 + | 7uy -> parseOprMem rhlp (baseRMReg rhlp RG7) None 0 + (* Mod 01b *) + | 8uy -> parseOprMem rhlp (baseRMReg rhlp RG0) None 1 + | 9uy -> parseOprMem rhlp (baseRMReg rhlp RG1) None 1 + | 10uy -> parseOprMem rhlp (baseRMReg rhlp RG2) None 1 + | 11uy -> parseOprMem rhlp (baseRMReg rhlp RG3) None 1 + | 12uy -> parseOprMemWithSIB rhlp modVal 1 + | 13uy -> parseOprMem rhlp (baseRMReg rhlp RG5) None 1 + | 14uy -> parseOprMem rhlp (baseRMReg rhlp RG6) None 1 + | 15uy -> parseOprMem rhlp (baseRMReg rhlp RG7) None 1 + (* Mod 10b *) + | 16uy -> parseOprMem rhlp (baseRMReg rhlp RG0) None 4 + | 17uy -> parseOprMem rhlp (baseRMReg rhlp RG1) None 4 + | 18uy -> parseOprMem rhlp (baseRMReg rhlp RG2) None 4 + | 19uy -> parseOprMem rhlp (baseRMReg rhlp RG3) None 4 + | 20uy -> parseOprMemWithSIB rhlp modVal 4 + | 21uy -> parseOprMem rhlp (baseRMReg rhlp RG5) None 4 + | 22uy -> parseOprMem rhlp (baseRMReg rhlp RG6) None 4 + | 23uy -> parseOprMem rhlp (baseRMReg rhlp RG7) None 4 + | _ -> raise ParsingFailureException + + let parseMemory modRM (rhlp: ReadHelper) = + if rhlp.MemEffAddrSize = 16 then parseMEM16 rhlp modRM + else parseMEM32 rhlp modRM + + let parseMemOrReg modRM (rhlp: ReadHelper) = + if modRM &&& 0b11000000uy = 0b11000000uy then + findRegRmAndSIBBase rhlp.MemEffRegSize rhlp.REXPrefix (getRM modRM) + |> OprReg + else parseMemory modRM rhlp + + let parseVVVVReg (rhlp: ReadHelper) = + match rhlp.VEXInfo with + | None -> raise ParsingFailureException + | Some vInfo when vInfo.VectorLength = 512 -> + Register.make (int vInfo.VVVV) Register.Kind.ZMM 512 |> OprReg + | Some vInfo when vInfo.VectorLength = 256 -> + Register.make (int vInfo.VVVV) Register.Kind.YMM 256 |> OprReg + | Some vInfo -> + Register.make (int vInfo.VVVV) Register.Kind.XMM 128 |> OprReg + + let parseVEXtoGPR (rhlp: ReadHelper) = + match rhlp.VEXInfo with + | None -> raise ParsingFailureException + | Some vInfo -> + let grp = (int vInfo.VVVV) &&& 0b111 + int (grpEAX rhlp.RegSize) + grp + |> LanguagePrimitives.EnumOfValue + |> OprReg + + let parseMMXReg n = Register.make n Register.Kind.MMX 64 |> OprReg + + let parseSegReg n = Register.make n Register.Kind.Segment 16 |> OprReg + + let parseBoundRegister n = Register.make n Register.Kind.Bound 128 |> OprReg + + let parseControlReg n = Register.make n Register.Kind.Control 32 |> OprReg + + let parseDebugReg n = Register.make n Register.Kind.Debug 0 |> OprReg + + let parseOprOnlyDisp (rhlp: ReadHelper) = + RegType.toByteWidth rhlp.MemEffAddrSize + |> parseOprMem rhlp None None + + let getImmZ (rhlp: ReadHelper) = + if rhlp.MemEffOprSize = 64 || rhlp.MemEffOprSize = 32 then 32 + else rhlp.MemEffOprSize + + let opGprImm rhlp regGrp = + let o1 = getOprFromRegGrpREX (int regGrp) rhlp + let o2 = parseOprSImm rhlp rhlp.MemEffOprSize + TwoOperands (o1, o2) + + let parseOprForRelJmp (rhlp: ReadHelper) immSz = +#if LCACHE + rhlp.MarkHashEnd () +#endif + let immSz = RegType.toByteWidth immSz + let offset = parseSignedImm rhlp immSz + let relOffset = offset + int64 (rhlp.ParsedLen ()) + OprDirAddr (Relative (relOffset)) + +open OperandParsingHelper + +type internal OpRmGpr () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMemOrReg modRM rhlp + let opr2 = + findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + TwoOperands (opr1, opr2) + +type internal OpRmSeg () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMemOrReg modRM rhlp + let opr2 = parseSegReg (getReg modRM) + TwoOperands (opr1, opr2) + +type internal OpRmCtrl () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMemOrReg modRM rhlp + let opr2 = parseControlReg (getReg modRM) + TwoOperands (opr1, opr2) + +type internal OpRmDbg () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMemOrReg modRM rhlp + let opr2 = parseDebugReg (getReg modRM) + TwoOperands (opr1, opr2) + +type internal OpRMMmx () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMemOrReg modRM rhlp + let opr2 = parseMMXReg (getReg modRM) + TwoOperands (opr1, opr2) + +type internal OpMmMmx () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = + if modIsReg modRM then parseMMXReg (getRM modRM) + else parseMemory modRM rhlp + let opr2 = parseMMXReg (getReg modRM) + TwoOperands (opr1, opr2) + +type internal OpBmBnd () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = + if modIsReg modRM then parseBoundRegister (getRM modRM) + else parseMemory modRM rhlp + let opr2 = parseBoundRegister (getReg modRM) + TwoOperands (opr1, opr2) + +type internal OpRmBnd () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMemOrReg modRM rhlp + let opr2 = parseBoundRegister (getReg modRM) + TwoOperands (opr1, opr2) + +type internal OpGprRm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = + findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr2 = parseMemOrReg modRM rhlp + TwoOperands (opr1, opr2) + +type internal OpGprM () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + if modIsMemory modRM then + let opr1 = + findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr2 = parseMemory modRM rhlp + TwoOperands (opr1, opr2) + else raise ParsingFailureException + +type internal OpSegRm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseSegReg (getReg modRM) + let opr2 = parseMemOrReg modRM rhlp + TwoOperands (opr1, opr2) + +type internal OpBndBm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseBoundRegister (getReg modRM) + let opr2 = + if modIsReg modRM then parseBoundRegister (getRM modRM) + else parseMemory modRM rhlp + TwoOperands (opr1, opr2) + +type internal OpBndRm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseBoundRegister (getReg modRM) + let opr2 = parseMemOrReg modRM rhlp + TwoOperands (opr1, opr2) + +type internal OpCtrlRm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseControlReg (getReg modRM) + let opr2 = parseMemOrReg modRM rhlp + TwoOperands (opr1, opr2) + +type internal OpDbgRm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseDebugReg (getReg modRM) + let opr2 = parseMemOrReg modRM rhlp + TwoOperands (opr1, opr2) + +type internal OpMmxRm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMMXReg (getReg modRM) + let opr2 = + if modIsReg modRM then parseMMXReg (getRM modRM) + else parseMemory modRM rhlp + TwoOperands (opr1, opr2) + +type internal OpMmxMm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMMXReg (getReg modRM) + let opr2 = parseMemOrReg modRM rhlp + TwoOperands (opr1, opr2) + +type internal OpGprRMm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = + findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr2 = + if modIsReg modRM then parseMMXReg (getRM modRM) + else parseMemOrReg modRM rhlp + TwoOperands (opr1, opr2) + +type internal OpRegImm8 () = + inherit OperandParser () + override __.Render rhlp = + let o1 = getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + let o2 = parseOprImm rhlp 8 + TwoOperands (o1, o2) + +type internal OpImm8Reg () = + inherit OperandParser () + override __.Render rhlp = + let o1 = parseOprImm rhlp 8 + let o2 = getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + TwoOperands (o1, o2) + +type internal OpImm8 () = + inherit OperandParser () + override __.Render rhlp = + let opr = parseOprImm rhlp 8 + OneOperand opr + +type internal OpImm16 () = + inherit OperandParser () + override __.Render rhlp = + let opr = parseOprImm rhlp 16 + OneOperand opr + +type internal OpRegImm () = + inherit OperandParser () + override __.Render rhlp = + let o1 = getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + let o2 = parseOprSImm rhlp (getImmZ rhlp) + TwoOperands (o1, o2) + +type internal OpSImm8 () = + inherit OperandParser () + override __.Render rhlp = + let opr = parseOprSImm rhlp 8 + OneOperand opr + +type internal OpImm () = + inherit OperandParser () + override __.Render rhlp = + let opr = parseOprSImm rhlp (getImmZ rhlp) + OneOperand opr + +type internal OpEs () = + inherit OperandParser () + override __.Render _rhlp = + OneOperand (OprReg R.ES) + +type internal OpCs () = + inherit OperandParser () + override __.Render _rhlp = + OneOperand (OprReg R.CS) + +type internal OpSs () = + inherit OperandParser () + override __.Render _rhlp = + OneOperand (OprReg R.SS) + +type internal OpDs () = + inherit OperandParser () + override __.Render _rhlp = + OneOperand (OprReg R.DS) + +type internal OpFs () = + inherit OperandParser () + override __.Render _rhlp = + OneOperand (OprReg R.FS) + +type internal OpGs () = + inherit OperandParser () + override __.Render _rhlp = + OneOperand (OprReg R.GS) + +type internal OpALDx () = + inherit OperandParser () + override __.Render _rhlp = + TwoOperands (OprReg R.AL, OprReg R.DX) + +type internal OpEaxDx () = + inherit OperandParser () + override __.Render rhlp = + let reg = if hasOprSz rhlp.Prefixes then R.AX else R.EAX + TwoOperands (OprReg reg, OprReg R.DX) + +type internal OpDxEax () = + inherit OperandParser () + override __.Render rhlp = + let reg = if hasOprSz rhlp.Prefixes then R.AX else R.EAX + TwoOperands (OprReg R.DX, OprReg reg) + +type internal OpDxAL () = + inherit OperandParser () + override __.Render rhlp = + TwoOperands (OprReg R.DX, OprReg R.AL) + +type internal OpNo () = + inherit OperandParser () + override __.Render rhlp = + NoOperand + +type internal OpEax () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + OneOperand o + +type internal OpEcx () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpNoREX (int RegGrp.RG1) rhlp + OneOperand o + +type internal OpEdx () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpNoREX (int RegGrp.RG2) rhlp + OneOperand o + +type internal OpEbx () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpNoREX (int RegGrp.RG3) rhlp + OneOperand o + +type internal OpEsp () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpNoREX (int RegGrp.RG4) rhlp + OneOperand o + +type internal OpEbp () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpNoREX (int RegGrp.RG5) rhlp + OneOperand o + +type internal OpEsi () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpNoREX (int RegGrp.RG6) rhlp + OneOperand o + +type internal OpEdi () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpNoREX (int RegGrp.RG7) rhlp + OneOperand o + +type internal OpRax () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpREX (int RegGrp.RG0) rhlp + OneOperand o + +type internal OpRcx () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpREX (int RegGrp.RG1) rhlp + OneOperand o + +type internal OpRdx () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpREX (int RegGrp.RG2) rhlp + OneOperand o + +type internal OpRbx () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpREX (int RegGrp.RG3) rhlp + OneOperand o + +type internal OpRsp () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpREX (int RegGrp.RG4) rhlp + OneOperand o + +type internal OpRbp () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpREX (int RegGrp.RG5) rhlp + OneOperand o + +type internal OpRsi () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpREX (int RegGrp.RG6) rhlp + OneOperand o + +type internal OpRdi () = + inherit OperandParser () + override __.Render rhlp = + let o = getOprFromRegGrpREX (int RegGrp.RG7) rhlp + OneOperand o + +type internal OpRaxRax () = + inherit OperandParser () + override __.Render rhlp = + let o1 = + getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + let o2 = + getOprFromRegGrpREX (int RegGrp.RG0) rhlp + TwoOperands (o1, o2) + +type internal OpRaxRcx () = + inherit OperandParser () + override __.Render rhlp = + let o1 = + getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + let o2 = getOprFromRegGrpREX (int RegGrp.RG1) rhlp + TwoOperands (o1, o2) + +type internal OpRaxRdx () = + inherit OperandParser () + override __.Render rhlp = + let o1 = + getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + let o2 = + getOprFromRegGrpREX (int RegGrp.RG2) rhlp + TwoOperands (o1, o2) + +type internal OpRaxRbx () = + inherit OperandParser () + override __.Render rhlp = + let o1 = + getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + let o2 = getOprFromRegGrpREX (int RegGrp.RG3) rhlp + TwoOperands (o1, o2) + +type internal OpRaxRsp () = + inherit OperandParser () + override __.Render rhlp = + let o1 = + getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + let o2 = getOprFromRegGrpREX (int RegGrp.RG4) rhlp + TwoOperands (o1, o2) + +type internal OpRaxRbp () = + inherit OperandParser () + override __.Render rhlp = + let o1 = + getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + let o2 = getOprFromRegGrpREX (int RegGrp.RG5) rhlp + TwoOperands (o1, o2) + +type internal OpRaxRsi () = + inherit OperandParser () + override __.Render rhlp = + let o1 = + getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + let o2 = getOprFromRegGrpREX (int RegGrp.RG6) rhlp + TwoOperands (o1, o2) + +type internal OpRaxRdi () = + inherit OperandParser () + override __.Render rhlp = + let o1 = + getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + let o2 = getOprFromRegGrpREX (int RegGrp.RG7) rhlp + TwoOperands (o1, o2) + +type internal OpGprRmImm8 () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let o1 = + findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let o2 = parseMemOrReg modRM rhlp + let opr3 = parseOprSImm rhlp 8 + ThreeOperands (o1, o2, opr3) + +type internal OpGprRmImm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let o1 = + findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let o2 = parseMemOrReg modRM rhlp + let opr3 = parseOprSImm rhlp (getImmZ rhlp) + ThreeOperands (o1, o2, opr3) + +type internal OpRel8 () = + inherit OperandParser () + override __.Render rhlp = + let opr = parseOprForRelJmp rhlp 8 + OneOperand opr + +type internal OpRel () = + inherit OperandParser () + override __.Render rhlp = + let opr = parseOprForRelJmp rhlp (getImmZ rhlp) + OneOperand opr + +type internal OpDir () = + inherit OperandParser () + override __.Render rhlp = + let addrSz = RegType.toByteWidth rhlp.MemEffAddrSize + let addrValue = parseUnsignedImm rhlp addrSz + let selector = rhlp.ReadInt16 () + let absAddr = Absolute (selector, addrValue, RegType.fromByteWidth addrSz) + let opr = OprDirAddr absAddr + OneOperand opr + +type internal OpRaxFar () = + inherit OperandParser () + override __.Render rhlp = + let o1 = + getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + let o2 = parseOprOnlyDisp rhlp + TwoOperands (o1, o2) + +type internal OpFarRax () = + inherit OperandParser () + override __.Render rhlp = + let o1 = parseOprOnlyDisp rhlp + let o2 = + getOprFromRegGrpNoREX (int RegGrp.RG0) rhlp + TwoOperands (o1, o2) + +type internal OpALImm8 () = + inherit OperandParser () + override __.Render rhlp = + let o1 = getOprFromRegGrpREX (int RegGrp.RG0) rhlp + let o2 = parseOprImm rhlp 8 + TwoOperands (o1, o2) + +type internal OpCLImm8 () = + inherit OperandParser () + override __.Render rhlp = + let o1 = getOprFromRegGrpREX (int RegGrp.RG1) rhlp + let o2 = parseOprImm rhlp 8 + TwoOperands (o1, o2) + +type internal OpDLImm8 () = + inherit OperandParser () + override __.Render rhlp = + let o1 = getOprFromRegGrpREX (int RegGrp.RG2) rhlp + let o2 = parseOprImm rhlp 8 + TwoOperands (o1, o2) + +type internal OpBLImm8 () = + inherit OperandParser () + override __.Render rhlp = + let o1 = getOprFromRegGrpREX (int RegGrp.RG3) rhlp + let o2 = parseOprImm rhlp 8 + TwoOperands (o1, o2) + +type internal OpAhImm8 () = + inherit OperandParser () + override __.Render rhlp = + let o1 = getOprFromRegGrpREX (int RegGrp.RG4) rhlp + let o2 = parseOprImm rhlp 8 + TwoOperands (o1, o2) + +type internal OpChImm8 () = + inherit OperandParser () + override __.Render rhlp = + let o1 = getOprFromRegGrpREX (int RegGrp.RG5) rhlp + let o2 = parseOprImm rhlp 8 + TwoOperands (o1, o2) + +type internal OpDhImm8 () = + inherit OperandParser () + override __.Render rhlp = + let o1 = getOprFromRegGrpREX (int RegGrp.RG6) rhlp + let o2 = parseOprImm rhlp 8 + TwoOperands (o1, o2) + +type internal OpBhImm8 () = + inherit OperandParser () + override __.Render rhlp = + let o1 = getOprFromRegGrpREX (int RegGrp.RG7) rhlp + let o2 = parseOprImm rhlp 8 + TwoOperands (o1, o2) + +type internal OpRaxImm () = + inherit OperandParser () + override __.Render rhlp = + opGprImm rhlp RegGrp.RG0 + +type internal OpRcxImm () = + inherit OperandParser () + override __.Render rhlp = + opGprImm rhlp RegGrp.RG1 + +type internal OpRdxImm () = + inherit OperandParser () + override __.Render rhlp = + opGprImm rhlp RegGrp.RG2 + +type internal OpRbxImm () = + inherit OperandParser () + override __.Render rhlp = + opGprImm rhlp RegGrp.RG3 + +type internal OpRspImm () = + inherit OperandParser () + override __.Render rhlp = + opGprImm rhlp RegGrp.RG4 + +type internal OpRbpImm () = + inherit OperandParser () + override __.Render rhlp = + opGprImm rhlp RegGrp.RG5 + +type internal OpRsiImm () = + inherit OperandParser () + override __.Render rhlp = + opGprImm rhlp RegGrp.RG6 + +type internal OpRdiImm () = + inherit OperandParser () + override __.Render rhlp = + opGprImm rhlp RegGrp.RG7 + +type internal OpImmImm () = + inherit OperandParser () + override __.Render rhlp = + let opr1 = parseOprImm rhlp 16 + let opr2 = parseOprImm rhlp 8 + TwoOperands (opr1, opr2) + +type internal OpRmImm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMemOrReg modRM rhlp + let opr2 = parseOprSImm rhlp (getImmZ rhlp) + TwoOperands (opr1, opr2) + +type internal OpRmImm8 () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMemOrReg modRM rhlp + let opr2 = parseOprSImm rhlp 8 + TwoOperands (opr1, opr2) + +type internal OpMmxImm8 () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = + if modIsReg modRM then parseMMXReg (getRM modRM) + else parseMemory modRM rhlp + let opr2 = parseOprSImm rhlp 8 + TwoOperands (opr1, opr2) + +type internal OpMem () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr = parseMemOrReg modRM rhlp + OneOperand opr + +type internal OpM1 () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr = parseMemOrReg modRM rhlp + TwoOperands (opr, OprImm (1L, 0)) + +type internal OpRmCL () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr = parseMemOrReg modRM rhlp + TwoOperands (opr, OprReg R.CL) + +type internal OpXmmVvXm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = + findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr3 = parseMemOrReg modRM rhlp + let oprs = ThreeOperands (opr1, parseVVVVReg rhlp, opr3) + oprs + +type internal OpGprVvRm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = + findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr2 = parseVEXtoGPR rhlp + let opr3 = parseMemOrReg modRM rhlp + ThreeOperands (opr1, opr2, opr3) + +type internal OpXmVvXmm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMemOrReg modRM rhlp + let opr3 = + findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + ThreeOperands (opr1, parseVVVVReg rhlp, opr3) + +type internal OpGpr () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr = + findRegRmAndSIBBase rhlp.RegSize rhlp.REXPrefix (getRM modRM) |> OprReg + OneOperand opr + +type internal OpXmmRmImm8 () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = + findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr2 = parseMemOrReg modRM rhlp + let opr3 = parseOprImm rhlp 8 + ThreeOperands (opr1, opr2, opr3) + +type internal OpMmxMmImm8 () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMMXReg (getReg modRM) + let opr2 = + if modIsReg modRM then parseMMXReg (getRM modRM) + else parseMemory modRM rhlp + let opr3 = parseOprImm rhlp 8 + ThreeOperands (opr1, opr2, opr3) + +type internal OpMmxRmImm8 () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMMXReg (getReg modRM) + let opr2 = parseMemOrReg modRM rhlp + let opr3 = parseOprImm rhlp 8 + ThreeOperands (opr1, opr2, opr3) + +type internal OpGprMmxImm8 () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr2 = + if modIsReg modRM then parseMMXReg (getRM modRM) + else parseMemory modRM rhlp + let opr3 = parseOprImm rhlp 8 + ThreeOperands (opr1, opr2, opr3) + +type internal OpXmmVvXmImm8 () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr2 = parseVVVVReg rhlp + let opr3 = parseMemOrReg modRM rhlp + let opr4 = parseOprImm rhlp 8 + FourOperands (opr1, opr2, opr3, opr4) + +type internal OpXmmVvXmXmm () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr2 = parseVVVVReg rhlp + let opr3 = parseMemOrReg modRM rhlp + let imm8 = (rhlp.ReadUInt8 () >>> 4) &&& 0b1111uy |> int (* imm8[7:4] *) + let opr4 = findRegRBits rhlp.RegSize rhlp.REXPrefix imm8 |> OprReg + FourOperands (opr1, opr2, opr3, opr4) + +type internal OpXmRegImm8 () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMemOrReg modRM rhlp + let opr2 = findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr3 = parseOprImm rhlp 8 + ThreeOperands (opr1, opr2, opr3) + +type internal OpGprRmVv () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr2 = parseMemOrReg modRM rhlp + let opr3 = parseVEXtoGPR rhlp + ThreeOperands (opr1, opr2, opr3) + +type internal OpVvRmImm8 () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr2 = parseMemOrReg modRM rhlp + let opr3 = parseOprImm rhlp 8 + ThreeOperands (parseVVVVReg rhlp, opr2, opr3) + +type internal OpRmGprCL () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = parseMemOrReg modRM rhlp + let opr2 = findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr3 = Register.CL |> OprReg + ThreeOperands (opr1, opr2, opr3) + +type internal OpXmmXmXmm0 () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr2 = parseMemOrReg modRM rhlp + ThreeOperands (opr1, opr2, OprReg R.XMM0) + +type internal OpXmmXmVv () = + inherit OperandParser () + override __.Render rhlp = + let modRM = rhlp.ReadByte () + let opr1 = findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr2 = parseMemOrReg modRM rhlp + ThreeOperands (opr1, opr2, parseVVVVReg rhlp) diff --git a/src/FrontEnd/BinLifter/Intel/IntelParser.fs b/src/FrontEnd/BinLifter/Intel/IntelParser.fs new file mode 100644 index 00000000..b6d82eaf --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelParser.fs @@ -0,0 +1,542 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.Intel + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.FrontEnd.BinLifter.Intel.Helper +open LanguagePrimitives +open type Prefix + +/// Parser for Intel (x86 or x86-64) instructions. Parser will return a +/// platform-agnostic instruction type (Instruction). +type IntelParser (wordSz) = + inherit Parser () + + let oparsers = + [| OpRmGpr () :> OperandParser + OpRmSeg () :> OperandParser + OpRmCtrl () :> OperandParser + OpRmDbg () :> OperandParser + OpRMMmx () :> OperandParser + OpMmMmx () :> OperandParser + OpBmBnd () :> OperandParser + OpRmBnd () :> OperandParser + OpGprRm () :> OperandParser + OpGprM () :> OperandParser + OpSegRm () :> OperandParser + OpBndBm () :> OperandParser + OpBndRm () :> OperandParser + OpCtrlRm () :> OperandParser + OpDbgRm () :> OperandParser + OpMmxRm () :> OperandParser + OpMmxMm () :> OperandParser + OpGprRMm () :> OperandParser + OpRegImm8 () :> OperandParser + OpImm8Reg () :> OperandParser + OpImm8 () :> OperandParser + OpImm16 () :> OperandParser + OpRegImm () :> OperandParser + OpSImm8 () :> OperandParser + OpImm () :> OperandParser + OpEs () :> OperandParser + OpCs () :> OperandParser + OpSs () :> OperandParser + OpDs () :> OperandParser + OpFs () :> OperandParser + OpGs () :> OperandParser + OpALDx () :> OperandParser + OpEaxDx () :> OperandParser + OpDxEax () :> OperandParser + OpDxAL () :> OperandParser + OpNo () :> OperandParser + OpEax () :> OperandParser + OpEcx () :> OperandParser + OpEdx () :> OperandParser + OpEbx () :> OperandParser + OpEsp () :> OperandParser + OpEbp () :> OperandParser + OpEsi () :> OperandParser + OpEdi () :> OperandParser + OpRax () :> OperandParser + OpRcx () :> OperandParser + OpRdx () :> OperandParser + OpRbx () :> OperandParser + OpRsp () :> OperandParser + OpRbp () :> OperandParser + OpRsi () :> OperandParser + OpRdi () :> OperandParser + OpRaxRax () :> OperandParser + OpRaxRcx () :> OperandParser + OpRaxRdx () :> OperandParser + OpRaxRbx () :> OperandParser + OpRaxRsp () :> OperandParser + OpRaxRbp () :> OperandParser + OpRaxRsi () :> OperandParser + OpRaxRdi () :> OperandParser + OpGprRmImm8 () :> OperandParser + OpGprRmImm () :> OperandParser + OpRel8 () :> OperandParser + OpRel () :> OperandParser + OpDir () :> OperandParser + OpRaxFar () :> OperandParser + OpFarRax () :> OperandParser + OpALImm8 () :> OperandParser + OpCLImm8 () :> OperandParser + OpDLImm8 () :> OperandParser + OpBLImm8 () :> OperandParser + OpAhImm8 () :> OperandParser + OpChImm8 () :> OperandParser + OpDhImm8 () :> OperandParser + OpBhImm8 () :> OperandParser + OpRaxImm () :> OperandParser + OpRcxImm () :> OperandParser + OpRdxImm () :> OperandParser + OpRbxImm () :> OperandParser + OpRspImm () :> OperandParser + OpRbpImm () :> OperandParser + OpRsiImm () :> OperandParser + OpRdiImm () :> OperandParser + OpImmImm () :> OperandParser + OpRmImm () :> OperandParser + OpRmImm8 () :> OperandParser + OpMmxImm8 () :> OperandParser + OpMem () :> OperandParser + OpM1 () :> OperandParser + OpRmCL () :> OperandParser + OpXmmVvXm () :> OperandParser + OpGprVvRm () :> OperandParser + OpXmVvXmm () :> OperandParser + OpGpr () :> OperandParser + OpXmmRmImm8 () :> OperandParser + OpMmxMmImm8 () :> OperandParser + OpMmxRmImm8 () :> OperandParser + OpGprMmxImm8 () :> OperandParser + OpXmmVvXmImm8 () :> OperandParser + OpXmmVvXmXmm () :> OperandParser + OpXmRegImm8 () :> OperandParser + OpGprRmVv () :> OperandParser + OpVvRmImm8 () :> OperandParser + OpRmGprCL () :> OperandParser + OpXmmXmXmm0 () :> OperandParser + OpXmmXmVv () :> OperandParser |] + + let szcomputers = + [| SzByte () :> InsSizeComputer + SzWord () :> InsSizeComputer + SzDef () :> InsSizeComputer + SzVecDef () :> InsSizeComputer + SzDV () :> InsSizeComputer + SzD () :> InsSizeComputer + SzMemW () :> InsSizeComputer + SzRegW () :> InsSizeComputer + SzWV () :> InsSizeComputer + SzD64 () :> InsSizeComputer + SzPZ () :> InsSizeComputer + SzDqDq () :> InsSizeComputer + SzDqdDq () :> InsSizeComputer + SzDqdDqMR () :> InsSizeComputer + SzDqqDq () :> InsSizeComputer + SzDqqDqMR () :> InsSizeComputer + SzXqX () :> InsSizeComputer + SzDqqDqWS () :> InsSizeComputer + SzVyDq () :> InsSizeComputer + SzVyDqMR () :> InsSizeComputer + SzDY () :> InsSizeComputer + SzQDq () :> InsSizeComputer + SzDqqQ () :> InsSizeComputer + SzDqQ () :> InsSizeComputer + SzDqdY () :> InsSizeComputer + SzDqqY () :> InsSizeComputer + SzDqY () :> InsSizeComputer + SzDq () :> InsSizeComputer + SzDQ () :> InsSizeComputer + SzQQ () :> InsSizeComputer + SzYQ () :> InsSizeComputer + SzYQRM () :> InsSizeComputer + SzDwQ () :> InsSizeComputer + SzDwDq () :> InsSizeComputer + SzDwDqMR () :> InsSizeComputer + SzQD () :> InsSizeComputer + SzDqd () :> InsSizeComputer + SzXDq () :> InsSizeComputer + SzDqX () :> InsSizeComputer + SzXD () :> InsSizeComputer + SzDqqdqX () :> InsSizeComputer + SzDqddqX () :> InsSizeComputer + SzDqwDq () :> InsSizeComputer + SzDqwX () :> InsSizeComputer + SzDqQqq () :> InsSizeComputer + SzDqbX () :> InsSizeComputer + SzDbDq () :> InsSizeComputer + SzBV () :> InsSizeComputer + SzQ () :> InsSizeComputer + SzS () :> InsSizeComputer + SzDX () :> InsSizeComputer + SzDqdXz () :> InsSizeComputer + SzDqqX () :> InsSizeComputer + SzP () :> InsSizeComputer + SzPRM () :> InsSizeComputer + SzXqXz () :> InsSizeComputer + SzXXz () :> InsSizeComputer + SzXzX () :> InsSizeComputer + SzXzXz () :> InsSizeComputer + SzDqqQq () :> InsSizeComputer + SzDqqXz () :> InsSizeComputer + SzQqXz () :> InsSizeComputer + SzQqXzRM () :> InsSizeComputer + SzDqdX () :> InsSizeComputer + SzDXz () :> InsSizeComputer + SzQXz () :> InsSizeComputer + SzDqQq () :> InsSizeComputer + SzDqXz () :> InsSizeComputer + SzYDq () :> InsSizeComputer |] + + let oneByteParsers = + [| OneOp00 () :> ParsingJob + OneOp01 () :> ParsingJob + OneOp02 () :> ParsingJob + OneOp03 () :> ParsingJob + OneOp04 () :> ParsingJob + OneOp05 () :> ParsingJob + OneOp06 () :> ParsingJob + OneOp07 () :> ParsingJob + OneOp08 () :> ParsingJob + OneOp09 () :> ParsingJob + OneOp0A () :> ParsingJob + OneOp0B () :> ParsingJob + OneOp0C () :> ParsingJob + OneOp0D () :> ParsingJob + OneOp0E () :> ParsingJob + OneOp0F () :> ParsingJob + OneOp10 () :> ParsingJob + OneOp11 () :> ParsingJob + OneOp12 () :> ParsingJob + OneOp13 () :> ParsingJob + OneOp14 () :> ParsingJob + OneOp15 () :> ParsingJob + OneOp16 () :> ParsingJob + OneOp17 () :> ParsingJob + OneOp18 () :> ParsingJob + OneOp19 () :> ParsingJob + OneOp1A () :> ParsingJob + OneOp1B () :> ParsingJob + OneOp1C () :> ParsingJob + OneOp1D () :> ParsingJob + OneOp1E () :> ParsingJob + OneOp1F () :> ParsingJob + OneOp20 () :> ParsingJob + OneOp21 () :> ParsingJob + OneOp22 () :> ParsingJob + OneOp23 () :> ParsingJob + OneOp24 () :> ParsingJob + OneOp25 () :> ParsingJob + OneOp26 () :> ParsingJob + OneOp27 () :> ParsingJob + OneOp28 () :> ParsingJob + OneOp29 () :> ParsingJob + OneOp2A () :> ParsingJob + OneOp2B () :> ParsingJob + OneOp2C () :> ParsingJob + OneOp2D () :> ParsingJob + OneOp2E () :> ParsingJob + OneOp2F () :> ParsingJob + OneOp30 () :> ParsingJob + OneOp31 () :> ParsingJob + OneOp32 () :> ParsingJob + OneOp33 () :> ParsingJob + OneOp34 () :> ParsingJob + OneOp35 () :> ParsingJob + OneOp36 () :> ParsingJob + OneOp37 () :> ParsingJob + OneOp38 () :> ParsingJob + OneOp39 () :> ParsingJob + OneOp3A () :> ParsingJob + OneOp3B () :> ParsingJob + OneOp3C () :> ParsingJob + OneOp3D () :> ParsingJob + OneOp3E () :> ParsingJob + OneOp3F () :> ParsingJob + OneOp40 () :> ParsingJob + OneOp41 () :> ParsingJob + OneOp42 () :> ParsingJob + OneOp43 () :> ParsingJob + OneOp44 () :> ParsingJob + OneOp45 () :> ParsingJob + OneOp46 () :> ParsingJob + OneOp47 () :> ParsingJob + OneOp48 () :> ParsingJob + OneOp49 () :> ParsingJob + OneOp4A () :> ParsingJob + OneOp4B () :> ParsingJob + OneOp4C () :> ParsingJob + OneOp4D () :> ParsingJob + OneOp4E () :> ParsingJob + OneOp4F () :> ParsingJob + OneOp50 () :> ParsingJob + OneOp51 () :> ParsingJob + OneOp52 () :> ParsingJob + OneOp53 () :> ParsingJob + OneOp54 () :> ParsingJob + OneOp55 () :> ParsingJob + OneOp56 () :> ParsingJob + OneOp57 () :> ParsingJob + OneOp58 () :> ParsingJob + OneOp59 () :> ParsingJob + OneOp5A () :> ParsingJob + OneOp5B () :> ParsingJob + OneOp5C () :> ParsingJob + OneOp5D () :> ParsingJob + OneOp5E () :> ParsingJob + OneOp5F () :> ParsingJob + OneOp60 () :> ParsingJob + OneOp61 () :> ParsingJob + OneOp62 () :> ParsingJob + OneOp63 () :> ParsingJob + OneOp64 () :> ParsingJob + OneOp65 () :> ParsingJob + OneOp66 () :> ParsingJob + OneOp67 () :> ParsingJob + OneOp68 () :> ParsingJob + OneOp69 () :> ParsingJob + OneOp6A () :> ParsingJob + OneOp6B () :> ParsingJob + OneOp6C () :> ParsingJob + OneOp6D () :> ParsingJob + OneOp6E () :> ParsingJob + OneOp6F () :> ParsingJob + OneOp70 () :> ParsingJob + OneOp71 () :> ParsingJob + OneOp72 () :> ParsingJob + OneOp73 () :> ParsingJob + OneOp74 () :> ParsingJob + OneOp75 () :> ParsingJob + OneOp76 () :> ParsingJob + OneOp77 () :> ParsingJob + OneOp78 () :> ParsingJob + OneOp79 () :> ParsingJob + OneOp7A () :> ParsingJob + OneOp7B () :> ParsingJob + OneOp7C () :> ParsingJob + OneOp7D () :> ParsingJob + OneOp7E () :> ParsingJob + OneOp7F () :> ParsingJob + OneOp80 () :> ParsingJob + OneOp81 () :> ParsingJob + OneOp82 () :> ParsingJob + OneOp83 () :> ParsingJob + OneOp84 () :> ParsingJob + OneOp85 () :> ParsingJob + OneOp86 () :> ParsingJob + OneOp87 () :> ParsingJob + OneOp88 () :> ParsingJob + OneOp89 () :> ParsingJob + OneOp8A () :> ParsingJob + OneOp8B () :> ParsingJob + OneOp8C () :> ParsingJob + OneOp8D () :> ParsingJob + OneOp8E () :> ParsingJob + OneOp8F () :> ParsingJob + OneOp90 () :> ParsingJob + OneOp91 () :> ParsingJob + OneOp92 () :> ParsingJob + OneOp93 () :> ParsingJob + OneOp94 () :> ParsingJob + OneOp95 () :> ParsingJob + OneOp96 () :> ParsingJob + OneOp97 () :> ParsingJob + OneOp98 () :> ParsingJob + OneOp99 () :> ParsingJob + OneOp9A () :> ParsingJob + OneOp9B () :> ParsingJob + OneOp9C () :> ParsingJob + OneOp9D () :> ParsingJob + OneOp9E () :> ParsingJob + OneOp9F () :> ParsingJob + OneOpA0 () :> ParsingJob + OneOpA1 () :> ParsingJob + OneOpA2 () :> ParsingJob + OneOpA3 () :> ParsingJob + OneOpA4 () :> ParsingJob + OneOpA5 () :> ParsingJob + OneOpA6 () :> ParsingJob + OneOpA7 () :> ParsingJob + OneOpA8 () :> ParsingJob + OneOpA9 () :> ParsingJob + OneOpAA () :> ParsingJob + OneOpAB () :> ParsingJob + OneOpAC () :> ParsingJob + OneOpAD () :> ParsingJob + OneOpAE () :> ParsingJob + OneOpAF () :> ParsingJob + OneOpB0 () :> ParsingJob + OneOpB1 () :> ParsingJob + OneOpB2 () :> ParsingJob + OneOpB3 () :> ParsingJob + OneOpB4 () :> ParsingJob + OneOpB5 () :> ParsingJob + OneOpB6 () :> ParsingJob + OneOpB7 () :> ParsingJob + OneOpB8 () :> ParsingJob + OneOpB9 () :> ParsingJob + OneOpBA () :> ParsingJob + OneOpBB () :> ParsingJob + OneOpBC () :> ParsingJob + OneOpBD () :> ParsingJob + OneOpBE () :> ParsingJob + OneOpBF () :> ParsingJob + OneOpC0 () :> ParsingJob + OneOpC1 () :> ParsingJob + OneOpC2 () :> ParsingJob + OneOpC3 () :> ParsingJob + OneOpC4 () :> ParsingJob + OneOpC5 () :> ParsingJob + OneOpC6 () :> ParsingJob + OneOpC7 () :> ParsingJob + OneOpC8 () :> ParsingJob + OneOpC9 () :> ParsingJob + OneOpCA () :> ParsingJob + OneOpCB () :> ParsingJob + OneOpCC () :> ParsingJob + OneOpCD () :> ParsingJob + OneOpCE () :> ParsingJob + OneOpCF () :> ParsingJob + OneOpD0 () :> ParsingJob + OneOpD1 () :> ParsingJob + OneOpD2 () :> ParsingJob + OneOpD3 () :> ParsingJob + OneOpD4 () :> ParsingJob + OneOpD5 () :> ParsingJob + OneOpD6 () :> ParsingJob + OneOpD7 () :> ParsingJob + OneOpD8 () :> ParsingJob + OneOpD9 () :> ParsingJob + OneOpDA () :> ParsingJob + OneOpDB () :> ParsingJob + OneOpDC () :> ParsingJob + OneOpDD () :> ParsingJob + OneOpDE () :> ParsingJob + OneOpDF () :> ParsingJob + OneOpE0 () :> ParsingJob + OneOpE1 () :> ParsingJob + OneOpE2 () :> ParsingJob + OneOpE3 () :> ParsingJob + OneOpE4 () :> ParsingJob + OneOpE5 () :> ParsingJob + OneOpE6 () :> ParsingJob + OneOpE7 () :> ParsingJob + OneOpE8 () :> ParsingJob + OneOpE9 () :> ParsingJob + OneOpEA () :> ParsingJob + OneOpEB () :> ParsingJob + OneOpEC () :> ParsingJob + OneOpED () :> ParsingJob + OneOpEE () :> ParsingJob + OneOpEF () :> ParsingJob + OneOpF0 () :> ParsingJob + OneOpF1 () :> ParsingJob + OneOpF2 () :> ParsingJob + OneOpF3 () :> ParsingJob + OneOpF4 () :> ParsingJob + OneOpF5 () :> ParsingJob + OneOpF6 () :> ParsingJob + OneOpF7 () :> ParsingJob + OneOpF8 () :> ParsingJob + OneOpF9 () :> ParsingJob + OneOpFA () :> ParsingJob + OneOpFB () :> ParsingJob + OneOpFC () :> ParsingJob + OneOpFD () :> ParsingJob + OneOpFE () :> ParsingJob + OneOpFF () :> ParsingJob |] + + /// Split a byte value into two fileds (high 3 bits; low 5 bits), and + /// categorize prefix values into 8 groups based on the high 3 bits (= 2^3). + /// The below array is a collection of bitmaps that maps the low 5-bit value + /// to a bit value indicating whether the given byte value is a prefix value + /// or not. + let prefixCheck = + [| 0x0u (* 000xxxxx = cannot be a prefix value *) + 0x40404040u (* 001xxxxx = 26/2e/36/3e is possible *) + 0x0u (* 010xxxxx = cannot be a prefix value *) + 0x000000f0u (* 011xxxxx = 64/65/66/67 is possible *) + 0x0u + 0x0u + 0x0u + 0x000d0000u (* 111xxxxx = f0/f2/f3 is possible *) |] + + let rhlp = ReadHelper (wordSz, oparsers, szcomputers) + + member inline private __.ParsePrefix (reader, pos: int) = + let mutable pos = pos + let mutable pref = PrxNone + let mutable b = (reader: BinReader).PeekByte pos + while ((prefixCheck.[(int b >>> 5)] >>> (int b &&& 0b11111)) &&& 1u) > 0u do + match b with + | 0xF0uy -> pref <- PrxLOCK ||| (clearGrp1PrefMask &&& pref) + | 0xF2uy -> pref <- PrxREPNZ ||| (clearGrp1PrefMask &&& pref) + | 0xF3uy -> pref <- PrxREPZ ||| (clearGrp1PrefMask &&& pref) + | 0x2Euy -> pref <- PrxCS ||| (clearSegMask &&& pref) + | 0x36uy -> pref <- PrxSS ||| (clearSegMask &&& pref) + | 0x3Euy -> pref <- PrxDS ||| (clearSegMask &&& pref) + | 0x26uy -> pref <- PrxES ||| (clearSegMask &&& pref) + | 0x64uy -> pref <- PrxFS ||| (clearSegMask &&& pref) + | 0x65uy -> pref <- PrxGS ||| (clearSegMask &&& pref) + | 0x66uy -> pref <- PrxOPSIZE ||| pref + | 0x67uy -> pref <- PrxADDRSIZE ||| pref + | _ -> pos <- pos - 1 + pos <- pos + 1 + b <- reader.PeekByte pos + rhlp.Prefixes <- pref + pos + + member inline private __.ParseREX (reader, pos, rex: REXPrefix byref) = + if wordSz = WordSize.Bit32 then pos + else + let rb = (reader: BinReader).PeekByte pos |> int + if rb &&& 0b11110000 = 0b01000000 then + rex <- EnumOfValue rb + pos + 1 + else pos + + override __.Parse reader addr pos = + let mutable rex = REXPrefix.NOREX + let prefEndPos = __.ParsePrefix (reader, pos) + let nextPos = __.ParseREX (reader, prefEndPos, &rex) + rhlp.VEXInfo <- None + rhlp.BinReader <- reader + rhlp.InsAddr <- addr + rhlp.REXPrefix <- rex + rhlp.InitialPos <- pos + rhlp.CurrPos <- nextPos +#if LCACHE + rhlp.MarkPrefixEnd (prefEndPos) +#endif + oneByteParsers.[int (rhlp.ReadByte ())].Run rhlp :> Instruction + + override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Intel/IntelParsingHelper.fs b/src/FrontEnd/BinLifter/Intel/IntelParsingHelper.fs new file mode 100644 index 00000000..98aff376 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelParsingHelper.fs @@ -0,0 +1,4556 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.Intel + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.FrontEnd.BinLifter.Intel.Helper +open LanguagePrimitives + +type OD = OprDesc +type internal SZ = SizeKind + +module internal ParsingHelper = begin +#if !EMULATION + let inline ensure32 (rhlp: ReadHelper) = + if WordSize.is64 rhlp.WordSize then raise ParsingFailureException else () + + let inline ensure64 (rhlp: ReadHelper) = + if WordSize.is32 rhlp.WordSize then raise ParsingFailureException else () + + let inline ensureVEX128 (rhlp: ReadHelper) = + match rhlp.VEXInfo with + | Some { VectorLength = 256 } -> raise ParsingFailureException + | _ -> () +#endif + + let inline getVVVV b = ~~~ (b >>> 3) &&& 0b01111uy + + let getVPrefs b = + match b &&& 0b00000011uy with + | 0b01uy -> Prefix.PrxOPSIZE + | 0b10uy -> Prefix.PrxREPZ + | 0b11uy -> Prefix.PrxREPNZ + | _ -> Prefix.PrxNone + + let getTwoVEXInfo (reader: BinReader) (rex: byref) pos = + let b = reader.PeekByte pos + rex <- rex ||| if (b >>> 7) = 0uy then REXPrefix.REXR else REXPrefix.NOREX + let vLen = if ((b >>> 2) &&& 0b000001uy) = 0uy then 128 else 256 + { VVVV = getVVVV b + VectorLength = vLen + VEXType = VEXType.VEXTwoByteOp + VPrefixes = getVPrefs b + EVEXPrx = None } + + let pickVEXType b1 = + match b1 &&& 0b00011uy with + | 0b01uy -> VEXType.VEXTwoByteOp + | 0b10uy -> VEXType.VEXThreeByteOpOne + | 0b11uy -> VEXType.VEXThreeByteOpTwo + | _ -> raise ParsingFailureException + + let getVREXPref (b1: byte) b2 = + let w = (b2 &&& 0b10000000uy) >>> 4 + let rxb = (~~~ b1) >>> 5 + let rex = w ||| rxb ||| 0b1000000uy + if rex &&& 0b1111uy = 0uy then REXPrefix.NOREX + else EnumOfValue (int rex) + + let getThreeVEXInfo (reader: BinReader) (rex: byref) pos = + let b1 = reader.PeekByte pos + let b2 = reader.PeekByte (pos + 1) + let vLen = if ((b2 >>> 2) &&& 0b000001uy) = 0uy then 128 else 256 + rex <- rex ||| getVREXPref b1 b2 + { VVVV = getVVVV b2 + VectorLength = vLen + VEXType = pickVEXType b1 + VPrefixes = getVPrefs b2 + EVEXPrx = None } + + let getVLen = function + | 0b00uy -> 128 + | 0b01uy -> 256 + | 0b10uy -> 512 + | 0b11uy -> raise ParsingFailureException + | _ -> raise ParsingFailureException + + let getEVEXInfo (reader: BinReader) (rex: byref) pos = + let b1 = reader.PeekByte pos + let b2 = reader.PeekByte (pos + 1) + let l'l = reader.PeekByte (pos + 2) >>> 5 &&& 0b011uy + let vLen = getVLen l'l + let aaa = reader.PeekByte (pos + 2) &&& 0b111uy + let z = if (reader.PeekByte (pos + 2) >>> 7 &&& 0b1uy) = 0uy then Zeroing + else Merging + let b = (reader.PeekByte (pos + 2) >>> 4) &&& 0b1uy + let e = Some { AAA = aaa; Z = z; B = b } + rex <- rex ||| getVREXPref b1 b2 + { VVVV = getVVVV b2 + VectorLength = vLen + VEXType = pickVEXType b1 ||| VEXType.EVEX + VPrefixes = getVPrefs b2 + EVEXPrx = e } + + let exceptionalOperationSize opcode (rhlp: ReadHelper) = + match opcode with + | Opcode.PUSH | Opcode.POP -> rhlp.OperationSize <- rhlp.MemEffOprSize + | Opcode.MOVSB | Opcode.INSB + | Opcode.STOSB | Opcode.LODSB + | Opcode.OUTSB | Opcode.SCASB -> rhlp.OperationSize <- 8 + | Opcode.OUTSW -> rhlp.OperationSize <- 16 + | Opcode.OUTSD -> rhlp.OperationSize <- 32 + | _ -> () + + let inline newInsInfo (rhlp: ReadHelper) opcode oprs = + IntelInstruction (rhlp.InsAddr, + uint32 (rhlp.ParsedLen ()), + rhlp.WordSize, + rhlp.Prefixes, + rhlp.REXPrefix, + rhlp.VEXInfo, + opcode, + oprs, + rhlp.OperationSize, + rhlp.MemEffAddrSize + (* rhlp.GetInsID () *)) + + (* Table A-7/15 of Volume 2 + (D8/DC Opcode Map When ModR/M Byte is within 00H to BFH) *) + let getD8OpWithin00toBF b = + match getReg b with + | 0b000 -> Opcode.FADD + | 0b001 -> Opcode.FMUL + | 0b010 -> Opcode.FCOM + | 0b011 -> Opcode.FCOMP + | 0b100 -> Opcode.FSUB + | 0b101 -> Opcode.FSUBR + | 0b110 -> Opcode.FDIV + | 0b111 -> Opcode.FDIVR + | _ -> raise ParsingFailureException + + let getDCOpWithin00toBF b = getD8OpWithin00toBF b + + (* Table A-8 of Volume 2 + (D8 Opcode Map When ModR/M Byte is Outside 00H to BFH) *) + let getD8OpcodeOutside00toBF = function + | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FADD + | b when b >= 0xC8uy && b <= 0xCFuy -> Opcode.FMUL + | b when b >= 0xD0uy && b <= 0xD7uy -> Opcode.FCOM + | b when b >= 0xD8uy && b <= 0xDFuy -> Opcode.FCOMP + | b when b >= 0xE0uy && b <= 0xE7uy -> Opcode.FSUB + | b when b >= 0xE8uy && b <= 0xEFuy -> Opcode.FSUBR + | b when b >= 0xF0uy && b <= 0xF7uy -> Opcode.FDIV + | b when b >= 0xF8uy && b <= 0xFFuy -> Opcode.FDIVR + | _ -> raise ParsingFailureException + + (* Table A-9 of Volume 2 + (D9 Opcode Map When ModR/M Byte is Within 00H to BFH) *) + let getD9OpWithin00toBF b = + match getReg b with + | 0b000 -> Opcode.FLD + | 0b010 -> Opcode.FST + | 0b011 -> Opcode.FSTP + | 0b100 -> Opcode.FLDENV + | 0b101 -> Opcode.FLDCW + | 0b110 -> Opcode.FSTENV + | 0b111 -> Opcode.FNSTCW + | _ -> raise ParsingFailureException + + (* Table A-10 of Volume 2 + (D9 Opcode Map When ModR/M Byte is Outside 00H to BFH) *) + let getD9OpcodeOutside00toBF = function + | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FLD + | b when b >= 0xC8uy && b <= 0xCFuy -> Opcode.FXCH + | 0xD0uy -> Opcode.FNOP + | 0xE0uy -> Opcode.FCHS + | 0xE1uy -> Opcode.FABS + | 0xE5uy -> Opcode.FXAM + | 0xE8uy -> Opcode.FLD1 + | 0xE9uy -> Opcode.FLDL2T + | 0xEAuy -> Opcode.FLDL2E + | 0xEBuy -> Opcode.FLDPI + | 0xECuy -> Opcode.FLDLG2 + | 0xEDuy -> Opcode.FLDLN2 + | 0xEEuy -> Opcode.FLDZ + | 0xF0uy -> Opcode.F2XM1 + | 0xF1uy -> Opcode.FYL2X + | 0xF2uy -> Opcode.FPTAN + | 0xF3uy -> Opcode.FPATAN + | 0xF4uy -> Opcode.FXTRACT + | 0xF5uy -> Opcode.FPREM1 + | 0xF6uy -> Opcode.FDECSTP + | 0xF7uy -> Opcode.FINCSTP + | 0xF8uy -> Opcode.FPREM + | 0xF9uy -> Opcode.FYL2XP1 + | 0xFAuy -> Opcode.FSQRT + | 0xFBuy -> Opcode.FSINCOS + | 0xFCuy -> Opcode.FRNDINT + | 0xFDuy -> Opcode.FSCALE + | 0xFEuy -> Opcode.FSIN + | 0xFFuy -> Opcode.FCOS + | _ -> raise ParsingFailureException + + (* Table A-11/19 of Volume 2 + (DA/DE Opcode Map When ModR/M Byte is Within 00H to BFH) *) + let getDAOpWithin00toBF b = + match getReg b with + | 0b000 -> Opcode.FIADD + | 0b001 -> Opcode.FIMUL + | 0b010 -> Opcode.FICOM + | 0b011 -> Opcode.FICOMP + | 0b100 -> Opcode.FISUB + | 0b101 -> Opcode.FISUBR + | 0b110 -> Opcode.FIDIV + | 0b111 -> Opcode.FIDIVR + | _ -> raise ParsingFailureException + + let getDEOpWithin00toBF b = getDAOpWithin00toBF b + + (* Table A-12 of Volume 2 + (DA Opcode Map When ModR/M Byte is Outside 00H to BFH) *) + let getDAOpcodeOutside00toBF = function + | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FCMOVB + | b when b >= 0xC8uy && b <= 0xCFuy -> Opcode.FCMOVE + | b when b >= 0xD0uy && b <= 0xD7uy -> Opcode.FCMOVBE + | b when b >= 0xD8uy && b <= 0xDFuy -> Opcode.FCMOVU + | 0xE9uy -> Opcode.FUCOMPP + | _ -> raise ParsingFailureException + + (* Table A-13 of Volume 2 + (DB Opcode Map When ModR/M Byte is Within 00H to BFH) *) + let getDBOpWithin00toBF b = + match getReg b with + | 0b000 -> Opcode.FILD + | 0b001 -> Opcode.FISTTP + | 0b010 -> Opcode.FIST + | 0b011 -> Opcode.FISTP + | 0b101 -> Opcode.FLD + | 0b111 -> Opcode.FSTP + | _ -> raise ParsingFailureException + + (* Table A-14 of Volume 2 + (DB Opcode Map When ModR/M Byte is Outside 00H to BFH) *) + let getDBOpcodeOutside00toBF = function + | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FCMOVNB + | b when b >= 0xC8uy && b <= 0xCFuy -> Opcode.FCMOVNE + | b when b >= 0xD0uy && b <= 0xD7uy -> Opcode.FCMOVNBE + | b when b >= 0xD8uy && b <= 0xDFuy -> Opcode.FCMOVNU + | b when b >= 0xE8uy && b <= 0xEFuy -> Opcode.FUCOMI + | b when b >= 0xF0uy && b <= 0xF7uy -> Opcode.FCOMI + | 0xE2uy -> Opcode.FCLEX + | 0xE3uy -> Opcode.FINIT + | _ -> raise ParsingFailureException + + (* Table A-16 of Volume 2 + (DC Opcode Map When ModR/M Byte is Outside 00H to BFH) *) + let getDCOpcodeOutside00toBF = function + | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FADD + | b when b >= 0xC8uy && b <= 0xCFuy -> Opcode.FMUL + | b when b >= 0xE0uy && b <= 0xE7uy -> Opcode.FSUBR + | b when b >= 0xE8uy && b <= 0xEFuy -> Opcode.FSUB + | b when b >= 0xF0uy && b <= 0xF7uy -> Opcode.FDIVR + | b when b >= 0xF8uy && b <= 0xFFuy -> Opcode.FDIV + | _ -> raise ParsingFailureException + + (* Table A-17 of Volume 2 + (DD Opcode Map When ModR/M Byte is Within 00H to BFH) *) + let getDDOpWithin00toBF b = + match getReg b with + | 0b000 -> Opcode.FLD + | 0b001 -> Opcode.FISTTP + | 0b010 -> Opcode.FST + | 0b011 -> Opcode.FSTP + | 0b100 -> Opcode.FRSTOR + | 0b110 -> Opcode.FSAVE + | 0b111 -> Opcode.FNSTSW + | _ -> raise ParsingFailureException + + (* Table A-18 of Volume 2 + (DD Opcode Map When ModR/M Byte is Outside 00H to BFH) *) + let getDDOpcodeOutside00toBF b = + match b with + | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FFREE + | b when b >= 0xD0uy && b <= 0xD7uy -> Opcode.FST + | b when b >= 0xD8uy && b <= 0xDFuy -> Opcode.FSTP + | b when b >= 0xE0uy && b <= 0xE7uy -> Opcode.FUCOM + | b when b >= 0xE8uy && b <= 0xEFuy -> Opcode.FUCOMP + | _ -> raise ParsingFailureException + + (* Table A-20 of Volume 2 + (DE Opcode Map When ModR/M Byte is Outside 00H to BFH) *) + let getDEOpcodeOutside00toBF = function + | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FADDP + | b when b >= 0xC8uy && b <= 0xCFuy -> Opcode.FMULP + | 0xD9uy -> Opcode.FCOMPP + | b when b >= 0xE0uy && b <= 0xE7uy -> Opcode.FSUBRP + | b when b >= 0xE8uy && b <= 0xEFuy -> Opcode.FSUBP + | b when b >= 0xF0uy && b <= 0xF7uy -> Opcode.FDIVRP + | b when b >= 0xF8uy && b <= 0xFFuy -> Opcode.FDIVP + | _ -> raise ParsingFailureException + + (* Table A-21 of Volume 2 + (DF Opcode Map When ModR/M Byte is Within 00H to BFH) *) + let getDFOpWithin00toBF b = + match getReg b with + | 0b000 -> Opcode.FILD + | 0b001 -> Opcode.FISTTP + | 0b010 -> Opcode.FIST + | 0b011 -> Opcode.FISTP + | 0b100 -> Opcode.FBLD + | 0b101 -> Opcode.FILD + | 0b110 -> Opcode.FBSTP + | 0b111 -> Opcode.FISTP + | _ -> raise ParsingFailureException + + (* Table A-22 of Volume 2 + (DF Opcode Map When ModR/M Byte is Outside 00H to BFH) *) + let getDFOpcodeOutside00toBF = function + | 0xE0uy -> Opcode.FNSTSW + | b when b >= 0xE8uy && b <= 0xEFuy -> Opcode.FUCOMIP + | b when b >= 0xF0uy && b <= 0xF7uy -> Opcode.FCOMIP + | _ -> raise ParsingFailureException + + let getD8OverBF b = + getD8OpcodeOutside00toBF b, TwoOperands (OprReg R.ST0, getRM b |> getSTReg) + + let getD9OverBF b = + getD9OpcodeOutside00toBF b, + if b < 0xC0uy || b >= 0xD0uy then NoOperand + else OneOperand (getRM b |> getSTReg) + + let getDAOverBF b = + getDAOpcodeOutside00toBF b, + if b = 0xE9uy then NoOperand + else TwoOperands (OprReg R.ST0, getRM b |> getSTReg) + + let getDBOverBF b = + getDBOpcodeOutside00toBF b, + if b = 0xE2uy || b = 0xE3uy then NoOperand + else TwoOperands (OprReg R.ST0, getRM b |> getSTReg) + + let getDCOverBF b = + getDCOpcodeOutside00toBF b, TwoOperands (getRM b |> getSTReg, OprReg R.ST0) + + let getDDOverBF b = + getDDOpcodeOutside00toBF b, + if b < 0xE0uy || b >= 0xE8uy then getRM b |> getSTReg |> OneOperand + else TwoOperands (getRM b |> getSTReg, OprReg R.ST0) + + let getDEOverBF b = + getDEOpcodeOutside00toBF b, + if b = 0xD9uy then NoOperand + else TwoOperands (getRM b |> getSTReg, OprReg R.ST0) + + let getDFOverBF b = + getDFOpcodeOutside00toBF b, + if b = 0xE0uy then OprReg R.AX |> OneOperand + else TwoOperands (OprReg R.ST0, getRM b |> getSTReg) + + let getD9EscEffOprSizeByModRM = function + | 0b000 | 0b010 | 0b011 -> 32 (* single-real *) + | 0b100 | 0b110 -> 224 (* 14/28 bytes (Vol.1 8-11 8.1.10) *) + | 0b101 | 0b111 -> 16 (* 2 bytes *) + | _ -> raise ParsingFailureException + + let getDBEscEffOprSizeByModRM = function + | 0b101 | 0b111 -> 80 (* extended-real *) + | 0b000 | 0b001 | 0b010 | 0b011 -> 32 (* dword-integer *) + | _ -> raise ParsingFailureException + + let getDDEscEffOprSizeByModRM = function + | 0b000 | 0b010 | 0b011 -> 64 (* double-real *) + | 0b001 -> 64 (* integer64 *) + | 0b100 | 0b110 -> 864 (* 94/108 bytes *) + | 0b111 -> 16 (* 2 bytes *) + | _ -> raise ParsingFailureException + + let getDFEscEffOprSizeByModRM = function + | 0b000 | 0b001 | 0b010 | 0b011 -> 16 (* word-integer *) + | 0b100 | 0b110 -> 80 (* packed-BCD *) + | 0b101 | 0b111 -> 64 (* qword-integer *) + | _ -> raise ParsingFailureException + + let getEscEffOprSizeByESCOp = function + | 0xD8uy -> 32 (* single-real *) + | 0xDAuy -> 32 (* dword-integer *) + | 0xDCuy -> 64 (* double-real *) + | 0xDEuy -> 16 (* word-integer *) + | _ -> raise ParsingFailureException + + let selectPrefix (rhlp: ReadHelper) = + match rhlp.VEXInfo with + | None -> rhlp.Prefixes + | Some v -> v.VPrefixes + + /// Not Encodable + let notEn _ = raise ParsingFailureException + + let nor0F10 = function + | MPref.MPrxNP -> struct (Opcode.MOVUPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.MOVUPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> struct (Opcode.MOVSS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF2 -> struct (Opcode.MOVSD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F10Mem = function + | MPref.MPrxNP -> struct (Opcode.VMOVUPS, OD.GprRm, SZ.VecDef) (* VpsWps *) + | MPref.MPrx66 -> struct (Opcode.VMOVUPD, OD.GprRm, SZ.VecDef) (* VpdWpd *) + | MPref.MPrxF3 -> struct (Opcode.VMOVSS, OD.GprRm, SZ.DqdDq) (* VdqMd *) + | MPref.MPrxF2 -> struct (Opcode.VMOVSD, OD.GprRm, SZ.DqqDq) (* VdqMq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F10Reg = function + | MPref.MPrxNP -> struct (Opcode.VMOVUPS, OD.GprRm, SZ.VecDef) (* VpsWps *) + | MPref.MPrx66 -> struct (Opcode.VMOVUPD, OD.GprRm, SZ.VecDef) (* VpdWpd *) + | MPref.MPrxF3 -> struct (Opcode.VMOVSS, OD.XmmVvXm, SZ.VecDef) (* VxHxWss *) + | MPref.MPrxF2 -> struct (Opcode.VMOVSD, OD.XmmVvXm, SZ.VecDef) (* VxHxWsd *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F11 = function + | MPref.MPrxNP -> struct (Opcode.MOVUPS, OD.RmGpr, SZ.DqDq) (* WdqVdq *) + | MPref.MPrx66 -> struct (Opcode.MOVUPD, OD.RmGpr, SZ.DqDq) (* WdqVdq *) + | MPref.MPrxF3 -> struct (Opcode.MOVSS, OD.RmGpr, SZ.DqdDqMR) (* WdqdVdq *) + | MPref.MPrxF2 -> struct (Opcode.MOVSD, OD.RmGpr, SZ.DqqDq) (* WdqqVdq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F11Mem = function + | MPref.MPrxNP -> struct (Opcode.VMOVUPS, OD.RmGpr, SZ.VecDef) (* WpsVps *) + | MPref.MPrx66 -> struct (Opcode.VMOVUPD, OD.RmGpr, SZ.VecDef) (* WpdVpd *) + | MPref.MPrxF3 -> struct (Opcode.VMOVSS, OD.RmGpr, SZ.DqdDqMR) (* MdVdq *) + | MPref.MPrxF2 -> struct (Opcode.VMOVSD, OD.RmGpr, SZ.DqqDq) (* MqVdq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F11Reg = function + | MPref.MPrxNP -> struct (Opcode.VMOVUPS, OD.RmGpr, SZ.VecDef) (* WpsVps *) + | MPref.MPrx66 -> struct (Opcode.VMOVUPD, OD.RmGpr, SZ.VecDef) (* WpdVpd *) + | MPref.MPrxF3 -> struct (Opcode.VMOVSS, OD.XmVvXmm, SZ.VecDef) (* WssHxVss *) + | MPref.MPrxF2 -> struct (Opcode.VMOVSD, OD.XmVvXmm, SZ.VecDef) (* WsdHxVsd *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F12Mem = function + | MPref.MPrxNP -> struct (Opcode.MOVLPS, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrx66 -> struct (Opcode.MOVLPD, OD.GprRm, SZ.DqqDq) (* VdqMq *) + | MPref.MPrxF3 -> struct (Opcode.MOVSLDUP, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF2 -> struct (Opcode.MOVDDUP, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F12Reg = function + | MPref.MPrxNP -> struct (Opcode.MOVHLPS, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrx66 -> struct (Opcode.MOVLPD, OD.GprRm, SZ.DqqDq) (* VdqMq *) + | MPref.MPrxF3 -> struct (Opcode.MOVSLDUP, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF2 -> struct (Opcode.MOVDDUP, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F12Mem = function + | MPref.MPrxNP -> + struct (Opcode.VMOVLPS, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrx66 -> struct (Opcode.VMOVLPD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqMq *) + | MPref.MPrxF3 -> struct (Opcode.VMOVSLDUP, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrxF2 -> struct (Opcode.VMOVDDUP, OD.GprRm, SZ.XqX) (* VxWxq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F12Reg = function + | MPref.MPrxNP -> + struct (Opcode.VMOVHLPS, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrx66 -> struct (Opcode.VMOVLPD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqMq *) + | MPref.MPrxF3 -> struct (Opcode.VMOVSLDUP, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrxF2 -> struct (Opcode.VMOVDDUP, OD.GprRm, SZ.XqX) (* VxWxq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F13 = function + | MPref.MPrxNP -> struct (Opcode.MOVLPS, OD.RmGpr, SZ.DqqDq) (* MqVdq *) + | MPref.MPrx66 -> struct (Opcode.MOVLPD, OD.RmGpr, SZ.DqqDq) (* MqVdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F13 = function + | MPref.MPrxNP -> struct (Opcode.VMOVLPS, OD.RmGpr, SZ.DqqDq) (* MqVdq *) + | MPref.MPrx66 -> struct (Opcode.VMOVLPD, OD.RmGpr, SZ.DqqDq) (* MqVdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F14 = function + | MPref.MPrxNP -> struct (Opcode.UNPCKLPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.UNPCKLPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F14 = function + | MPref.MPrxNP -> + struct (Opcode.VUNPCKLPS, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> + struct (Opcode.VUNPCKLPD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F15 = function + | MPref.MPrxNP -> struct (Opcode.UNPCKHPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.UNPCKHPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F15 = function + | MPref.MPrxNP -> + struct (Opcode.VUNPCKHPS, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> + struct (Opcode.VUNPCKHPD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F16Mem = function + | MPref.MPrxNP -> struct (Opcode.MOVHPS, OD.GprRm, SZ.DqqDq) (* VdqMq *) + | MPref.MPrx66 -> struct (Opcode.MOVHPD, OD.GprRm, SZ.DqqDq) (* VdqMq *) + | MPref.MPrxF3 -> struct (Opcode.MOVSHDUP, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F16Reg = function + | MPref.MPrxNP -> struct (Opcode.MOVLHPS, OD.GprRm, SZ.DqDq) (* VdqUdq *) + | MPref.MPrx66 -> struct (Opcode.MOVHPD, OD.GprRm, SZ.DqqDq) (* VdqMq *) + | MPref.MPrxF3 -> struct (Opcode.MOVSHDUP, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F16Mem = function + | MPref.MPrxNP -> struct (Opcode.VMOVHPS, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqMq *) + | MPref.MPrx66 -> struct (Opcode.VMOVHPD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqMq *) + | MPref.MPrxF3 -> struct (Opcode.VMOVSHDUP, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F16Reg = function + | MPref.MPrxNP -> + struct (Opcode.VMOVLHPS, OD.XmmVvXm, SZ.DqDq) (* VdqHdqUdq *) + | MPref.MPrx66 -> + struct (Opcode.VMOVHPD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqMq *) + | MPref.MPrxF3 -> struct (Opcode.VMOVSHDUP, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F17 = function + | MPref.MPrxNP -> struct (Opcode.MOVHPS, OD.RmGpr, SZ.DqqDq) (* MqVdq *) + | MPref.MPrx66 -> struct (Opcode.MOVHPD, OD.RmGpr, SZ.DqqDq) (* MqVdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F17 = function + | MPref.MPrxNP -> struct (Opcode.VMOVHPS, OD.RmGpr, SZ.DqqDq) (* MqVdq *) + | MPref.MPrx66 -> struct (Opcode.VMOVHPD, OD.RmGpr, SZ.DqqDq) (* MqVdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F1A = function + | MPref.MPrxNP -> struct (Opcode.BNDLDX, OD.BndRm, SZ.VyDq) (* BNMib *) + | MPref.MPrx66 -> struct (Opcode.BNDMOV, OD.BndBm, SZ.DqqDqWS) (* BNBNdqq *) + | MPref.MPrxF3 -> struct (Opcode.BNDCL, OD.BndRm, SZ.VyDq) (* BNEv *) + | MPref.MPrxF2 -> struct (Opcode.BNDCU, OD.BndRm, SZ.VyDq) (* BNEv *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F1B = function + | MPref.MPrxNP -> struct (Opcode.BNDSTX, OD.RmBnd, SZ.VyDqMR) (* MibBN *) + | MPref.MPrx66 -> struct (Opcode.BNDMOV, OD.BmBnd, SZ.DqqDqWS) (* BNdqqBN *) + | MPref.MPrxF3 -> struct (Opcode.BNDMK, OD.BndRm, SZ.VyDq) (* BNMv *) + | MPref.MPrxF2 -> struct (Opcode.BNDCN, OD.BndRm, SZ.VyDq) (* BNEv *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F28 = function + | MPref.MPrxNP -> struct (Opcode.MOVAPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.MOVAPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F28 = function + | MPref.MPrxNP -> struct (Opcode.VMOVAPS, OD.RmGpr, SZ.VecDef) (* VpsWps *) + | MPref.MPrx66 -> struct (Opcode.VMOVAPD, OD.GprRm, SZ.VecDef) (* VpdWpd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F29 = function + | MPref.MPrxNP -> struct (Opcode.MOVAPS, OD.RmGpr, SZ.DqDq) (* WdqVdq *) + | MPref.MPrx66 -> struct (Opcode.MOVAPD, OD.RmGpr, SZ.DqDq) (* WdqVdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F29 = function + | MPref.MPrxNP -> struct (Opcode.VMOVAPS, OD.RmGpr, SZ.VecDef) (* WpsVps *) + | MPref.MPrx66 -> struct (Opcode.VMOVAPD, OD.RmGpr, SZ.VecDef) (* WpdVpd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F2A = function + | MPref.MPrxNP -> struct (Opcode.CVTPI2PS, OD.GprRMm, SZ.QDq) (* VdqQpi *) + | MPref.MPrx66 -> struct (Opcode.CVTPI2PD, OD.GprRMm, SZ.QDq) (* VdqQpi *) + | MPref.MPrxF3 -> struct (Opcode.CVTSI2SS, OD.GprRm, SZ.VyDq) (* VdqEy *) + | MPref.MPrxF2 -> struct (Opcode.CVTSI2SD, OD.GprRm, SZ.VyDq) (* VdqEy *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F2A = function + | MPref.MPrxNP + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> + struct (Opcode.VCVTSI2SS, OD.XmmVvXm, SZ.VyDq) (* VssHssEy *) + | MPref.MPrxF2 -> + struct (Opcode.VCVTSI2SD, OD.XmmVvXm, SZ.VyDq) (* VsdHsdEy *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F2B = function + | MPref.MPrxNP -> struct (Opcode.MOVNTPS, OD.RmGpr, SZ.DqDq) (* MdqVdq *) + | MPref.MPrx66 -> struct (Opcode.MOVNTPD, OD.RmGpr, SZ.DqDq) (* MdqVdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F2B = function + | MPref.MPrxNP -> struct (Opcode.VMOVNTPS, OD.RmGpr, SZ.VecDef) (* MpsVps *) + | MPref.MPrx66 -> struct (Opcode.VMOVNTPD, OD.RmGpr, SZ.VecDef) (* MpdVpd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F2C = function + | MPref.MPrxNP -> + struct (Opcode.CVTTPS2PI, OD.MmxMm, SZ.DqqQ) (* PpiWdqq *) + | MPref.MPrx66 -> struct (Opcode.CVTTPD2PI, OD.MmxMm, SZ.DqQ) (* PpiWdq *) + | MPref.MPrxF3 -> struct (Opcode.CVTTSS2SI, OD.GprRm, SZ.DqdY) (* GyWdqd *) + | MPref.MPrxF2 -> struct (Opcode.CVTTSD2SI, OD.GprRm, SZ.DqqY) (* GyWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F2C = function + | MPref.MPrxNP + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> struct (Opcode.VCVTTSS2SI, OD.GprRm, SZ.DqdY) (* GyWdqd *) + | MPref.MPrxF2 -> struct (Opcode.VCVTTSD2SI, OD.GprRm, SZ.DqqY) (* GyWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F2D = function + | MPref.MPrxNP -> struct (Opcode.CVTPS2PI, OD.MmxMm, SZ.DqqQ) (* PpiWdqq *) + | MPref.MPrx66 -> struct (Opcode.CVTPD2PI, OD.MmxMm, SZ.DqQ) (* PpiWdq *) + | MPref.MPrxF3 -> struct (Opcode.CVTSS2SI, OD.GprRm, SZ.DqdY) (* GyWdqd *) + | MPref.MPrxF2 -> struct (Opcode.CVTSD2SI, OD.GprRm, SZ.DqqY) (* GyWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F2D = function + | MPref.MPrxNP + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> struct (Opcode.VCVTSS2SI, OD.GprRm, SZ.DqdY) (* GyWdqd *) + | MPref.MPrxF2 -> struct (Opcode.VCVTSD2SI, OD.GprRm, SZ.DqqY) (* GyWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F2E = function + | MPref.MPrxNP -> struct (Opcode.UCOMISS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrx66 -> struct (Opcode.UCOMISD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F2E = function + | MPref.MPrxNP -> struct (Opcode.VUCOMISS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrx66 -> struct (Opcode.VUCOMISD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F2F = function + | MPref.MPrxNP -> struct (Opcode.COMISS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrx66 -> struct (Opcode.COMISD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F2F = function + | MPref.MPrxNP -> struct (Opcode.VCOMISS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrx66 -> struct (Opcode.VCOMISD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F50 = function + | MPref.MPrxNP -> struct (Opcode.MOVMSKPS, OD.GprRm, SZ.DqY) (* GyUdq *) + | MPref.MPrx66 -> struct (Opcode.MOVMSKPD, OD.GprRm, SZ.DqY) (* GyUdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F50 = function + | MPref.MPrxNP -> struct (Opcode.VMOVMSKPS, OD.GprRm, SZ.DqY) (* GyUdq *) + | MPref.MPrx66 -> struct (Opcode.VMOVMSKPD, OD.GprRm, SZ.DqY) (* GyUdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F51 = function + | MPref.MPrxNP -> struct (Opcode.SQRTPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.SQRTPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> struct (Opcode.SQRTSS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF2 -> struct (Opcode.SQRTSD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F51 = function + | MPref.MPrxNP -> struct (Opcode.VSQRTPS, OD.GprRm, SZ.VecDef) (* VpsWps *) + | MPref.MPrx66 -> struct (Opcode.VSQRTPD, OD.GprRm, SZ.VecDef) (* VpdWpd *) + | MPref.MPrxF3 -> + struct (Opcode.VSQRTSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> + struct (Opcode.VSQRTSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F52 = function + | MPref.MPrxNP -> struct (Opcode.RSQRTPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> struct (Opcode.RSQRTSS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F52 = function + | MPref.MPrxNP -> struct (Opcode.VRSQRTPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> + struct (Opcode.VRSQRTSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd*) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F53 = function + | MPref.MPrxNP -> struct (Opcode.RCPPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> struct (Opcode.RCPSS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F53 = function + | MPref.MPrxNP -> struct (Opcode.VRCPPS, OD.GprRm, SZ.VecDef) (* VxHx *) + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> + struct (Opcode.VRCPSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F54 = function + | MPref.MPrxNP -> struct (Opcode.ANDPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.ANDPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F54 = function + | MPref.MPrxNP -> + struct (Opcode.VANDPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> + struct (Opcode.VANDPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F55 = function + | MPref.MPrxNP -> struct (Opcode.ANDNPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.ANDNPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F55 = function + | MPref.MPrxNP -> + struct (Opcode.VANDNPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> + struct (Opcode.VANDNPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F56 = function + | MPref.MPrxNP -> struct (Opcode.ORPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.ORPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F56 = function + | MPref.MPrxNP -> struct (Opcode.VORPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> struct (Opcode.VORPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F57 = function + | MPref.MPrxNP -> struct (Opcode.XORPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.XORPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F57 = function + | MPref.MPrxNP -> + struct (Opcode.VXORPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> + struct (Opcode.VXORPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F58 = function + | MPref.MPrxNP -> struct (Opcode.ADDPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.ADDPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> struct (Opcode.ADDSS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF2 -> struct (Opcode.ADDSD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F58 = function + | MPref.MPrxNP -> + struct (Opcode.VADDPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> + struct (Opcode.VADDPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 -> + struct (Opcode.VADDSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> + struct (Opcode.VADDSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F59 = function + | MPref.MPrxNP -> struct (Opcode.MULPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.MULPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> struct (Opcode.MULSS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF2 -> struct (Opcode.MULSD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F59 = function + | MPref.MPrxNP -> + struct (Opcode.VMULPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> + struct (Opcode.VMULPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 -> + struct (Opcode.VMULSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> + struct (Opcode.VMULSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F5A = function + | MPref.MPrxNP -> struct (Opcode.CVTPS2PD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrx66 -> struct (Opcode.CVTPD2PS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> struct (Opcode.CVTSS2SD, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF2 -> struct (Opcode.CVTSD2SS, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F5A = function + | MPref.MPrxNP -> + struct (Opcode.VCVTPS2PD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrx66 -> struct (Opcode.VCVTPD2PS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> + struct (Opcode.VCVTSS2SD, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> + struct (Opcode.VCVTSD2SS, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F5AW0 = function + | MPref.MPrxNP -> struct (Opcode.VCVTPS2PD, OD.GprRm, SZ.XqXz) (* VZxzWxq *) + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F5AW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VCVTPD2PS, OD.GprRm, SZ.XzX) (* VxWZxz *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F5B = function + | MPref.MPrxNP -> struct (Opcode.CVTDQ2PS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.CVTPS2DQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> struct (Opcode.CVTTPS2DQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F5B = function + | MPref.MPrxNP -> struct (Opcode.VCVTDQ2PS, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F5C = function + | MPref.MPrxNP -> struct (Opcode.SUBPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.SUBPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> struct (Opcode.SUBSS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF2 -> struct (Opcode.SUBSD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F5C = function + | MPref.MPrxNP -> + struct (Opcode.VSUBPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> + struct (Opcode.VSUBPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 -> + struct (Opcode.VSUBSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> + struct (Opcode.VSUBSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F5D = function + | MPref.MPrxNP -> struct (Opcode.MINPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.MINPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> struct (Opcode.MINSS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF2 -> struct (Opcode.MINSD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F5D = function + | MPref.MPrxNP -> + struct (Opcode.VMINPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> + struct (Opcode.VMINPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 -> + struct (Opcode.VMINSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> + struct (Opcode.VMINSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F5DW0 = function + | MPref.MPrxNP + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> + struct (Opcode.VMINSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F5E = function + | MPref.MPrxNP -> struct (Opcode.DIVPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.DIVPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> struct (Opcode.DIVSS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF2 -> struct (Opcode.DIVSD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F5E = function + | MPref.MPrxNP -> + struct (Opcode.VDIVPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> + struct (Opcode.VDIVPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 -> + struct (Opcode.VDIVSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> + struct (Opcode.VDIVSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F5F = function + | MPref.MPrxNP -> struct (Opcode.MAXPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrx66 -> struct (Opcode.MAXPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> struct (Opcode.MAXSS, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF2 -> struct (Opcode.MAXSD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F5F = function + | MPref.MPrxNP -> + struct (Opcode.VMAXPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> + struct (Opcode.VMAXPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 -> + struct (Opcode.VMAXSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> + struct (Opcode.VMAXSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F5FW0 = function + | MPref.MPrxNP -> struct (Opcode.VMAXPS, OD.XmmVvXm, SZ.XzXz) (* VZxzHxWZxz *) + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> + struct (Opcode.VMAXSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F5FW1 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> + struct (Opcode.VMAXSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F60 = function + | MPref.MPrxNP -> struct (Opcode.PUNPCKLBW, OD.MmxRm, SZ.DQ) (* PqQd *) + | MPref.MPrx66 -> struct (Opcode.PUNPCKLBW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F60 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPUNPCKLBW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F61 = function + | MPref.MPrxNP -> struct (Opcode.PUNPCKLWD, OD.MmxRm, SZ.DQ) (* PqQd *) + | MPref.MPrx66 -> struct (Opcode.PUNPCKLWD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F61 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPUNPCKLWD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F62 = function + | MPref.MPrxNP -> struct (Opcode.PUNPCKLDQ, OD.MmxRm, SZ.DQ) (* PqQd *) + | MPref.MPrx66 -> struct (Opcode.PUNPCKLDQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F62 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPUNPCKLDQ, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F63 = function + | MPref.MPrxNP -> struct (Opcode.PACKSSWB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PACKSSWB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F63 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPACKSSWB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F64 = function + | MPref.MPrxNP -> struct (Opcode.PCMPGTB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PCMPGTB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F64 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPCMPGTB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F65 = function + | MPref.MPrxNP -> struct (Opcode.PCMPGTW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PCMPGTW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F65 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPCMPGTW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F66 = function + | MPref.MPrxNP -> struct (Opcode.PCMPGTD, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PCMPGTD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F66 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPCMPGTD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F67 = function + | MPref.MPrxNP -> struct (Opcode.PACKUSWB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PACKUSWB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F67 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPACKUSWB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F68 = function + | MPref.MPrxNP -> struct (Opcode.PUNPCKHBW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PUNPCKHBW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F68 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPUNPCKHBW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F69 = function + | MPref.MPrxNP -> struct (Opcode.PUNPCKHWD, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PUNPCKHWD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F69 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPUNPCKHWD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F6A = function + | MPref.MPrxNP -> struct (Opcode.PUNPCKHDQ, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PUNPCKHDQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F6A = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPUNPCKHDQ, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F6B = function + | MPref.MPrxNP -> struct (Opcode.PACKSSDW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PACKSSDW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F6B = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPACKSSDW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F6C = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PUNPCKLQDQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F6C = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPUNPCKLQDQ, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F6D = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PUNPCKHQDQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F6D = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPUNPCKHQDQ, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F6EW1 = function + | MPref.MPrxNP -> struct (Opcode.MOVQ, OD.MmxMm, SZ.YQRM) (* PqEy *) + | MPref.MPrx66 -> struct (Opcode.MOVQ, OD.GprRm, SZ.VyDq) (* VdqEy *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F6EW0 = function + | MPref.MPrxNP -> struct (Opcode.MOVD, OD.MmxMm, SZ.YQRM) (* PqEy *) + | MPref.MPrx66 -> struct (Opcode.MOVD, OD.GprRm, SZ.VyDq) (* VdqEy *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F6EW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VMOVQ, OD.GprRm, SZ.VyDq) (* VdqEy *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F6EW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VMOVD, OD.GprRm, SZ.VyDq) (* VdqEy *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F6F = function + | MPref.MPrxNP -> struct (Opcode.MOVQ, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.MOVDQA, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> struct (Opcode.MOVDQU, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F6F = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VMOVDQA, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrxF3 -> struct (Opcode.VMOVDQU, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F6FW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VMOVDQA64, OD.GprRm, SZ.VecDef) (* VZxzWZxz *) + | MPref.MPrxF3 -> + struct (Opcode.VMOVDQU64, OD.GprRm, SZ.VecDef) (* VZxzWZxz *) + | MPref.MPrxF2 -> + struct (Opcode.VMOVDQU16, OD.GprRm, SZ.VecDef) (* VZxzWZxz *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F6FW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VMOVDQA32, OD.GprRm, SZ.VecDef) (* VZxzWZxz *) + | MPref.MPrxF3 -> + struct (Opcode.VMOVDQU32, OD.GprRm, SZ.VecDef) (* VZxzWZxz *) + | MPref.MPrxF2 -> struct (Opcode.VMOVDQU8, OD.GprRm, SZ.VecDef) (* VZxzWZxz *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F70 = function + | MPref.MPrxNP -> struct (Opcode.PSHUFW, OD.MmxMmImm8, SZ.QQ) (* PqQqIb *) + | MPref.MPrx66 -> struct (Opcode.PSHUFD, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 -> + struct (Opcode.PSHUFHW, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF2 -> + struct (Opcode.PSHUFLW, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F70 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPSHUFD, OD.XmmRmImm8, SZ.VecDef) (* VxWxIb *) + | MPref.MPrxF3 -> + struct (Opcode.VPSHUFHW, OD.XmmRmImm8, SZ.VecDef) (* VxWxIb *) + | MPref.MPrxF2 -> + struct (Opcode.VPSHUFLW, OD.XmmRmImm8, SZ.VecDef) (* VxWxIb *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F74 = function + | MPref.MPrxNP -> struct (Opcode.PCMPEQB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PCMPEQB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F74 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPCMPEQB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F75 = function + | MPref.MPrxNP -> struct (Opcode.PCMPEQW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PCMPEQW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F75 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPCMPEQW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F76 = function + | MPref.MPrxNP -> struct (Opcode.PCMPEQD, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PCMPEQD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F76 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPCMPEQD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F77 = function + | MPref.MPrxNP -> struct (Opcode.EMMS, OD.No, SZ.Def) (* NoOpr *) + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F77 = function + | MPref.MPrxNP -> struct (Opcode.VZEROUPPER, OD.No, SZ.Def) (* NoOpr *) + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F7EW1 = function + | MPref.MPrxNP -> struct (Opcode.MOVQ, OD.RMMmx, SZ.YQ) (* EyPq *) + | MPref.MPrx66 -> struct (Opcode.MOVQ, OD.RmGpr, SZ.VyDqMR) (* EyVdq *) + | MPref.MPrxF3 -> struct (Opcode.MOVQ, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F7EW0 = function + | MPref.MPrxNP -> struct (Opcode.MOVD, OD.RMMmx, SZ.YQ) (* EyPq *) + | MPref.MPrx66 -> struct (Opcode.MOVD, OD.RmGpr, SZ.VyDqMR) (* EyVdq *) + | MPref.MPrxF3 -> struct (Opcode.MOVQ, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F7EW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VMOVQ, OD.RmGpr, SZ.VyDqMR) (* EyVdq *) + | MPref.MPrxF3 -> struct (Opcode.VMOVQ, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F7EW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VMOVD, OD.RmGpr, SZ.VyDqMR) (* EyVdq *) + | MPref.MPrxF3 -> struct (Opcode.VMOVQ, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F7F = function + | MPref.MPrxNP -> struct (Opcode.MOVQ, OD.MmMmx, SZ.QQ) (* QqPq *) + | MPref.MPrx66 -> struct (Opcode.MOVDQA, OD.RmGpr, SZ.DqDq) (* WdqVdq *) + | MPref.MPrxF3 -> struct (Opcode.MOVDQU, OD.RmGpr, SZ.DqDq) (* WdqVdq *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F7F = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VMOVDQA, OD.RmGpr, SZ.VecDef) (* WxVx *) + | MPref.MPrxF3 -> struct (Opcode.VMOVDQU, OD.RmGpr, SZ.VecDef) (* WxVx *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F7FW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VMOVDQA64, OD.RmGpr, SZ.VecDef) (* WZxzVZxz *) + | MPref.MPrxF3 -> + struct (Opcode.VMOVDQU64, OD.RmGpr, SZ.VecDef) (* WZxzVZxz *) + | MPref.MPrxF2 -> + struct (Opcode.VMOVDQU16, OD.RmGpr, SZ.VecDef) (* WZxzVZxz *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F7FW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VMOVDQA32, OD.RmGpr, SZ.VecDef) (* WZxzVZxz *) + | MPref.MPrxF3 -> + struct (Opcode.VMOVDQU32, OD.RmGpr, SZ.VecDef) (* WZxzVZxz *) + | MPref.MPrxF2 -> + struct (Opcode.VMOVDQU8, OD.RmGpr, SZ.VecDef) (* WZxzVZxz *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FC2 = function + | MPref.MPrxNP -> + struct (Opcode.CMPPS, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrx66 -> + struct (Opcode.CMPPD, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 -> + struct (Opcode.CMPSS, OD.XmmRmImm8, SZ.DqdDq) (* VdqWdqdIb *) + | MPref.MPrxF2 -> + struct (Opcode.CMPSD, OD.XmmRmImm8, SZ.DqqDq) (* VdqWdqqIb *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FC2 = function + | MPref.MPrxNP -> + struct (Opcode.VCMPPS, OD.XmmVvXmImm8, SZ.VecDef) (* VpsHpsWpsIb *) + | MPref.MPrx66 -> + struct (Opcode.VCMPPD, OD.XmmVvXmImm8, SZ.VecDef) (* VpdHpdWpdIb *) + | MPref.MPrxF3 -> + struct (Opcode.VCMPSS, OD.XmmVvXmImm8, SZ.VecDef) (* VssHssWssIb *) + | MPref.MPrxF2 -> + struct (Opcode.VCMPSD, OD.XmmVvXmImm8, SZ.VecDef) (* VsdHsdWsdIb *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0FC2W0 = function + | MPref.MPrxNP -> + struct (Opcode.VCMPPS, OD.XmmVvXmImm8, SZ.XzXz) (* VZxzHxWZxzIb *) + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0FC2W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VCMPPD, OD.XmmVvXmImm8, SZ.XzXz) (* VZxzHxWZxzIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FC4 = function + | MPref.MPrxNP -> struct (Opcode.PINSRW, OD.MmxRmImm8, SZ.DwQ) (* PqEdwIb *) + | MPref.MPrx66 -> + struct (Opcode.PINSRW, OD.XmmRmImm8, SZ.DwDq) (* VdqEdwIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FC4 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPINSRW, OD.XmmVvXmImm8, SZ.DwDq) (* VdqHdqEdwIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FC5 = function + | MPref.MPrxNP -> struct (Opcode.PEXTRW, OD.GprMmxImm8, SZ.QD) (* GdNqIb *) + | MPref.MPrx66 -> struct (Opcode.PEXTRW, OD.XmmRmImm8, SZ.Dqd) (* GdUdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FC5 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPEXTRW, OD.XmmRmImm8, SZ.Dqd) (* GdUdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FC6 = function + | MPref.MPrxNP -> struct (Opcode.SHUFPS, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrx66 -> struct (Opcode.SHUFPD, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FC6 = function + | MPref.MPrxNP -> + struct (Opcode.VSHUFPS, OD.XmmVvXmImm8, SZ.VecDef) (* VpsHpsWpsIb *) + | MPref.MPrx66 -> + struct (Opcode.VSHUFPD, OD.XmmVvXmImm8, SZ.VecDef) (* VpdHpdWpdIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FD1 = function + | MPref.MPrxNP -> struct (Opcode.PSRLW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSRLW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FD1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSRLW, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FD2 = function + | MPref.MPrxNP -> struct (Opcode.PSRLD, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSRLD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FD2 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSRLD, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FD3 = function + | MPref.MPrxNP -> struct (Opcode.PSRLQ, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSRLQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FD3 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSRLQ, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FD4 = function + | MPref.MPrxNP -> struct (Opcode.PADDQ, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PADDQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FD4 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPADDQ, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FD5 = function + | MPref.MPrxNP -> struct (Opcode.PMULLW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PMULLW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FD5 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMULLW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FD6 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.MOVQ, OD.RmGpr, SZ.DqqDq) (* WdqqVdq *) + | MPref.MPrxF3 -> struct (Opcode.MOVQ2DQ, OD.GprRMm, SZ.QDq) (* VdqNq *) + | MPref.MPrxF2 -> struct (Opcode.MOVDQ2Q, OD.MmxMm, SZ.DqQ) (* PqUdq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FD6 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VMOVQ, OD.RmGpr, SZ.DqqDq) (* WdqqVdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FD7 = function + | MPref.MPrxNP -> struct (Opcode.PMOVMSKB, OD.GprRMm, SZ.QD) (* GdNq *) + | MPref.MPrx66 -> struct (Opcode.PMOVMSKB, OD.GprRm, SZ.Dqd) (* GdUdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FD7 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMOVMSKB, OD.GprRm, SZ.XD) (* GdUx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FD8 = function + | MPref.MPrxNP -> struct (Opcode.PSUBUSB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSUBUSB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FD8 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSUBUSB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FD9 = function + | MPref.MPrxNP -> struct (Opcode.PSUBUSW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSUBUSW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FD9 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSUBUSW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FDA = function + | MPref.MPrxNP -> struct (Opcode.PMINUB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PMINUB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FDA = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMINUB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FDB = function + | MPref.MPrxNP -> struct (Opcode.PAND, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PAND, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FDB = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPAND, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FDC = function + | MPref.MPrxNP -> struct (Opcode.PADDUSB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PADDUSB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FDC = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPADDUSB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FDD = function + | MPref.MPrxNP -> struct (Opcode.PADDUSW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PADDUSW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FDD = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPADDUSW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FDE = function + | MPref.MPrxNP -> struct (Opcode.PMAXUB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PMAXUB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FDE = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMAXUB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FDF = function + | MPref.MPrxNP -> struct (Opcode.PANDN, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PANDN, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FDF = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPANDN, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FE0 = function + | MPref.MPrxNP -> struct (Opcode.PAVGB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PAVGB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FE0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPAVGB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FE1 = function + | MPref.MPrxNP -> struct (Opcode.PSRAW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSRAW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FE1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSRAW, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FE2 = function + | MPref.MPrxNP -> struct (Opcode.PSRAD, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSRAD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FE2 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSRAD, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FE3 = function + | MPref.MPrxNP -> struct (Opcode.PAVGW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PAVGW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FE3 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPAVGW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FE4 = function + | MPref.MPrxNP -> struct (Opcode.PMULHUW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PMULHUW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FE4 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMULHUW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FE5 = function + | MPref.MPrxNP -> struct (Opcode.PMULHW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PMULHW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FE5 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMULHW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FE6 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.CVTTPD2DQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> struct (Opcode.CVTDQ2PD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF2 -> struct (Opcode.CVTPD2DQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FE6 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VCVTTPD2DQ, OD.GprRm, SZ.DqX) (* VdqWx *) + | MPref.MPrxF3 -> + struct (Opcode.VCVTDQ2PD, OD.GprRm, SZ.DqqdqX) (* VxWdqqdq *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0FE6W0 = function + | MPref.MPrxNP + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> struct (Opcode.VCVTDQ2PD, OD.GprRm, SZ.XXz) (* VZxzWx *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FE7 = function + | MPref.MPrxNP -> struct (Opcode.MOVNTQ, OD.RMMmx, SZ.QQ) (* MqPq *) + | MPref.MPrx66 -> struct (Opcode.MOVNTDQ, OD.RmGpr, SZ.DqDq) (* MdqVdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FE7 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VMOVNTDQ, OD.RmGpr, SZ.VecDef) (* MxVx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0FE7W1 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0FE7W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VMOVNTDQ, OD.RmGpr, SZ.VecDef) (* MZxzVZxz *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FE8 = function + | MPref.MPrxNP -> struct (Opcode.PSUBSB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSUBSB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FE8 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSUBSB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FE9 = function + | MPref.MPrxNP -> struct (Opcode.PSUBSW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSUBSW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FE9 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSUBSW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FEA = function + | MPref.MPrxNP -> struct (Opcode.PMINSW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PMINSW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FEA = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMINSW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FEB = function + | MPref.MPrxNP -> struct (Opcode.POR, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.POR, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FEB = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPOR, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FEC = function + | MPref.MPrxNP -> struct (Opcode.PADDSB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PADDSB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FEC = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPADDSB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FED = function + | MPref.MPrxNP -> struct (Opcode.PADDSW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PADDSW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FED = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPADDSW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FEE = function + | MPref.MPrxNP -> struct (Opcode.PMAXSW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PMAXSW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FEE = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMAXSW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FEF = function + | MPref.MPrxNP -> struct (Opcode.PXOR, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PXOR, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FEF = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPXOR, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0FEFW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPXORD, OD.XmmVvXm, SZ.XzXz) (* VZxzHxWZxz *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0FEFW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPXORQ, OD.XmmVvXm, SZ.XzXz) (* VZxzHxWZxz *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FF0 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> struct (Opcode.LDDQU, OD.GprRm, SZ.DqDq) (* VdqMdq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FF0 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> struct (Opcode.VLDDQU, OD.GprRm, SZ.VecDef) (* VxMx *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FF1 = function + | MPref.MPrxNP -> struct (Opcode.PSLLW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSLLW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FF1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSLLW, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FF2 = function + | MPref.MPrxNP -> struct (Opcode.PSLLD, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSLLD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FF2 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSLLD, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FF3 = function + | MPref.MPrxNP -> struct (Opcode.PSLLQ, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSLLQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FF3 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSLLQ, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FF4 = function + | MPref.MPrxNP -> struct (Opcode.PMULUDQ, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PMULUDQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FF4 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMULUDQ, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FF5 = function + | MPref.MPrxNP -> struct (Opcode.PMADDWD, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PMADDWD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FF5 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMADDWD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FF6 = function + | MPref.MPrxNP -> struct (Opcode.PSADBW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSADBW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FF6 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSADBW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FF8 = function + | MPref.MPrxNP -> struct (Opcode.PSUBB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSUBB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FF8 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSUBB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FF9 = function + | MPref.MPrxNP -> struct (Opcode.PSUBW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSUBW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FF9 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSUBW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FFA = function + | MPref.MPrxNP -> struct (Opcode.PSUBD, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSUBD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FFA = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSUBD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FFB = function + | MPref.MPrxNP -> struct (Opcode.PSUBQ, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSUBQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FFB = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSUBQ, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FFC = function + | MPref.MPrxNP -> struct (Opcode.PADDB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PADDB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FFC = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPADDB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FFD = function + | MPref.MPrxNP -> struct (Opcode.PADDW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PADDW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FFD = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPADDW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0FFE = function + | MPref.MPrxNP -> struct (Opcode.PADDD, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PADDD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FFE = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPADDD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3800 = function + | MPref.MPrxNP -> struct (Opcode.PSHUFB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSHUFB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3800 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSHUFB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3801 = function + | MPref.MPrxNP -> struct (Opcode.PHADDW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PHADDW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3801 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPHADDW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3802 = function + | MPref.MPrxNP -> struct (Opcode.PHADDD, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PHADDD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3802 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPHADDD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3803 = function + | MPref.MPrxNP -> struct (Opcode.PHADDSW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PHADDSW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3803 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPHADDSW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3805 = function + | MPref.MPrxNP -> struct (Opcode.PHSUBW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PHSUBW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3805 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPHSUBW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3806 = function + | MPref.MPrxNP -> struct (Opcode.PHSUBD, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PHSUBD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3806 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPHSUBD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3807 = function + | MPref.MPrxNP -> struct (Opcode.PHSUBSW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PHSUBSW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3807 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPHSUBSW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3808 = function + | MPref.MPrxNP -> struct (Opcode.PSIGNB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSIGNB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3808 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSIGNB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3809 = function + | MPref.MPrxNP -> struct (Opcode.PSIGNW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSIGNW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3809 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSIGNW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F380A = function + | MPref.MPrxNP -> struct (Opcode.PSIGND, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PSIGND, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F380A = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPSIGND, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F380B = function + | MPref.MPrxNP -> struct (Opcode.PMULHRSW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PMULHRSW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F380B = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPMULHRSW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3815 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.BLENDVPD, OD.XmmXmXmm0, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3817 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PTEST, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3817 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPTEST, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3818W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VBROADCASTSS, OD.GprRm, SZ.DX) (* VxMd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3818W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VBROADCASTSS, OD.GprRm, SZ.DqdXz) (* VZxzWdqd *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3819W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VBROADCASTSD, OD.GprRm, SZ.DqqQq) (* VqqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3819W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VBROADCASTSD, OD.GprRm, SZ.DqqXz) (* VZxzWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F381C = function + | MPref.MPrxNP -> struct (Opcode.PABSB, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PABSB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F381C = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPABSB, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F381D = function + | MPref.MPrxNP -> struct (Opcode.PABSW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PABSW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F381D = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPABSW, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F381E = function + | MPref.MPrxNP -> struct (Opcode.PABSD, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (Opcode.PABSD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F381E = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPABSD, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3820 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMOVSXBW, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3820 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPMOVSXBW, OD.GprRm, SZ.DqqdqX) (* VxWdqqdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3821 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMOVSXBD, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3821 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMOVSXBD, OD.GprRm, SZ.DqddqX) (* VxWdqdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3822 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMOVSXBQ, OD.GprRm, SZ.DqwDq) (* VdqWdqw *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3822 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMOVSXBQ, OD.GprRm, SZ.DqwX) (* VxWdqwd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3823 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMOVSXWD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3823 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPMOVSXWD, OD.GprRm, SZ.DqqdqX) (* VxWdqqdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3824 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMOVSXWQ, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3824 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMOVSXWQ, OD.GprRm, SZ.DqddqX) (* VxWdqdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3825 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMOVSXDQ, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3825 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPMOVSXDQ, OD.GprRm, SZ.DqqdqX) (* VxWdqqdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3828 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMULDQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3828 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMULDQ, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3829 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PCMPEQQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3829 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPCMPEQQ, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F382B = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PACKUSDW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F382B = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPACKUSDW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3830 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMOVZXBW, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3830 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPMOVZXBW, OD.GprRm, SZ.DqqdqX) (* VxWdqqdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3830 = function + | MPref.MPrxNP + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> struct (Opcode.VPMOVWB, OD.RmGpr, SZ.QqXz) (* WqqVZxz *) + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3831 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMOVZXBD, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3831 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMOVZXBD, OD.GprRm, SZ.DqddqX) (* VxWdqdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3832 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMOVZXBQ, OD.GprRm, SZ.DqwDq) (* VdqWdqw *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3832 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMOVZXBQ, OD.GprRm, SZ.DqwX) (* VxWdqwd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3833 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMOVZXWD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3833 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPMOVZXWD, OD.GprRm, SZ.DqqdqX) (* VxWdqqdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3833 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMOVZXWD, OD.GprRm, SZ.XqXz) (* VZxzWxq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3834 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMOVZXWQ, OD.GprRm, SZ.DqdDq) (* VdqWdqd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3834 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMOVZXWQ, OD.GprRm, SZ.DqddqX) (* VxWdqdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3835 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMOVZXDQ, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3835 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPMOVZXDQ, OD.GprRm, SZ.DqqdqX) (* VxWdqqdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3837 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PCMPGTQ, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3837 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPCMPGTQ, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3838 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMINSB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3838 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMINSB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3839 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMINSD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3839 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMINSD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F383A = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMINUW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F383A = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMINUW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F383B = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMINUD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F383B = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMINUD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F383C = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMAXSB, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F383C = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMAXSB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F383D = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMAXSD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F383D = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMAXSD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F383E = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMAXUW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F383E = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPMAXUW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F383F = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMAXUD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F383F = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPMAXUD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3840 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PMULLD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3840 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPMULLD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3841 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PHMINPOSUW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3841 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPHMINPOSUW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3843W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VGETEXPSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F384DW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VRCP14SD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3858W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPBROADCASTD, OD.GprRm, SZ.DqdX) (* VxWdqd *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3858W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPBROADCASTD, OD.GprRm, SZ.DqdXz) (* VZxzWdqd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3859W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPBROADCASTQ, OD.GprRm, SZ.DqdX) (* VxWdqd *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3859W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPBROADCASTQ, OD.GprRm, SZ.DqdXz) (* VZxzWdqd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F385A = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F385A = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VBROADCASTI128, OD.GprRm, SZ.DqQqq) (* VqqMdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3875W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPERMI2W, OD.XmmVvXm, SZ.XzXz) (* VZxzHxWZxz *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3876W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPERMI2D, OD.XmmVvXm, SZ.XzXz) (* VZxzHxWZxz *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3877W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPERMI2PD, OD.XmmVvXm, SZ.XzXz) (* VZxzHxWZxz *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3878 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3878 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPBROADCASTB, OD.GprRm, SZ.DqbX) (* VxWdqb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F387AW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPBROADCASTB, OD.GprRm, SZ.DXz) (* VZxzRd *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F387CW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPBROADCASTD, OD.GprRm, SZ.DXz) (* VZxzRd *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F387CW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.VPBROADCASTQ, OD.GprRm, SZ.QXz) (* VZxzRq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3890W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPGATHERDD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3890W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPGATHERDD, OD.GprRm, SZ.VecDef) (* VZxzWZxz *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3892W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VGATHERDPS, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3892W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VGATHERDPS, OD.GprRm, SZ.VecDef) (* VZxzWZxz *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3893W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VGATHERQPD, OD.XmmXmVv, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3898W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD132PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3898W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD132PD, OD.XmmVvXm, SZ.XzXz) (* VZxzHxWZxz *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3899W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD132SS, OD.XmmVvXm, SZ.DqdXz) (* VxHxWdqd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3899W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD132SD, OD.XmmVvXm, SZ.DqqX) (* VxHxWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F389BW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMSUB132SS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F389BW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMSUB132SS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F389CW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFNMADD132PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F389CW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFNMADD132PD, OD.XmmVvXm, SZ.XzXz) (* VZxzHxWZxz *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F389DW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFNMADD132SD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F389DW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFNMADD132SD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38A8W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD213PS, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38A8W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD213PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F38A8W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD213PS, OD.XmmVvXm, SZ.XzXz) (* VZxzHxWZxz *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38A9W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD213SS, OD.XmmVvXm, SZ.DqdXz) (* VxHxWdqd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38A9W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD213SD, OD.XmmVvXm, SZ.DqqX) (* VxHxWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38AAW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMSUB213PD, OD.XmmVvXm, SZ.DqqX) (* VxHxWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38ABW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMSUB213SD, OD.XmmVvXm, SZ.DqqX) (* VxHxWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38ACW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFNMADD213PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38ADW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFNMADD213SD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F38ADW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFNMADD213SD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38B8W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD231PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F38B8W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD231PD, OD.XmmVvXm, SZ.XzXz) (* VZxzHxWZxz *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38B9W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD231SS, OD.XmmVvXm, SZ.DqdXz) (* VxHxWdqd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38B9W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMADD231SD, OD.XmmVvXm, SZ.DqqX) (* VxHxWdqq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38BAW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMSUB231PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38BBW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMSUB231SD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F38BBW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFMSUB231SD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38BCW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFNMADD231PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F38BCW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFNMADD231PD, OD.XmmVvXm, SZ.XzXz) (* VZxzHxWZxz *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38BDW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFNMADD231SD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F38BDW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VFNMADD231SD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F38CBW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VRCP28SD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F38CDW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VRSQRT28SD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F38F0 = function + | MPref.MPrxNP -> struct (Opcode.MOVBE, OD.GprRm, SZ.Def) (* GyMy *) + | MPref.MPrx66 -> struct (Opcode.MOVBE, OD.GprRm, SZ.Word) (* GwMw *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> struct (Opcode.CRC32, OD.GprRm, SZ.BV) (* GvEb *) + | MPref.MPrx66F2 -> struct (Opcode.CRC32, OD.GprRm, SZ.BV) (* GvEb *) + | _ -> raise ParsingFailureException + + let nor0F38F1 = function + | MPref.MPrxNP -> struct (Opcode.MOVBE, OD.RmGpr, SZ.Def) (* MyGy *) + | MPref.MPrx66 -> struct (Opcode.MOVBE, OD.RmGpr, SZ.Word) (* MwGw *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> struct (Opcode.CRC32, OD.GprRm, SZ.Def) (* GvEy *) + | MPref.MPrx66F2 -> struct (Opcode.CRC32, OD.GprRm, SZ.WV) (* GvEw *) + | _ -> raise ParsingFailureException + + let vex0F38F2 = function + | MPref.MPrxNP -> struct (Opcode.ANDN, OD.GprVvRm, SZ.Def) (* GyByEy *) + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F38F5W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.WRUSSD, OD.RmGpr, SZ.Def) (* EyGy *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F38F5W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.WRUSSQ, OD.RmGpr, SZ.Def) (* EyGy *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38F5W0 = function + | MPref.MPrxNP -> struct (Opcode.BZHI, OD.GprRmVv, SZ.Def) (* GyEyBy *) + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> struct (Opcode.PEXT, OD.GprVvRm, SZ.Def) (* GyByEy *) + | MPref.MPrxF2 -> struct (Opcode.PDEP, OD.GprVvRm, SZ.Def) (* GyByEy *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38F5W1 = function + | MPref.MPrxNP -> struct (Opcode.BZHI, OD.GprRmVv, SZ.Def) (* GyEyBy *) + | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrxF3 -> struct (Opcode.PEXT, OD.GprVvRm, SZ.Def) (* GyByEy *) + | MPref.MPrxF2 -> struct (Opcode.PDEP, OD.GprVvRm, SZ.Def) (* GyByEy *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F38F6W0 = function + | MPref.MPrxNP -> struct (Opcode.WRSSD, OD.GprRm, SZ.Def) (* GyEy *) + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F38F6W1 = function + | MPref.MPrxNP -> struct (Opcode.WRSSQ, OD.GprRm, SZ.Def) (* GyEy *) + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38F6W0 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> struct (Opcode.MULX, OD.GprVvRm, SZ.Def) (* GyByEy *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38F6W1 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> struct (Opcode.MULX, OD.GprVvRm, SZ.Def) (* GyByEy *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F38F7 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F38F7 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.SHLX, OD.GprRmVv, SZ.Def) (* GyEyBy *) + | MPref.MPrxF3 -> struct (Opcode.SARX, OD.GprRmVv, SZ.Def) (* GyEyBy *) + | MPref.MPrxF2 -> struct (Opcode.SHRX, OD.GprRmVv, SZ.Def) (* GyEyBy *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A08 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.ROUNDPS, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A08 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VROUNDPS, OD.XmmRmImm8, SZ.VecDef) (* VxWxIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A09 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.ROUNDPD, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A09 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VROUNDPD, OD.XmmVvXmImm8, SZ.VecDef) (* VxHxWxIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A0B = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.ROUNDSD, OD.XmmRmImm8, SZ.DqqDq) (* VdqWdqqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A0B = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VROUNDSD, OD.XmmVvXmImm8, SZ.DqqDq) (* VdqHdqWdqqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A0BW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VRNDSCALESD, OD.XmmVvXmImm8, SZ.DqqDq) (* VdqHdqWdqqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A0F = function + | MPref.MPrxNP -> struct (Opcode.PALIGNR, OD.MmxMmImm8, SZ.QQ) (* PqQqIb *) + | MPref.MPrx66 -> + struct (Opcode.PALIGNR, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A0F = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPALIGNR, OD.XmmVvXmImm8, SZ.VecDef) (* VxHxWxIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A15 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.PEXTRW, OD.XmRegImm8, SZ.DwDq) (* EdwVdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A15 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPEXTRW, OD.XmRegImm8, SZ.DwDq) (* EdwVdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A16 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.PEXTRD, OD.XmRegImm8, SZ.DwDq) (* EdwVdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A16 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPEXTRD, OD.XmRegImm8, SZ.DwDq) (* EdwVdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A18W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VINSERTF128, OD.XmmVvXmImm8, SZ.DqQqq) (* VqqHqqWdqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A19W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VEXTRACTF128, OD.XmRegImm8, SZ.DqQq) (* WdqVqqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A19W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VEXTRACTF32X4, OD.XmRegImm8, SZ.DqXz) (* WdqVZxzIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A19W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VEXTRACTF64X2, OD.XmRegImm8, SZ.DqXz) (* WdqVZxzIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A1AW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VINSERTF64X4, OD.XmmVvXmImm8, SZ.QqXzRM) (* VZxzHxWqqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A1BW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VEXTRACTF32X8, OD.XmRegImm8, SZ.QqXz) (* WZqqVZxzIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A1BW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VEXTRACTF64X4, OD.XmRegImm8, SZ.QqXz) (* WZqqVZxzIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A20 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (Opcode.PINSRB, OD.XmmRmImm8, SZ.DbDq) (* VdqEdbIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A20 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPINSRB, OD.XmmVvXmImm8, SZ.DbDq) (* VdqHdqEdbIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A22W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPINSRD, OD.XmmVvXmImm8, SZ.YDq) (* VdqHdqEyIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A22W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPINSRQ, OD.XmmVvXmImm8, SZ.YDq) (* VdqHdqEyIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A22W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPINSRD, OD.XmmVvXmImm8, SZ.YDq) (* VdqHdqEyIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A22W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPINSRQ, OD.XmmVvXmImm8, SZ.YDq) (* VdqHdqEyIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A25W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPTERNLOGD, OD.XmmVvXmImm8, SZ.XzXz) (* VZxzHxWZxzIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A27W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VGETMANTSD, OD.XmmVvXmImm8, SZ.DqqDq) (* VdqHdqWdqqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A38 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A38 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VINSERTI128, OD.XmmVvXmImm8, SZ.DqQqq) (* VqqHqqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A3AW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VINSERTI32X8, OD.XmmVvXmImm8, SZ.QqXzRM) (* VZxzHxWqqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A3AW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VINSERTI64X4, OD.XmmVvXmImm8, SZ.QqXzRM) (* VZxzHxWqqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A3BW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VEXTRACTI32X8, OD.XmRegImm8, SZ.QqXz) (* WqqVZxzIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A3BW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VEXTRACTI64X4, OD.XmRegImm8, SZ.QqXz) (* WqqVZxzIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A43W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VSHUFI32X4, OD.XmmVvXmImm8, SZ.XzXz) (* VZxzHxWZxzIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A43W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VSHUFI64X2, OD.XmmVvXmImm8, SZ.XzXz) (* VZxzHxWZxzIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A4BW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VBLENDVPD, OD.XmmVvXmXmm, SZ.VecDef) (* VxHxWxLx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A57W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VREDUCESD, OD.XmmVvXmImm8, SZ.DqqDq) (* VdqHdqWdqqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A60 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.PCMPESTRM, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A60 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPCMPESTRM, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A61 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.PCMPESTRI, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A61 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPCMPESTRI, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A62 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.PCMPISTRM, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A62 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPCMPISTRM, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A63 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.PCMPISTRI, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A63 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (Opcode.VPCMPISTRI, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3AF0 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3AF0 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> struct (Opcode.RORX, OD.XmmRmImm8, SZ.Def) (* GyEyIb *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let grp1Op = function + | 0 -> Opcode.ADD + | 1 -> Opcode.OR + | 2 -> Opcode.ADC + | 3 -> Opcode.SBB + | 4 -> Opcode.AND + | 5 -> Opcode.SUB + | 6 -> Opcode.XOR + | 7 -> Opcode.CMP + | _ -> raise ParsingFailureException + + let grp2Op = function + | 0 -> Opcode.ROL + | 1 -> Opcode.ROR + | 2 -> Opcode.RCL + | 3 -> Opcode.RCR + | 4 -> Opcode.SHL + | 5 -> Opcode.SHR + | 6 -> Opcode.InvalOP + | 7 -> Opcode.SAR + | _ -> raise ParsingFailureException + + let grp4Op = function + | 0 -> Opcode.INC + | 1 -> Opcode.DEC + | _ -> raise ParsingFailureException + + let grp5 = function + | 0 -> struct (Opcode.INC, OD.Mem, SZ.Def, SzCond.Nor) + | 1 -> struct (Opcode.DEC, OD.Mem, SZ.Def, SzCond.Nor) + | 2 -> struct (Opcode.CALLNear, OD.Mem, SZ.Def, SzCond.F64) + | 3 -> struct (Opcode.CALLFar, OD.Mem, SZ.P, SzCond.Nor) + | 4 -> struct (Opcode.JMPNear, OD.Mem, SZ.Def, SzCond.F64) + | 5 -> struct (Opcode.JMPFar, OD.Dir, SZ.P, SzCond.Nor) + | 6 -> struct (Opcode.PUSH, OD.Mem, SZ.Def, SzCond.D64) + | _ -> raise ParsingFailureException + + let grp7 = function + | 0 -> struct (Opcode.SGDT, OD.Mem, SZ.S, SzCond.Nor) + | 1 -> struct (Opcode.SIDT, OD.Mem, SZ.S, SzCond.Nor) + | 2 -> struct (Opcode.LGDT, OD.Mem, SZ.S, SzCond.Nor) + | 3 -> struct (Opcode.LIDT, OD.Mem, SZ.S, SzCond.Nor) + | 4 -> struct (Opcode.SMSW, OD.Mem, SZ.MemW, SzCond.Nor) + | 5 -> struct (Opcode.RSTORSSP, OD.Mem, SZ.Q, SzCond.Nor) + | 6 -> struct (Opcode.LMSW, OD.Mem, SZ.MemW, SzCond.Nor) + | 7 -> struct (Opcode.INVLPG, OD.Mem, SZ.MemW, SzCond.Nor) + | _ -> raise ParsingFailureException + + let grp8Op = function + | 0 -> Opcode.InvalOP + | 1 -> Opcode.InvalOP + | 2 -> Opcode.InvalOP + | 3 -> Opcode.InvalOP + | 4 -> Opcode.BT + | 5 -> Opcode.BTS + | 6 -> Opcode.BTR + | 7 -> Opcode.BTC + | _ -> raise ParsingFailureException + + let grp16Op = function + | 0 -> Opcode.PREFETCHNTA + | 1 -> Opcode.PREFETCHT0 + | 2 -> Opcode.PREFETCHT1 + | 3 -> Opcode.PREFETCHT2 + | _ -> raise ParsingFailureException + + let getGrp3OpKind oidx sidx oprGrp regBits = + match regBits with + | 0b000 when oprGrp = OpGroup.G3A -> + struct (Opcode.TEST, OD.RmImm8, SZ.Byte, SzCond.Nor) + | 0b000 when oprGrp = OpGroup.G3B -> + struct (Opcode.TEST, OD.RmImm, SZ.Def, SzCond.Nor) + | 0b010 -> struct (Opcode.NOT, oidx, sidx, SzCond.Nor) + | 0b011 -> struct (Opcode.NEG, oidx, sidx, SzCond.Nor) + | 0b100 -> struct (Opcode.MUL, oidx, sidx, SzCond.Nor) + | 0b101 -> struct (Opcode.IMUL, oidx, sidx, SzCond.Nor) + | 0b110 -> struct (Opcode.DIV, oidx, sidx, SzCond.Nor) + | 0b111 -> struct (Opcode.IDIV, oidx, sidx, SzCond.Nor) + | _ -> raise ParsingFailureException + + let getGrp6OpKind b regBits = + match modIsMemory b, regBits with + | true, 0b000 -> struct (Opcode.SLDT, OD.Mem, SZ.MemW, SzCond.Nor) + | false, 0b000 -> struct (Opcode.SLDT, OD.Mem, SZ.Def, SzCond.Nor) + | true, 0b001 -> struct (Opcode.STR, OD.Mem, SZ.MemW, SzCond.Nor) + | false, 0b001 -> struct (Opcode.STR, OD.Mem, SZ.Def, SzCond.Nor) + | _, 0b010 -> struct (Opcode.LLDT, OD.Mem, SZ.MemW, SzCond.Nor) + | _, 0b011 -> struct (Opcode.LTR, OD.Mem, SZ.MemW, SzCond.Nor) + | _, 0b100 -> struct (Opcode.VERR, OD.Mem, SZ.MemW, SzCond.Nor) + | _, 0b101 -> struct (Opcode.VERW, OD.Mem, SZ.MemW, SzCond.Nor) + | _ -> raise ParsingFailureException + + let parseGrp7OpKind (rhlp: ReadHelper) b regBits = + if modIsMemory b then grp7 regBits + else + match regBits, getRM b with + | 0b000, 0b001 -> + rhlp.IncPos (); struct (Opcode.VMCALL, OD.No, SZ.Def, SzCond.Nor) + | 0b000, 0b010 -> + rhlp.IncPos (); struct (Opcode.VMLAUNCH, OD.No, SZ.Def, SzCond.Nor) + | 0b000, 0b011 -> + rhlp.IncPos (); struct (Opcode.VMRESUME, OD.No, SZ.Def, SzCond.Nor) + | 0b000, 0b100 -> + rhlp.IncPos (); struct (Opcode.VMXOFF, OD.No, SZ.Def, SzCond.Nor) + | 0b001, 0b000 -> + rhlp.IncPos (); struct (Opcode.MONITOR, OD.No, SZ.Def, SzCond.Nor) + | 0b001, 0b001 -> + rhlp.IncPos (); struct (Opcode.MWAIT, OD.No, SZ.Def, SzCond.Nor) + | 0b001, 0b010 -> + rhlp.IncPos (); struct (Opcode.CLAC, OD.No, SZ.Def, SzCond.Nor) + | 0b001, 0b011 -> + rhlp.IncPos (); struct (Opcode.STAC, OD.No, SZ.Def, SzCond.Nor) + | 0b010, 0b000 -> + rhlp.IncPos (); struct (Opcode.XGETBV, OD.No, SZ.Def, SzCond.Nor) + | 0b010, 0b001 -> + rhlp.IncPos (); struct (Opcode.XSETBV, OD.No, SZ.Def, SzCond.Nor) + | 0b010, 0b100 -> + rhlp.IncPos (); struct (Opcode.VMFUNC, OD.No, SZ.Def, SzCond.Nor) + | 0b010, 0b101 -> + rhlp.IncPos (); struct (Opcode.XEND, OD.No, SZ.Def, SzCond.Nor) + | 0b010, 0b110 -> + rhlp.IncPos (); struct (Opcode.XTEST, OD.No, SZ.Def, SzCond.Nor) + | 0b100, _ -> struct (Opcode.SMSW, OD.Mem, SZ.Def, SzCond.Nor) + | 0b101, 0b000 -> + rhlp.IncPos (); struct (Opcode.SETSSBSY, OD.No, SZ.Def, SzCond.Nor) + | 0b101, 0b010 -> + rhlp.IncPos (); struct (Opcode.SAVEPREVSSP, OD.No, SZ.Def, SzCond.Nor) + | 0b101, 0b110 -> + rhlp.IncPos (); struct (Opcode.RDPKRU, OD.No, SZ.Def, SzCond.Nor) + | 0b101, 0b111 -> + rhlp.IncPos (); struct (Opcode.WRPKRU, OD.No, SZ.Def, SzCond.Nor) + | 0b110, _ -> struct (Opcode.LMSW, OD.Mem, SZ.MemW, SzCond.Nor) + | 0b111, 0b000 -> +#if !EMULATION + ensure32 rhlp +#endif + rhlp.IncPos (); struct (Opcode.SWAPGS, OD.No, SZ.Def, SzCond.Nor) + | 0b111, 0b001 -> + rhlp.IncPos (); struct (Opcode.RDTSCP, OD.No, SZ.Def, SzCond.Nor) + | _ -> raise ParsingFailureException + + let getGrp9OpKind (rhlp: ReadHelper) b regBits = + let hasOprSzPref = hasOprSz rhlp.Prefixes + let hasREPZPref = hasREPZ rhlp.Prefixes + let hasREXWPref = hasREXW rhlp.REXPrefix + match modIsMemory b, regBits, hasOprSzPref, hasREPZPref, hasREXWPref with + | true, 0b001, false, false, false -> + struct (Opcode.CMPXCHG8B, OD.Mem, SZ.Q, SzCond.Nor) + | true, 0b001, false, false, true -> + struct (Opcode.CMPXCHG16B, OD.Mem, SZ.Dq, SzCond.Nor) + | true, 0b011, false, false, false -> + struct (Opcode.XRSTORS, OD.Mem, SZ.Q, SzCond.Nor) + | true, 0b011, false, false, true -> + struct (Opcode.XRSTORS64, OD.Mem, SZ.Q, SzCond.Nor) + | true, 0b100, false, false, false -> + struct (Opcode.XSAVEC, OD.Mem, SZ.Q, SzCond.Nor) + | true, 0b100, false, false, true -> + struct (Opcode.XSAVEC64, OD.Mem, SZ.Q, SzCond.Nor) + | true, 0b101, false, false, false -> + struct (Opcode.XSAVES, OD.Mem, SZ.Q, SzCond.Nor) + | true, 0b101, false, false, true -> + struct (Opcode.XSAVES64, OD.Mem, SZ.Q, SzCond.Nor) + | true, 0b110, false, false, _ -> + struct (Opcode.VMPTRLD, OD.Mem, SZ.Q, SzCond.Nor) + | true, 0b111, false, false, _ -> + struct (Opcode.VMPTRST, OD.Mem, SZ.Q, SzCond.Nor) + | true, 0b110, true, false, _ -> + struct (Opcode.VMCLEAR, OD.Mem, SZ.Q, SzCond.Nor) + | true, 0b110, false, true, _ -> + struct (Opcode.VMXON, OD.Mem, SZ.Q, SzCond.Nor) + | true, 0b111, false, true, _ -> + struct (Opcode.VMPTRST, OD.Mem, SZ.Q, SzCond.Nor) + | false, 0b110, false, false, _ -> + struct (Opcode.RDRAND, OD.Mem, SZ.Def, SzCond.Nor) + | false, 0b111, false, false, _ -> + struct (Opcode.RDSEED, OD.Mem, SZ.Def, SzCond.Nor) + | _ -> raise ParsingFailureException + + let getGrp11OpKind rhlp op oidx1 sz1 b reg oidx2 sz2 = + match reg with + | 0b000 -> struct (Opcode.MOV, oidx2, sz2, SzCond.Nor) + | 0b111 when modIsMemory b -> raise ParsingFailureException + | 0b111 -> + if (rhlp: ReadHelper).ReadByte () = 0xF8uy then + struct (op, oidx1, sz1, SzCond.Nor) + else raise ParsingFailureException + | _ -> raise ParsingFailureException + + let getGrp12OpKind rhlp b regBits = + match modIsMemory b, regBits, hasOprSz (selectPrefix rhlp) with + | false, 0b010, false -> struct (Opcode.PSRLW, OD.MmxImm8, SZ.Q, SzCond.Nor) + | false, 0b010, true -> + if rhlp.VEXInfo = None then + struct (Opcode.PSRLW, OD.RmImm8, SZ.Dq, SzCond.Nor) + else struct (Opcode.VPSRLW, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) + | false, 0b100, false -> struct (Opcode.PSRAW, OD.MmxImm8, SZ.Q, SzCond.Nor) + | false, 0b100, true -> + if rhlp.VEXInfo = None then + struct (Opcode.PSRAW, OD.RmImm8, SZ.Dq, SzCond.Nor) + else struct (Opcode.VPSRAW, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) + | false, 0b110, false -> struct (Opcode.PSLLW, OD.MmxImm8, SZ.Q, SzCond.Nor) + | false, 0b110, true -> + if rhlp.VEXInfo = None then + struct (Opcode.PSLLW, OD.RmImm8, SZ.Dq, SzCond.Nor) + else struct (Opcode.VPSLLW, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) + | _ -> raise ParsingFailureException + + let getGrp13OpKind rhlp b regBits = + match modIsMemory b, regBits, hasOprSz (selectPrefix rhlp) with + | false, 0b010, false -> struct (Opcode.PSRLD, OD.MmxImm8, SZ.Q, SzCond.Nor) + | false, 0b010, true -> + if rhlp.VEXInfo = None then + struct (Opcode.PSRLD, OD.RmImm8, SZ.Dq, SzCond.Nor) + else struct (Opcode.VPSRLD, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) + | false, 0b100, false -> struct (Opcode.PSRAD, OD.MmxImm8, SZ.Q, SzCond.Nor) + | false, 0b100, true -> + if rhlp.VEXInfo = None then + struct (Opcode.PSRAD, OD.RmImm8, SZ.Dq, SzCond.Nor) + else struct (Opcode.VPSRAD, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) + | false, 0b110, false -> struct (Opcode.PSLLD, OD.MmxImm8, SZ.Q, SzCond.Nor) + | false, 0b110, true -> + if rhlp.VEXInfo = None then + struct (Opcode.PSLLD, OD.RmImm8, SZ.Dq, SzCond.Nor) + else struct (Opcode.VPSLLD, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) + | _ -> raise ParsingFailureException + + let getGrp14OpKind rhlp b regBits = + match modIsMemory b, regBits, hasOprSz (selectPrefix rhlp) with + | false, 0b010, false -> + struct (Opcode.PSRLQ, OD.MmxImm8, SZ.Q, SzCond.Nor) + | false, 0b010, true -> + if rhlp.VEXInfo = None then + struct (Opcode.PSRLQ, OD.RmImm8, SZ.Dq, SzCond.Nor) + else struct (Opcode.VPSRLQ, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) + | false, 0b011, true -> + if rhlp.VEXInfo = None then + struct (Opcode.PSRLDQ, OD.RmImm8, SZ.Dq, SzCond.Nor) + else struct (Opcode.VPSRLDQ, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) + | false, 0b110, false -> struct (Opcode.PSLLQ, OD.MmxImm8, SZ.Q, SzCond.Nor) + | false, 0b110, true -> + if rhlp.VEXInfo = None then + struct (Opcode.PSLLQ, OD.RmImm8, SZ.Dq, SzCond.Nor) + else struct (Opcode.VPSLLQ, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) + | false, 0b111, true -> + if rhlp.VEXInfo = None then + struct (Opcode.PSLLDQ, OD.RmImm8, SZ.Dq, SzCond.Nor) + else struct (Opcode.VPSLLDQ, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) + | _ -> raise ParsingFailureException + + let parseGrp15OpKind (rhlp: ReadHelper) b regBits = + match modIsMemory b, regBits, hasREPZ rhlp.Prefixes with + | true, 0b110, true -> struct (Opcode.CLRSSBSY, OD.Mem, SZ.Q, SzCond.Nor) + | true, 0b000, false -> + let op = if hasREXW rhlp.REXPrefix then Opcode.FXSAVE64 else Opcode.FXSAVE + struct (op, OD.Mem, SZ.Def, SzCond.Nor) + | true, 0b001, false -> + let op = + if hasREXW rhlp.REXPrefix then Opcode.FXRSTOR64 else Opcode.FXRSTOR + struct (op, OD.Mem, SZ.Def, SzCond.Nor) + | true, 0b010, false -> struct (Opcode.LDMXCSR, OD.Mem, SZ.D, SzCond.Nor) + | true, 0b011, false -> struct (Opcode.STMXCSR, OD.Mem, SZ.D, SzCond.Nor) + | true, 0b100, false -> struct (Opcode.XSAVE, OD.Mem, SZ.Def, SzCond.Nor) + | true, 0b101, false -> struct (Opcode.XRSTOR, OD.Mem, SZ.Def, SzCond.Nor) + | true, 0b110, false -> struct (Opcode.XSAVEOPT, OD.Mem, SZ.Def, SzCond.Nor) + | true, 0b111, false -> struct (Opcode.CLFLUSH, OD.Mem, SZ.BV, SzCond.Nor) + | false, 0b101, false -> + rhlp.IncPos (); struct (Opcode.LFENCE, OD.No, SZ.Def, SzCond.Nor) + | false, 0b110, false -> + rhlp.IncPos (); struct (Opcode.MFENCE, OD.No, SZ.Def, SzCond.Nor) + | false, 0b111, false -> + rhlp.IncPos (); struct (Opcode.SFENCE, OD.No, SZ.Def, SzCond.Nor) + | false, 0b000, true -> struct (Opcode.RDFSBASE, OD.Gpr, SZ.Def, SzCond.Nor) + | false, 0b001, true -> struct (Opcode.RDGSBASE, OD.Gpr, SZ.Def, SzCond.Nor) + | false, 0b010, true -> struct (Opcode.WRFSBASE, OD.Gpr, SZ.Def, SzCond.Nor) + | false, 0b011, true -> struct (Opcode.WRGSBASE, OD.Gpr, SZ.Def, SzCond.Nor) + | false, 0b101, true -> + let op = if hasREXW rhlp.REXPrefix then Opcode.INCSSPQ else Opcode.INCSSPD + struct (op, OD.Gpr, SZ.Def, SzCond.Nor) + | _ -> raise ParsingFailureException + + let parseGrpOpKind (rhlp: ReadHelper) oidx sidx oprGrp = + let b = rhlp.PeekByte () + let r = getReg b + match oprGrp with + | OpGroup.G1 -> struct (grp1Op r, oidx, sidx, SzCond.Nor) + | OpGroup.G1Inv64 -> +#if !EMULATION + ensure32 rhlp +#endif + struct (grp1Op r, oidx, sidx, SzCond.Nor) + | OpGroup.G1A -> struct (Opcode.POP, oidx, sidx, SzCond.D64) + | OpGroup.G2 when r = 0b110 -> raise ParsingFailureException + | OpGroup.G2 -> struct (grp2Op r, oidx, sidx, SzCond.Nor) + | OpGroup.G3A | OpGroup.G3B -> getGrp3OpKind oidx sidx oprGrp r + | OpGroup.G4 -> struct (grp4Op r, OD.Mem, SZ.Byte, SzCond.Nor) + | OpGroup.G5 -> grp5 r + | OpGroup.G6 -> getGrp6OpKind b r + | OpGroup.G7 -> parseGrp7OpKind rhlp b r + | OpGroup.G8 -> struct (grp8Op r, oidx, sidx, SzCond.Nor) + | OpGroup.G9 -> getGrp9OpKind rhlp b r + | OpGroup.G11A -> + getGrp11OpKind rhlp Opcode.XABORT OD.Imm8 SZ.Def b r oidx sidx + | OpGroup.G11B -> + getGrp11OpKind rhlp Opcode.XBEGIN OD.Rel SZ.D64 b r oidx sidx + | OpGroup.G12 -> getGrp12OpKind rhlp b r + | OpGroup.G13 -> getGrp13OpKind rhlp b r + | OpGroup.G14 -> getGrp14OpKind rhlp b r + | OpGroup.G15 -> parseGrp15OpKind rhlp b r + | OpGroup.G16 -> struct (grp16Op r, oidx, sidx, SzCond.Nor) + | OpGroup.G10 | OpGroup.G17 + | _ -> + raise ParsingFailureException (* Not implemented yet *) + + /// Add BND prefix (Intel MPX extension). + let addBND (rhlp: ReadHelper) = + if hasREPNZ rhlp.Prefixes then + rhlp.Prefixes <- Prefix.PrxBND ||| (clearGrp1PrefMask &&& rhlp.Prefixes) + else () + + let inline getMandPrx (prefix: Prefix) = + match int prefix &&& 0x40a with + | 0x402 -> MPref.MPrx66F2 + | 0x2 -> MPref.MPrxF2 + | 0x400 -> MPref.MPrx66 + | 0x8 -> MPref.MPrxF3 + | 0x0 -> MPref.MPrxNP + | _ -> raise ParsingFailureException + + /// Some instructions use 66/F2/F3 prefix as a mandatory prefix. When both + /// VEX.pp and old-style prefix are used, the VEX.pp is used to select the + /// opcodes. But if VEX.pp does not exist, then we have to use the old-style + /// prefix, and we have to filter out the prefixes because they are not going + /// to be used as a normal prefixes. They will only be used as a mandatory + /// prefix to decide the opcode. + let inline filterPrefs (prefix: Prefix) = prefix &&& clearVEXPrefMask + + let getInstr prefix fnInstr = fnInstr (getMandPrx prefix) + + /// The main instruction rendering function. + let render (rhlp: ReadHelper) opcode szCond (oidx: OprDesc) (sidx: SizeKind) = + rhlp.SzComputers.[int sidx].Render rhlp szCond + exceptionalOperationSize opcode rhlp + let oprs = rhlp.OprParsers.[int oidx].Render rhlp + newInsInfo rhlp opcode oprs + + /// Parse group Opcodes: Vol.2C A-19 Table A-6. Opcode Extensions for One- and + /// Two-byte Opcodes by Group Number. + let parseGrpOp rhlp grp oidx sidx = + let struct (op, oidx, szidx, szCond) = parseGrpOpKind rhlp oidx sidx grp + if isBranch op then addBND rhlp |> ignore + elif isCETInstr op then rhlp.Prefixes <- clearGrp1PrefMask &&& rhlp.Prefixes + else () + render rhlp op szCond oidx szidx + + /// Normal/VEX + let parseVEX (rhlp: ReadHelper) fnNor fnVex = + match rhlp.VEXInfo with + | None -> + let struct (op, oidx, sidx) = fnNor (getMandPrx rhlp.Prefixes) + rhlp.Prefixes <- filterPrefs rhlp.Prefixes + render rhlp op SzCond.Nor oidx sidx + | Some v -> + let struct (op, oidx, sidx) = fnVex (getMandPrx v.VPrefixes) + render rhlp op SzCond.Nor oidx sidx + + /// Normal(REX.W), VEX(REX.W) + let selectVEXW (rhlp: ReadHelper) fnNorW0 fnNorW1 fnVexW0 fnVexW1 = + match rhlp.VEXInfo with + | None -> + let fnNor = if hasREXW rhlp.REXPrefix then fnNorW1 else fnNorW0 + let ins = getInstr rhlp.Prefixes fnNor + rhlp.Prefixes <- filterPrefs rhlp.Prefixes + ins + | Some v -> + let fnVex = if hasREXW rhlp.REXPrefix then fnVexW1 else fnVexW0 + getInstr v.VPrefixes fnVex + + /// Normal/VEX (Both REX.W) + let parseVEXW rhlp fnNorW0 fnNorW1 fnVexW0 fnVexW1 = + let struct (op, oidx, sidx) = + selectVEXW rhlp fnNorW0 fnNorW1 fnVexW0 fnVexW1 + render rhlp op SzCond.Nor oidx sidx + + /// Normal(REX.W), VEX(REX.W) + /// Normal, VEX, EVEX(REX.W) + let selectEVEX (rhlp: ReadHelper) fnNor fnVex fnEVexW0 fnEVexW1 = + match rhlp.VEXInfo with + | None -> + let ins = getInstr rhlp.Prefixes fnNor + rhlp.Prefixes <- filterPrefs rhlp.Prefixes + ins + | Some v -> + if v.VEXType &&& VEXType.EVEX = VEXType.EVEX then + let fnEVex = if hasREXW rhlp.REXPrefix then fnEVexW1 else fnEVexW0 + getInstr v.VPrefixes fnEVex + else getInstr v.VPrefixes fnVex + + /// Normal/VEX/EVEX (EVEX REX.W) + let parseEVEX rhlp fnNor fnVex fnEVexW0 fnEVexW1 = + let struct (op, oidx, sidx) = + selectEVEX rhlp fnNor fnVex fnEVexW0 fnEVexW1 + render rhlp op SzCond.Nor oidx sidx + + /// VEX(REX.W), EVEX(REX.W) + let selectEVEXW (rhlp: ReadHelper) fnVexW0 fnVexW1 fnEVexW0 fnEVexW1 = + match rhlp.VEXInfo with + | None -> raise ParsingFailureException + | Some v -> + if v.VEXType &&& VEXType.EVEX = VEXType.EVEX then + let fnEVex = if hasREXW rhlp.REXPrefix then fnEVexW1 else fnEVexW0 + getInstr v.VPrefixes fnEVex + else + let fnVex = if hasREXW rhlp.REXPrefix then fnVexW1 else fnVexW0 + getInstr v.VPrefixes fnVex + + /// VEX/EVEX (Both REX.W) + let parseEVEXW rhlp fnVexW0 fnVexW1 fnEVexW0 fnEVexW1 = + let struct (op, oidx, sidx) = + selectEVEXW rhlp fnVexW0 fnVexW1 fnEVexW0 fnEVexW1 + render rhlp op SzCond.Nor oidx sidx + + /// Parse non-VEX instructions. + let parseNonVEX (rhlp: ReadHelper) fnNor = + let struct (op, oidx, sidx) = getInstr rhlp.Prefixes fnNor + rhlp.Prefixes <- filterPrefs rhlp.Prefixes + render rhlp op SzCond.Nor oidx sidx + + /// Parse non-VEX instructions. + let pVEXByMem (rhlp: ReadHelper) fnNorM fnNorR fnVexM fnVexR = + let struct (fnNor, fnVex) = + if rhlp.PeekByte () |> modIsMemory then struct (fnNorM, fnVexM) + else struct (fnNorR, fnVexR) + parseVEX rhlp fnNor fnVex + + /// Parse BND-related instructions. + let parseBND (rhlp: ReadHelper) szCond fnBND = + let struct (op, oidx, sidx) = getInstr rhlp.Prefixes fnBND + rhlp.Prefixes <- filterPrefs rhlp.Prefixes + render rhlp op szCond oidx sidx + + let parseCETInstr (rhlp: ReadHelper) = + let struct (op, oidx, sidx) = + match rhlp.PeekByte () with + | 0xFAuy -> rhlp.IncPos (); struct (Opcode.ENDBR64, OD.No, SZ.Def) + | 0xFBuy -> rhlp.IncPos (); struct (Opcode.ENDBR32, OD.No, SZ.Def) + | b when getReg b = 0b001 && getMod b = 0b11 -> + let op = if hasREXW rhlp.REXPrefix then Opcode.RDSSPQ else Opcode.RDSSPD + struct (op, OD.Gpr, SZ.Def) + | _ -> raise InvalidOpcodeException + rhlp.Prefixes <- clearGrp1PrefMask &&& rhlp.Prefixes + render rhlp op SzCond.Nor oidx sidx + + let parseESCOp (rhlp: ReadHelper) escFlag getOpIn getOpOut = + let modRM = rhlp.ReadByte () + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + if modRM <= 0xBFuy then + let op = getOpIn modRM + let effOprSize = + match escFlag with + | 0xD9uy -> getReg modRM |> getD9EscEffOprSizeByModRM + | 0xDBuy -> getReg modRM |> getDBEscEffOprSizeByModRM + | 0xDDuy -> getReg modRM |> getDDEscEffOprSizeByModRM + | 0xDFuy -> getReg modRM |> getDFEscEffOprSizeByModRM + | _ -> escFlag |> getEscEffOprSizeByESCOp + rhlp.MemEffOprSize <- effOprSize + rhlp.MemEffRegSize <- effOprSize + let o = OperandParsingHelper.parseMemory modRM rhlp + newInsInfo rhlp op (OneOperand o) + else + let opcode, oprs = getOpOut modRM + newInsInfo rhlp opcode oprs + + /// When the first two bytes are 0F38. + /// Table A-4 of Volume 2 (Three-byte Opcode Map : First Two Bytes are 0F 38H) + let parseThreeByteOp1 (rhlp: ReadHelper) = + match rhlp.ReadByte () with + | 0x00uy -> parseVEX rhlp nor0F3800 vex0F3800 + | 0x01uy -> parseVEX rhlp nor0F3801 vex0F3801 + | 0x02uy -> parseVEX rhlp nor0F3802 vex0F3802 + | 0x03uy -> parseVEX rhlp nor0F3803 vex0F3803 + | 0x05uy -> parseVEX rhlp nor0F3805 vex0F3805 + | 0x06uy -> parseVEX rhlp nor0F3806 vex0F3806 + | 0x07uy -> parseVEX rhlp nor0F3807 vex0F3807 + | 0x08uy -> parseVEX rhlp nor0F3808 vex0F3808 + | 0x09uy -> parseVEX rhlp nor0F3809 vex0F3809 + | 0x0auy -> parseVEX rhlp nor0F380A vex0F380A + | 0x0buy -> parseVEX rhlp nor0F380B vex0F380B + | 0x15uy -> parseVEX rhlp nor0F3815 notEn + | 0x17uy -> parseVEX rhlp nor0F3817 vex0F3817 + | 0x18uy -> parseEVEXW rhlp vex0F3818W0 notEn evex0F3818W0 notEn + | 0x19uy -> parseEVEXW rhlp vex0F3819W0 notEn notEn evex0F3819W1 + | 0x1cuy -> parseVEX rhlp nor0F381C vex0F381C + | 0x1duy -> parseVEX rhlp nor0F381D vex0F381D + | 0x1euy -> parseVEX rhlp nor0F381E vex0F381E + | 0x20uy -> parseVEX rhlp nor0F3820 vex0F3820 + | 0x21uy -> parseVEX rhlp nor0F3821 vex0F3821 + | 0x22uy -> parseVEX rhlp nor0F3822 vex0F3822 + | 0x23uy -> parseVEX rhlp nor0F3823 vex0F3823 + | 0x24uy -> parseVEX rhlp nor0F3824 vex0F3824 + | 0x25uy -> parseVEX rhlp nor0F3825 vex0F3825 + | 0x28uy -> parseVEX rhlp nor0F3828 vex0F3828 + | 0x29uy -> parseVEX rhlp nor0F3829 vex0F3829 + | 0x2buy -> parseVEX rhlp nor0F382B vex0F382B + | 0x30uy -> parseEVEX rhlp nor0F3830 vex0F3830 evex0F3830 evex0F3830 + | 0x31uy -> parseVEX rhlp nor0F3831 vex0F3831 + | 0x32uy -> parseVEX rhlp nor0F3832 vex0F3832 + | 0x33uy -> parseEVEX rhlp nor0F3833 vex0F3833 evex0F3833 evex0F3833 + | 0x34uy -> parseVEX rhlp nor0F3834 vex0F3834 + | 0x35uy -> parseVEX rhlp nor0F3835 vex0F3835 + | 0x37uy -> parseVEX rhlp nor0F3837 vex0F3837 + | 0x38uy -> parseVEX rhlp nor0F3838 vex0F3838 + | 0x39uy -> parseVEX rhlp nor0F3839 vex0F3839 + | 0x3auy -> parseVEX rhlp nor0F383A vex0F383A + | 0x3buy -> parseVEX rhlp nor0F383B vex0F383B + | 0x3cuy -> parseVEX rhlp nor0F383C vex0F383C + | 0x3duy -> parseVEX rhlp nor0F383D vex0F383D + | 0x3euy -> parseVEX rhlp nor0F383E vex0F383E + | 0x3fuy -> parseVEX rhlp nor0F383F vex0F383F + | 0x40uy -> parseVEX rhlp nor0F3840 vex0F3840 + | 0x41uy -> parseVEX rhlp nor0F3841 vex0F3841 + | 0x43uy -> parseEVEXW rhlp notEn notEn notEn evex0F3843W1 + | 0x4Duy -> parseEVEXW rhlp notEn notEn notEn evex0F384DW1 + | 0x58uy -> parseEVEXW rhlp vex0F3858W0 notEn evex0F3858W0 notEn + | 0x59uy -> parseEVEXW rhlp vex0F3859W0 notEn notEn evex0F3859W1 + | 0x5Auy -> parseVEX rhlp nor0F385A vex0F385A + | 0x75uy -> parseEVEXW rhlp notEn notEn notEn evex0F3875W1 + | 0x76uy -> parseEVEXW rhlp notEn notEn evex0F3876W0 notEn + | 0x77uy -> parseEVEXW rhlp notEn notEn notEn evex0F3877W1 + | 0x78uy -> parseVEX rhlp nor0F3878 vex0F3878 + | 0x7Auy -> parseEVEXW rhlp notEn notEn evex0F387AW0 notEn + | 0x7Cuy -> parseEVEXW rhlp notEn notEn evex0F387CW0 evex0F387CW1 + | 0x90uy -> parseEVEXW rhlp vex0F3890W0 notEn evex0F3890W0 notEn + | 0x92uy -> parseEVEXW rhlp vex0F3892W0 notEn evex0F3892W0 notEn + | 0x93uy -> parseEVEXW rhlp notEn vex0F3893W1 notEn notEn + | 0x98uy -> parseEVEXW rhlp notEn vex0F3898W1 notEn evex0F3898W1 + | 0x99uy -> parseVEXW rhlp notEn notEn vex0F3899W0 vex0F3899W1 + | 0x9Buy -> parseEVEXW rhlp vex0F389BW0 notEn evex0F389BW0 notEn + | 0x9Cuy -> parseEVEXW rhlp notEn vex0F389CW1 notEn evex0F389CW1 + | 0x9Duy -> parseEVEXW rhlp notEn vex0F389DW1 notEn evex0F389DW1 + | 0xA8uy -> parseEVEXW rhlp vex0F38A8W0 vex0F38A8W1 evex0F38A8W0 notEn + | 0xA9uy -> parseVEXW rhlp notEn notEn vex0F38A9W0 vex0F38A9W1 + | 0xAAuy -> parseEVEXW rhlp notEn vex0F38AAW1 notEn notEn + | 0xABuy -> parseEVEXW rhlp notEn vex0F38ABW1 notEn notEn + | 0xACuy -> parseEVEXW rhlp notEn vex0F38ACW1 notEn notEn + | 0xADuy -> parseEVEXW rhlp notEn vex0F38ADW1 notEn evex0F38ADW1 + | 0xB8uy -> parseEVEXW rhlp notEn vex0F38B8W1 notEn evex0F38B8W1 + | 0xB9uy -> parseVEXW rhlp notEn notEn vex0F38B9W0 vex0F38B9W1 + | 0xBAuy -> parseEVEXW rhlp notEn vex0F38BAW1 notEn notEn + | 0xBBuy -> parseEVEXW rhlp notEn vex0F38BBW1 notEn evex0F38BBW1 + | 0xBCuy -> parseEVEXW rhlp notEn vex0F38BCW1 notEn evex0F38BCW1 + | 0xBDuy -> parseEVEXW rhlp notEn vex0F38BDW1 notEn evex0F38BDW1 + | 0xCBuy -> parseEVEXW rhlp notEn notEn notEn evex0F38CBW1 + | 0xCDuy -> parseEVEXW rhlp notEn notEn notEn evex0F38CDW1 + | 0xF0uy -> parseNonVEX rhlp nor0F38F0 + | 0xF1uy -> parseNonVEX rhlp nor0F38F1 + | 0xF2uy -> parseVEX rhlp notEn vex0F38F2 + | 0xF5uy -> parseVEXW rhlp nor0F38F5W0 nor0F38F5W1 vex0F38F5W0 vex0F38F5W1 + | 0xF6uy -> parseVEXW rhlp nor0F38F6W0 nor0F38F6W1 vex0F38F6W0 vex0F38F6W1 + | 0xF7uy -> parseVEX rhlp nor0F38F7 vex0F38F7 + | _ -> raise ParsingFailureException + + /// When the first two bytes are 0F3A. + /// Table A-5 of Volume 2 (Three-byte Opcode Map : First Two Bytes are 0F 3AH) + let parseThreeByteOp2 (rhlp: ReadHelper) = + match rhlp.ReadByte () with + | 0x08uy -> parseVEX rhlp nor0F3A08 vex0F3A08 + | 0x09uy -> parseVEX rhlp nor0F3A09 vex0F3A09 + | 0x0Buy -> parseEVEX rhlp nor0F3A0B vex0F3A0B notEn evex0F3A0BW1 + | 0x0Fuy -> parseVEX rhlp nor0F3A0F vex0F3A0F + | 0x15uy -> parseVEX rhlp nor0F3A15 vex0F3A15 + | 0x16uy -> parseVEX rhlp nor0F3A16 vex0F3A16 + | 0x18uy -> parseEVEXW rhlp vex0F3A18W0 notEn notEn notEn + | 0x19uy -> parseEVEXW rhlp vex0F3A19W0 notEn evex0F3A19W0 evex0F3A19W1 + | 0x1Auy -> parseEVEXW rhlp notEn notEn notEn evex0F3A1AW1 + | 0x1Buy -> parseEVEXW rhlp notEn notEn evex0F3A1BW0 evex0F3A1BW1 + | 0x20uy -> parseVEX rhlp nor0F3A20 vex0F3A20 + | 0x22uy -> + parseEVEXW rhlp vex0F3A22W0 vex0F3A22W1 evex0F3A22W0 evex0F3A22W1 + | 0x25uy -> parseEVEXW rhlp notEn notEn evex0F3A25W0 notEn + | 0x27uy -> parseEVEXW rhlp notEn notEn notEn evex0F3A27W1 + | 0x38uy -> parseVEX rhlp nor0F3A38 vex0F3A38 + | 0x3Auy -> parseEVEXW rhlp notEn notEn evex0F3A3AW0 evex0F3A3AW1 + | 0x3Buy -> parseEVEXW rhlp notEn notEn evex0F3A3BW0 evex0F3A3BW1 + | 0x43uy -> parseEVEXW rhlp notEn notEn evex0F3A43W0 evex0F3A43W1 + | 0x4Buy -> parseVEXW rhlp notEn notEn vex0F3A4BW0 notEn + | 0x57uy -> parseEVEXW rhlp notEn notEn notEn evex0F3A57W1 + | 0x60uy -> parseVEX rhlp nor0F3A60 vex0F3A60 + | 0x61uy -> parseVEX rhlp nor0F3A61 vex0F3A61 + | 0x62uy -> parseVEX rhlp nor0F3A62 vex0F3A62 + | 0x63uy -> parseVEX rhlp nor0F3A63 vex0F3A63 + | 0xF0uy -> parseVEX rhlp nor0F3AF0 vex0F3AF0 + | _ -> raise ParsingFailureException + + let getOpCode0F0D (rhlp: ReadHelper) = + let b = rhlp.PeekByte () + match modIsMemory b, getReg b with + | true, 0b001 -> Opcode.PREFETCHW + | true, 0b010 -> Opcode.PREFETCHWT1 + | _ -> raise ParsingFailureException + + let ignOpSz (rhlp: ReadHelper) = + rhlp.Prefixes <- rhlp.Prefixes &&& EnumOfValue 0xFDFF + rhlp + + let pTwoByteOp (rhlp: ReadHelper) byte = + match byte with + | 0x02uy -> render rhlp Opcode.LAR SzCond.Nor OD.GprRm SZ.WV + | 0x03uy -> render rhlp Opcode.LSL SzCond.Nor OD.GprRm SZ.WV + | 0x05uy -> +#if !EMULATION + ensure64 rhlp +#endif + render rhlp Opcode.SYSCALL SzCond.Nor OD.No SZ.Def + | 0x06uy -> render rhlp Opcode.CLTS SzCond.Nor OD.No SZ.Def + | 0x07uy -> +#if !EMULATION + ensure64 rhlp +#endif + render rhlp Opcode.SYSRET SzCond.Nor OD.No SZ.Def + | 0x08uy -> render rhlp Opcode.INVD SzCond.Nor OD.No SZ.Def + | 0x09uy -> render rhlp Opcode.WBINVD SzCond.Nor OD.No SZ.Def + | 0x0Buy -> render rhlp Opcode.UD2 SzCond.Nor OD.No SZ.Def + | 0x0Duy -> render rhlp (getOpCode0F0D rhlp) SzCond.Nor OD.Mem SZ.Def + | 0x10uy -> pVEXByMem rhlp nor0F10 nor0F10 vex0F10Mem vex0F10Reg + | 0x11uy -> pVEXByMem rhlp nor0F11 nor0F11 vex0F11Mem vex0F11Reg + | 0x12uy -> pVEXByMem rhlp nor0F12Mem nor0F12Reg vex0F12Mem vex0F12Reg + | 0x13uy -> parseVEX rhlp nor0F13 vex0F13 + | 0x14uy -> parseVEX rhlp nor0F14 vex0F14 + | 0x15uy -> parseVEX rhlp nor0F15 vex0F15 + | 0x16uy -> pVEXByMem rhlp nor0F16Mem nor0F16Reg vex0F16Mem vex0F16Reg + | 0x17uy -> parseVEX rhlp nor0F17 vex0F17 + | 0x1Auy -> parseBND rhlp SzCond.Nor nor0F1A + | 0x1Buy -> parseBND rhlp SzCond.Nor nor0F1B + | 0x1Euy -> + if hasREPZ rhlp.Prefixes then parseCETInstr rhlp + else raise InvalidOpcodeException + | 0x1Fuy -> render rhlp Opcode.NOP SzCond.Nor OD.Mem SZ.Def (* NOP /0 Ev *) + | 0x20uy -> render rhlp Opcode.MOV SzCond.F64 OD.RmCtrl SZ.DY + | 0x21uy -> render rhlp Opcode.MOV SzCond.Nor OD.RmDbg SZ.DY + | 0x22uy -> render rhlp Opcode.MOV SzCond.Nor OD.CtrlRm SZ.DY + | 0x23uy -> render rhlp Opcode.MOV SzCond.Nor OD.DbgRm SZ.DY + | 0x28uy -> parseVEX rhlp nor0F28 vex0F28 + | 0x29uy -> parseVEX rhlp nor0F29 vex0F29 + | 0x2Auy -> parseVEX rhlp nor0F2A vex0F2A + | 0x2Buy -> parseVEX rhlp nor0F2B vex0F2B + | 0x2Cuy -> parseVEX rhlp nor0F2C vex0F2C + | 0x2Duy -> parseVEX rhlp nor0F2D vex0F2D + | 0x2Euy -> parseVEX rhlp nor0F2E vex0F2E + | 0x2Fuy -> parseVEX rhlp nor0F2F vex0F2F + | 0x30uy -> render rhlp Opcode.WRMSR SzCond.Nor OD.No SZ.Def + | 0x31uy -> render rhlp Opcode.RDTSC SzCond.Nor OD.No SZ.Def + | 0x32uy -> render rhlp Opcode.RDMSR SzCond.Nor OD.No SZ.Def + | 0x33uy -> render rhlp Opcode.RDPMC SzCond.Nor OD.No SZ.Def + | 0x34uy -> render rhlp Opcode.SYSENTER SzCond.Nor OD.No SZ.Def + | 0x35uy -> render rhlp Opcode.SYSEXIT SzCond.Nor OD.No SZ.Def + | 0x37uy -> render rhlp Opcode.GETSEC SzCond.Nor OD.No SZ.Def + | 0x40uy -> render rhlp Opcode.CMOVO SzCond.Nor OD.GprRm SZ.Def + | 0x41uy -> render rhlp Opcode.CMOVNO SzCond.Nor OD.GprRm SZ.Def + | 0x42uy -> render rhlp Opcode.CMOVB SzCond.Nor OD.GprRm SZ.Def + | 0x43uy -> render rhlp Opcode.CMOVAE SzCond.Nor OD.GprRm SZ.Def + | 0x44uy -> render rhlp Opcode.CMOVZ SzCond.Nor OD.GprRm SZ.Def + | 0x45uy -> render rhlp Opcode.CMOVNZ SzCond.Nor OD.GprRm SZ.Def + | 0x46uy -> render rhlp Opcode.CMOVBE SzCond.Nor OD.GprRm SZ.Def + | 0x47uy -> render rhlp Opcode.CMOVA SzCond.Nor OD.GprRm SZ.Def + | 0x48uy -> render rhlp Opcode.CMOVS SzCond.Nor OD.GprRm SZ.Def + | 0x49uy -> render rhlp Opcode.CMOVNS SzCond.Nor OD.GprRm SZ.Def + | 0x4Auy -> render rhlp Opcode.CMOVP SzCond.Nor OD.GprRm SZ.Def + | 0x4Buy -> render rhlp Opcode.CMOVNP SzCond.Nor OD.GprRm SZ.Def + | 0x4Cuy -> render rhlp Opcode.CMOVL SzCond.Nor OD.GprRm SZ.Def + | 0x4Duy -> render rhlp Opcode.CMOVGE SzCond.Nor OD.GprRm SZ.Def + | 0x4Euy -> render rhlp Opcode.CMOVLE SzCond.Nor OD.GprRm SZ.Def + | 0x4Fuy -> render rhlp Opcode.CMOVG SzCond.Nor OD.GprRm SZ.Def + | 0x50uy -> parseVEX rhlp nor0F50 vex0F50 + | 0x51uy -> parseVEX rhlp nor0F51 vex0F51 + | 0x52uy -> parseVEX rhlp nor0F52 vex0F52 + | 0x53uy -> parseVEX rhlp nor0F53 vex0F53 + | 0x54uy -> parseVEX rhlp nor0F54 vex0F54 + | 0x55uy -> parseVEX rhlp nor0F55 vex0F55 + | 0x56uy -> parseVEX rhlp nor0F56 vex0F56 + | 0x57uy -> parseVEX rhlp nor0F57 vex0F57 + | 0x58uy -> parseVEX rhlp nor0F58 vex0F58 + | 0x59uy -> parseVEX rhlp nor0F59 vex0F59 + | 0x5Auy -> parseEVEX rhlp nor0F5A vex0F5A evex0F5AW0 evex0F5AW1 + | 0x5Buy -> parseVEX rhlp nor0F5B vex0F5B + | 0x5Cuy -> parseVEX rhlp nor0F5C vex0F5C + | 0x5Duy -> parseEVEX rhlp nor0F5D vex0F5D evex0F5DW0 notEn + | 0x5Euy -> parseVEX rhlp nor0F5E vex0F5E + | 0x5Fuy -> parseEVEX rhlp nor0F5F vex0F5F evex0F5FW0 evex0F5FW1 + | 0x60uy -> parseVEX rhlp nor0F60 vex0F60 + | 0x61uy -> parseVEX rhlp nor0F61 vex0F61 + | 0x62uy -> parseVEX rhlp nor0F62 vex0F62 + | 0x63uy -> parseVEX rhlp nor0F63 vex0F63 + | 0x64uy -> parseVEX rhlp nor0F64 vex0F64 + | 0x65uy -> parseVEX rhlp nor0F65 vex0F65 + | 0x66uy -> parseVEX rhlp nor0F66 vex0F66 + | 0x67uy -> parseVEX rhlp nor0F67 vex0F67 + | 0x68uy -> parseVEX rhlp nor0F68 vex0F68 + | 0x69uy -> parseVEX rhlp nor0F69 vex0F69 + | 0x6Auy -> parseVEX rhlp nor0F6A vex0F6A + | 0x6Buy -> parseVEX rhlp nor0F6B vex0F6B + | 0x6Cuy -> parseVEX rhlp nor0F6C vex0F6C + | 0x6Duy -> parseVEX rhlp nor0F6D vex0F6D + | 0x6Euy -> parseVEXW rhlp nor0F6EW0 nor0F6EW1 vex0F6EW0 vex0F6EW1 + | 0x6Fuy -> parseEVEX rhlp nor0F6F vex0F6F evex0F6FW0 evex0F6FW1 + | 0x70uy -> parseVEX rhlp nor0F70 vex0F70 + | 0x74uy -> parseVEX rhlp nor0F74 vex0F74 + | 0x75uy -> parseVEX rhlp nor0F75 vex0F75 + | 0x76uy -> parseVEX rhlp nor0F76 vex0F76 + | 0x77uy -> parseVEX rhlp nor0F77 vex0F77 + | 0x7Euy -> parseVEXW rhlp nor0F7EW0 nor0F7EW1 vex0F7EW0 vex0F7EW1 + | 0x7Fuy -> parseEVEX rhlp nor0F7F vex0F7F evex0F7FW0 evex0F7FW1 + | 0x80uy -> addBND rhlp; render rhlp Opcode.JO SzCond.F64 OD.Rel SZ.D64 + | 0x81uy -> addBND rhlp; render rhlp Opcode.JNO SzCond.F64 OD.Rel SZ.D64 + | 0x82uy -> addBND rhlp; render rhlp Opcode.JB SzCond.F64 OD.Rel SZ.D64 + | 0x83uy -> addBND rhlp; render rhlp Opcode.JNB SzCond.F64 OD.Rel SZ.D64 + | 0x84uy -> addBND rhlp; render rhlp Opcode.JZ SzCond.F64 OD.Rel SZ.D64 + | 0x85uy -> addBND rhlp; render rhlp Opcode.JNZ SzCond.F64 OD.Rel SZ.D64 + | 0x86uy -> addBND rhlp; render rhlp Opcode.JBE SzCond.F64 OD.Rel SZ.D64 + | 0x87uy -> addBND rhlp; render rhlp Opcode.JA SzCond.F64 OD.Rel SZ.D64 + | 0x88uy -> addBND rhlp; render rhlp Opcode.JS SzCond.F64 OD.Rel SZ.D64 + | 0x89uy -> addBND rhlp; render rhlp Opcode.JNS SzCond.F64 OD.Rel SZ.D64 + | 0x8Auy -> addBND rhlp; render rhlp Opcode.JP SzCond.F64 OD.Rel SZ.D64 + | 0x8Buy -> addBND rhlp; render rhlp Opcode.JNP SzCond.F64 OD.Rel SZ.D64 + | 0x8Cuy -> addBND rhlp; render rhlp Opcode.JL SzCond.F64 OD.Rel SZ.D64 + | 0x8Duy -> addBND rhlp; render rhlp Opcode.JNL SzCond.F64 OD.Rel SZ.D64 + | 0x8Euy -> addBND rhlp; render rhlp Opcode.JLE SzCond.F64 OD.Rel SZ.D64 + | 0x8Fuy -> addBND rhlp; render rhlp Opcode.JG SzCond.F64 OD.Rel SZ.D64 + | 0x90uy -> render rhlp Opcode.SETO SzCond.Nor OD.Mem SZ.Byte + | 0x91uy -> render rhlp Opcode.SETNO SzCond.Nor OD.Mem SZ.Byte + | 0x92uy -> render rhlp Opcode.SETB SzCond.Nor OD.Mem SZ.Byte + | 0x93uy -> render rhlp Opcode.SETNB SzCond.Nor OD.Mem SZ.Byte + | 0x94uy -> render rhlp Opcode.SETZ SzCond.Nor OD.Mem SZ.Byte + | 0x95uy -> render rhlp Opcode.SETNZ SzCond.Nor OD.Mem SZ.Byte + | 0x96uy -> render rhlp Opcode.SETBE SzCond.Nor OD.Mem SZ.Byte + | 0x97uy -> render rhlp Opcode.SETA SzCond.Nor OD.Mem SZ.Byte + | 0x98uy -> render rhlp Opcode.SETS SzCond.Nor OD.Mem SZ.Byte + | 0x99uy -> render rhlp Opcode.SETNS SzCond.Nor OD.Mem SZ.Byte + | 0x9Auy -> render rhlp Opcode.SETP SzCond.Nor OD.Mem SZ.Byte + | 0x9Buy -> render rhlp Opcode.SETNP SzCond.Nor OD.Mem SZ.Byte + | 0x9Cuy -> render rhlp Opcode.SETL SzCond.Nor OD.Mem SZ.Byte + | 0x9Duy -> render rhlp Opcode.SETNL SzCond.Nor OD.Mem SZ.Byte + | 0x9Euy -> render rhlp Opcode.SETLE SzCond.Nor OD.Mem SZ.Byte + | 0x9Fuy -> render rhlp Opcode.SETG SzCond.Nor OD.Mem SZ.Byte + | 0xA0uy -> render rhlp Opcode.PUSH SzCond.D64 OD.Fs SZ.RegW + | 0xA1uy -> render rhlp Opcode.POP SzCond.D64 OD.Fs SZ.RegW + | 0xA2uy -> render rhlp Opcode.CPUID SzCond.Nor OD.No SZ.Def + | 0xA3uy -> render rhlp Opcode.BT SzCond.Nor OD.RmGpr SZ.Def + | 0xA4uy -> render rhlp Opcode.SHLD SzCond.Nor OD.XmRegImm8 SZ.Def + | 0xA5uy -> render rhlp Opcode.SHLD SzCond.Nor OD.RmGprCL SZ.Def + | 0xA8uy -> render rhlp Opcode.PUSH SzCond.D64 OD.Gs SZ.RegW + | 0xA9uy -> render rhlp Opcode.POP SzCond.D64 OD.Gs SZ.RegW + | 0xAAuy -> render rhlp Opcode.RSM SzCond.Nor OD.No SZ.Def + | 0xABuy -> render rhlp Opcode.BTS SzCond.Nor OD.RmGpr SZ.Def + | 0xACuy -> render rhlp Opcode.SHRD SzCond.Nor OD.XmRegImm8 SZ.Def + | 0xADuy -> render rhlp Opcode.SHRD SzCond.Nor OD.RmGprCL SZ.Def + | 0xAFuy -> render rhlp Opcode.IMUL SzCond.Nor OD.GprRm SZ.Def + | 0xB0uy -> render rhlp Opcode.CMPXCHG SzCond.Nor OD.RmGpr SZ.Byte + | 0xB1uy -> render rhlp Opcode.CMPXCHG SzCond.Nor OD.RmGpr SZ.Def + | 0xB2uy -> render rhlp Opcode.LSS SzCond.Nor OD.GprM SZ.PRM + | 0xB3uy -> render rhlp Opcode.BTR SzCond.Nor OD.RmGpr SZ.Def + | 0xB4uy -> render rhlp Opcode.LFS SzCond.Nor OD.GprM SZ.PRM + | 0xB5uy -> render rhlp Opcode.LGS SzCond.Nor OD.GprM SZ.PRM + | 0xB6uy -> render rhlp Opcode.MOVZX SzCond.Nor OD.GprRm SZ.BV + | 0xB7uy -> render rhlp Opcode.MOVZX SzCond.Nor OD.GprRm SZ.WV + | 0xB8uy when not <| hasREPZ rhlp.Prefixes -> raise ParsingFailureException + | 0xB8uy -> + rhlp.Prefixes <- filterPrefs rhlp.Prefixes + render rhlp Opcode.POPCNT SzCond.Nor OD.GprRm SZ.Def + | 0xBBuy when hasREPZ rhlp.Prefixes -> raise ParsingFailureException + | 0xBBuy -> render rhlp Opcode.BTC SzCond.Nor OD.RmGpr SZ.Def + | 0xBCuy when hasREPZ rhlp.Prefixes -> + rhlp.Prefixes <- filterPrefs rhlp.Prefixes + render rhlp Opcode.TZCNT SzCond.Nor OD.GprRm SZ.Def + | 0xBCuy -> render rhlp Opcode.BSF SzCond.Nor OD.GprRm SZ.Def + | 0xBDuy when hasREPZ rhlp.Prefixes -> + rhlp.Prefixes <- filterPrefs rhlp.Prefixes + render rhlp Opcode.LZCNT SzCond.Nor OD.GprRm SZ.Def + | 0xBDuy -> render rhlp Opcode.BSR SzCond.Nor OD.GprRm SZ.Def + | 0xBEuy -> render rhlp Opcode.MOVSX SzCond.Nor OD.GprRm SZ.BV + | 0xBFuy -> render rhlp Opcode.MOVSX SzCond.Nor OD.GprRm SZ.WV + | 0xC0uy -> render rhlp Opcode.XADD SzCond.Nor OD.RmGpr SZ.Byte + | 0xC1uy -> render rhlp Opcode.XADD SzCond.Nor OD.RmGpr SZ.Def + | 0xC2uy -> parseEVEX rhlp nor0FC2 vex0FC2 evex0FC2W0 evex0FC2W1 + | 0xC3uy -> render rhlp Opcode.MOVNTI SzCond.Nor OD.RmGpr SZ.Def + | 0xC4uy -> parseVEX rhlp nor0FC4 vex0FC4 + | 0xC5uy -> parseVEX rhlp nor0FC5 vex0FC5 + | 0xC6uy -> parseVEX rhlp nor0FC6 vex0FC6 + | 0xC8uy -> render (ignOpSz rhlp) Opcode.BSWAP SzCond.Nor OD.Rax SZ.Def + | 0xC9uy -> render (ignOpSz rhlp) Opcode.BSWAP SzCond.Nor OD.Rcx SZ.Def + | 0xCAuy -> render (ignOpSz rhlp) Opcode.BSWAP SzCond.Nor OD.Rdx SZ.Def + | 0xCBuy -> render (ignOpSz rhlp) Opcode.BSWAP SzCond.Nor OD.Rbx SZ.Def + | 0xCCuy -> render (ignOpSz rhlp) Opcode.BSWAP SzCond.Nor OD.Rsp SZ.Def + | 0xCDuy -> render (ignOpSz rhlp) Opcode.BSWAP SzCond.Nor OD.Rbp SZ.Def + | 0xCEuy -> render (ignOpSz rhlp) Opcode.BSWAP SzCond.Nor OD.Rsi SZ.Def + | 0xCFuy -> render (ignOpSz rhlp) Opcode.BSWAP SzCond.Nor OD.Rdi SZ.Def + | 0xD1uy -> parseVEX rhlp nor0FD1 vex0FD1 + | 0xD2uy -> parseVEX rhlp nor0FD2 vex0FD2 + | 0xD3uy -> parseVEX rhlp nor0FD3 vex0FD3 + | 0xD4uy -> parseVEX rhlp nor0FD4 vex0FD4 + | 0xD5uy -> parseVEX rhlp nor0FD5 vex0FD5 + | 0xD6uy -> +#if !EMULATION + ensureVEX128 rhlp +#endif + parseVEX rhlp nor0FD6 vex0FD6 + | 0xD7uy -> parseVEX rhlp nor0FD7 vex0FD7 + | 0xD8uy -> parseVEX rhlp nor0FD8 vex0FD8 + | 0xD9uy -> parseVEX rhlp nor0FD9 vex0FD9 + | 0xDAuy -> parseVEX rhlp nor0FDA vex0FDA + | 0xDBuy -> parseVEX rhlp nor0FDB vex0FDB + | 0xDCuy -> parseVEX rhlp nor0FDC vex0FDC + | 0xDDuy -> parseVEX rhlp nor0FDD vex0FDD + | 0xDEuy -> parseVEX rhlp nor0FDE vex0FDE + | 0xDFuy -> parseVEX rhlp nor0FDF vex0FDF + | 0xE0uy -> parseVEX rhlp nor0FE0 vex0FE0 + | 0xE1uy -> parseVEX rhlp nor0FE1 vex0FE1 + | 0xE2uy -> parseVEX rhlp nor0FE2 vex0FE2 + | 0xE3uy -> parseVEX rhlp nor0FE3 vex0FE3 + | 0xE4uy -> parseVEX rhlp nor0FE4 vex0FE4 + | 0xE5uy -> parseVEX rhlp nor0FE5 vex0FE5 + | 0xE6uy -> parseEVEX rhlp nor0FE6 vex0FE6 evex0FE6W0 notEn + | 0xE7uy -> parseEVEX rhlp nor0FE7 vex0FE7 evex0FE7W0 evex0FE7W1 + | 0xE8uy -> parseVEX rhlp nor0FE8 vex0FE8 + | 0xE9uy -> parseVEX rhlp nor0FE9 vex0FE9 + | 0xEAuy -> parseVEX rhlp nor0FEA vex0FEA + | 0xEBuy -> parseVEX rhlp nor0FEB vex0FEB + | 0xECuy -> parseVEX rhlp nor0FEC vex0FEC + | 0xEDuy -> parseVEX rhlp nor0FED vex0FED + | 0xEEuy -> parseVEX rhlp nor0FEE vex0FEE + | 0xEFuy -> parseEVEX rhlp nor0FEF vex0FEF evex0FEFW0 evex0FEFW1 + | 0xEFuy -> parseVEX rhlp nor0FEF vex0FEF + | 0xF0uy -> parseVEX rhlp nor0FF0 vex0FF0 + | 0xF1uy -> parseVEX rhlp nor0FF1 vex0FF1 + | 0xF2uy -> parseVEX rhlp nor0FF2 vex0FF2 + | 0xF3uy -> parseVEX rhlp nor0FF3 vex0FF3 + | 0xF4uy -> parseVEX rhlp nor0FF4 vex0FF4 + | 0xF5uy -> parseVEX rhlp nor0FF5 vex0FF5 + | 0xF6uy -> parseVEX rhlp nor0FF6 vex0FF6 + | 0xF8uy -> parseVEX rhlp nor0FF8 vex0FF8 + | 0xF9uy -> parseVEX rhlp nor0FF9 vex0FF9 + | 0xFAuy -> parseVEX rhlp nor0FFA vex0FFA + | 0xFBuy -> parseVEX rhlp nor0FFB vex0FFB + | 0xFCuy -> parseVEX rhlp nor0FFC vex0FFC + | 0xFDuy -> parseVEX rhlp nor0FFD vex0FFD + | 0xFEuy -> parseVEX rhlp nor0FFE vex0FFE + | 0x00uy -> parseGrpOp rhlp OpGroup.G6 OD.No SZ.Def + | 0x01uy -> parseGrpOp rhlp OpGroup.G7 OD.No SZ.Def + | 0xBAuy -> parseGrpOp rhlp OpGroup.G8 OD.RmImm8 SZ.Def + | 0xC7uy -> parseGrpOp rhlp OpGroup.G9 OD.No SZ.Def + | 0x71uy -> parseGrpOp rhlp OpGroup.G12 OD.No SZ.Def + | 0x72uy -> parseGrpOp rhlp OpGroup.G13 OD.No SZ.Def + | 0x73uy -> parseGrpOp rhlp OpGroup.G14 OD.No SZ.Def + | 0xAEuy -> parseGrpOp rhlp OpGroup.G15 OD.No SZ.Def + | 0x18uy -> parseGrpOp rhlp OpGroup.G16 OD.Mem SZ.Def + | 0x38uy -> parseThreeByteOp1 rhlp + | 0x3Auy -> parseThreeByteOp2 rhlp + | _ -> raise ParsingFailureException + + (* Table A-3 of Volume 2 (Two-byte Opcode Map) *) + let parseTwoByteOpcode (rhlp: ReadHelper) = + rhlp.ReadByte () |> pTwoByteOp rhlp + +end diff --git a/src/FrontEnd/BinLifter/Intel/IntelParsingJob.fs b/src/FrontEnd/BinLifter/Intel/IntelParsingJob.fs new file mode 100644 index 00000000..e1ee9112 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelParsingJob.fs @@ -0,0 +1,2074 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.Intel + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.FrontEnd.BinLifter.Intel.Helper +open B2R2.FrontEnd.BinLifter.Intel.ParsingHelper +open LanguagePrimitives + +[] +type internal ParsingJob () = + abstract Run: ReadHelper -> IntelInstruction + +type internal OneOp00 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.ADD oprs + +type internal OneOp01 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.ADD oprs + +type internal OneOp02 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.ADD oprs + +type internal OneOp03 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.ADD oprs + +type internal OneOp04 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm8].Render rhlp + newInsInfo rhlp Opcode.ADD oprs + +type internal OneOp05 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm].Render rhlp + newInsInfo rhlp Opcode.ADD oprs + +type internal OneOp06 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.RegW].Render rhlp SzCond.Nor + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Es].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp07 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.RegW].Render rhlp SzCond.Nor + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Es].Render rhlp + newInsInfo rhlp Opcode.POP oprs + +type internal OneOp08 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.OR oprs + +type internal OneOp09 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.OR oprs + +type internal OneOp0A () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.OR oprs + +type internal OneOp0B () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.OR oprs + +type internal OneOp0C () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm8].Render rhlp + newInsInfo rhlp Opcode.OR oprs + +type internal OneOp0D () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm].Render rhlp + newInsInfo rhlp Opcode.OR oprs + +type internal OneOp0E () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.RegW].Render rhlp SzCond.Nor + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Cs].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp0F () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.ReadByte () |> pTwoByteOp rhlp + +type internal OneOp10 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.ADC oprs + +type internal OneOp11 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.ADC oprs + +type internal OneOp12 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.ADC oprs + +type internal OneOp13 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.ADC oprs + +type internal OneOp14 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm8].Render rhlp + newInsInfo rhlp Opcode.ADC oprs + +type internal OneOp15 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm].Render rhlp + newInsInfo rhlp Opcode.ADC oprs + +type internal OneOp16 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.RegW].Render rhlp SzCond.Nor + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Ss].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp17 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.RegW].Render rhlp SzCond.Nor + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Ss].Render rhlp + newInsInfo rhlp Opcode.POP oprs + +type internal OneOp18 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.SBB oprs + +type internal OneOp19 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.SBB oprs + +type internal OneOp1A () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.SBB oprs + +type internal OneOp1B () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.SBB oprs + +type internal OneOp1C () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm8].Render rhlp + newInsInfo rhlp Opcode.SBB oprs + +type internal OneOp1D () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm].Render rhlp + newInsInfo rhlp Opcode.SBB oprs + +type internal OneOp1E () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.RegW].Render rhlp SzCond.Nor + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Ds].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp1F () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.RegW].Render rhlp SzCond.Nor + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Ds].Render rhlp + newInsInfo rhlp Opcode.POP oprs + +type internal OneOp20 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.AND oprs + +type internal OneOp21 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.AND oprs + +type internal OneOp22 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.AND oprs + +type internal OneOp23 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.AND oprs + +type internal OneOp24 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm8].Render rhlp + newInsInfo rhlp Opcode.AND oprs + +type internal OneOp25 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm].Render rhlp + newInsInfo rhlp Opcode.AND oprs + +type internal OneOp26 () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOp27 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.DAA oprs + +type internal OneOp28 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.SUB oprs + +type internal OneOp29 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.SUB oprs + +type internal OneOp2A () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.SUB oprs + +type internal OneOp2B () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.SUB oprs + +type internal OneOp2C () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm8].Render rhlp + newInsInfo rhlp Opcode.SUB oprs + +type internal OneOp2D () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm].Render rhlp + newInsInfo rhlp Opcode.SUB oprs + +type internal OneOp2E () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOp2F () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.DAS oprs + +type internal OneOp30 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.XOR oprs + +type internal OneOp31 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.XOR oprs + +type internal OneOp32 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.XOR oprs + +type internal OneOp33 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.XOR oprs + +type internal OneOp34 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm8].Render rhlp + newInsInfo rhlp Opcode.XOR oprs + +type internal OneOp35 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm].Render rhlp + newInsInfo rhlp Opcode.XOR oprs + +type internal OneOp36 () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOp37 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.AAA oprs + +type internal OneOp38 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.CMP oprs + +type internal OneOp39 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.CMP oprs + +type internal OneOp3A () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.CMP oprs + +type internal OneOp3B () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.CMP oprs + +type internal OneOp3C () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm8].Render rhlp + newInsInfo rhlp Opcode.CMP oprs + +type internal OneOp3D () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm].Render rhlp + newInsInfo rhlp Opcode.CMP oprs + +type internal OneOp3E () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOp3F () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.AAS oprs + +type internal OneOp40 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Eax].Render rhlp + newInsInfo rhlp Opcode.INC oprs + +type internal OneOp41 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Ecx].Render rhlp + newInsInfo rhlp Opcode.INC oprs + +type internal OneOp42 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Edx].Render rhlp + newInsInfo rhlp Opcode.INC oprs + +type internal OneOp43 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Ebx].Render rhlp + newInsInfo rhlp Opcode.INC oprs + +type internal OneOp44 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Esp].Render rhlp + newInsInfo rhlp Opcode.INC oprs + +type internal OneOp45 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Ebp].Render rhlp + newInsInfo rhlp Opcode.INC oprs + +type internal OneOp46 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Esi].Render rhlp + newInsInfo rhlp Opcode.INC oprs + +type internal OneOp47 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Edi].Render rhlp + newInsInfo rhlp Opcode.INC oprs + +type internal OneOp48 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Eax].Render rhlp + newInsInfo rhlp Opcode.DEC oprs + +type internal OneOp49 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Ecx].Render rhlp + newInsInfo rhlp Opcode.DEC oprs + +type internal OneOp4A () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Edx].Render rhlp + newInsInfo rhlp Opcode.DEC oprs + +type internal OneOp4B () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Ebx].Render rhlp + newInsInfo rhlp Opcode.DEC oprs + +type internal OneOp4C () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Esp].Render rhlp + newInsInfo rhlp Opcode.DEC oprs + +type internal OneOp4D () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Ebp].Render rhlp + newInsInfo rhlp Opcode.DEC oprs + +type internal OneOp4E () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Esi].Render rhlp + newInsInfo rhlp Opcode.DEC oprs + +type internal OneOp4F () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Edi].Render rhlp + newInsInfo rhlp Opcode.DEC oprs + +type internal OneOp50 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rax].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp51 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rcx].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp52 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rdx].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp53 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rbx].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp54 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rsp].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp55 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rbp].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp56 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rsi].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp57 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rdi].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp58 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rax].Render rhlp + newInsInfo rhlp Opcode.POP oprs + +type internal OneOp59 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rcx].Render rhlp + newInsInfo rhlp Opcode.POP oprs + +type internal OneOp5A () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rdx].Render rhlp + newInsInfo rhlp Opcode.POP oprs + +type internal OneOp5B () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rbx].Render rhlp + newInsInfo rhlp Opcode.POP oprs + +type internal OneOp5C () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rsp].Render rhlp + newInsInfo rhlp Opcode.POP oprs + +type internal OneOp5D () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rbp].Render rhlp + newInsInfo rhlp Opcode.POP oprs + +type internal OneOp5E () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rsi].Render rhlp + newInsInfo rhlp Opcode.POP oprs + +type internal OneOp5F () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Rdi].Render rhlp + newInsInfo rhlp Opcode.POP oprs + +type internal OneOp60 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + if hasOprSz rhlp.Prefixes then + render rhlp Opcode.PUSHA SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.PUSHAD SzCond.Nor OD.No SZ.Def + +type internal OneOp61 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + if hasOprSz rhlp.Prefixes then + render rhlp Opcode.POPA SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.POPAD SzCond.Nor OD.No SZ.Def + +type internal OneOp62 () = + inherit ParsingJob () + override __.Run rhlp = + if (rhlp.WordSize = WordSize.Bit64) || (rhlp.PeekByte () >= 0xC0uy) then + let mutable rex = rhlp.REXPrefix + let vInfo = getEVEXInfo rhlp.BinReader &rex rhlp.CurrPos + rhlp.VEXInfo <- Some vInfo + rhlp.REXPrefix <- rex + rhlp.CurrPos <- rhlp.CurrPos + 3 + match vInfo.VEXType &&& EnumOfValue 7 with + | VEXType.VEXTwoByteOp -> parseTwoByteOpcode rhlp + | VEXType.VEXThreeByteOpOne -> parseThreeByteOp1 rhlp + | VEXType.VEXThreeByteOpTwo -> parseThreeByteOp2 rhlp + | _ -> raise ParsingFailureException + else + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprM].Render rhlp + newInsInfo rhlp Opcode.BOUND oprs + +type internal OneOp63 () = + inherit ParsingJob () + override __.Run rhlp = + if is64bit rhlp then + if not (hasREXW rhlp.REXPrefix) then raise ParsingFailureException + else render rhlp Opcode.MOVSXD SzCond.Nor OD.GprRm SZ.DV + else render rhlp Opcode.ARPL SzCond.Nor OD.RmGpr SZ.Word + +type internal OneOp64 () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOp65 () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOp66 () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOp67 () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOp68 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.Imm].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp69 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRmImm].Render rhlp + newInsInfo rhlp Opcode.IMUL oprs + +type internal OneOp6A () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.D64 + rhlp.OperationSize <- rhlp.MemEffOprSize + let oprs = rhlp.OprParsers.[int OD.SImm8].Render rhlp + newInsInfo rhlp Opcode.PUSH oprs + +type internal OneOp6B () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRmImm8].Render rhlp + newInsInfo rhlp Opcode.IMUL oprs + +type internal OneOp6C () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + rhlp.OperationSize <- 8 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.INSB oprs + +type internal OneOp6D () = + inherit ParsingJob () + override __.Run rhlp = + if hasOprSz rhlp.Prefixes then + render rhlp Opcode.INSW SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.INSD SzCond.Nor OD.No SZ.Def + +type internal OneOp6E () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + rhlp.OperationSize <- 8 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.OUTSB oprs + +type internal OneOp6F () = + inherit ParsingJob () + override __.Run rhlp = + if hasOprSz rhlp.Prefixes then + render rhlp Opcode.OUTSW SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.OUTSD SzCond.Nor OD.No SZ.Def + +type internal OneOp70 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JO oprs + +type internal OneOp71 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JNO oprs + +type internal OneOp72 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JB oprs + +type internal OneOp73 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JNB oprs + +type internal OneOp74 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JZ oprs + +type internal OneOp75 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JNZ oprs + +type internal OneOp76 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JBE oprs + +type internal OneOp77 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JA oprs + +type internal OneOp78 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JS oprs + +type internal OneOp79 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JNS oprs + +type internal OneOp7A () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JP oprs + +type internal OneOp7B () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JNP oprs + +type internal OneOp7C () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JL oprs + +type internal OneOp7D () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JNL oprs + +type internal OneOp7E () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JLE oprs + +type internal OneOp7F () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JG oprs + +type internal OneOp80 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.RmImm8 SZ.Byte OpGroup.G1 + render rhlp op szCond oidx szidx + +type internal OneOp81 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.RmImm SZ.Def OpGroup.G1 + render rhlp op szCond oidx szidx + +type internal OneOp82 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.RmImm8 SZ.Byte OpGroup.G1Inv64 + render rhlp op szCond oidx szidx + +type internal OneOp83 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.RmImm8 SZ.Def OpGroup.G1 + render rhlp op szCond oidx szidx + +type internal OneOp84 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.TEST oprs + +type internal OneOp85 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.TEST oprs + +type internal OneOp86 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.XCHG oprs + +type internal OneOp87 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.XCHG oprs + +type internal OneOp88 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOp89 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmGpr].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOp8A () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOp8B () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprRm].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOp8C () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Word].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RmSeg].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOp8D () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprM].Render rhlp + newInsInfo rhlp Opcode.LEA oprs + +type internal OneOp8E () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Word].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.SegRm].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOp8F () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.Mem SZ.Def OpGroup.G1A + render rhlp op szCond oidx szidx + +type internal OneOp90 () = + inherit ParsingJob () + override __.Run rhlp = + if hasNoPref rhlp && hasNoREX rhlp then + render rhlp Opcode.NOP SzCond.Nor OD.No SZ.Def + elif hasREPZ rhlp.Prefixes then + render rhlp Opcode.PAUSE SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.XCHG SzCond.Nor OD.RaxRax SZ.Def + +type internal OneOp91 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RaxRcx].Render rhlp + newInsInfo rhlp Opcode.XCHG oprs + +type internal OneOp92 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RaxRdx].Render rhlp + newInsInfo rhlp Opcode.XCHG oprs + +type internal OneOp93 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RaxRbx].Render rhlp + newInsInfo rhlp Opcode.XCHG oprs + +type internal OneOp94 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RaxRsp].Render rhlp + newInsInfo rhlp Opcode.XCHG oprs + +type internal OneOp95 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RaxRbp].Render rhlp + newInsInfo rhlp Opcode.XCHG oprs + +type internal OneOp96 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RaxRsi].Render rhlp + newInsInfo rhlp Opcode.XCHG oprs + +type internal OneOp97 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RaxRdi].Render rhlp + newInsInfo rhlp Opcode.XCHG oprs + +type internal OneOp98 () = + inherit ParsingJob () + override __.Run rhlp = + if hasOprSz rhlp.Prefixes then + render rhlp Opcode.CBW SzCond.Nor OD.No SZ.Def + elif hasREXW rhlp.REXPrefix then + render rhlp Opcode.CDQE SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.CWDE SzCond.Nor OD.No SZ.Def + +type internal OneOp99 () = + inherit ParsingJob () + override __.Run rhlp = + if hasOprSz rhlp.Prefixes then + render rhlp Opcode.CWD SzCond.Nor OD.No SZ.Def + elif hasREXW rhlp.REXPrefix then + render rhlp Opcode.CQO SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.CDQ SzCond.Nor OD.No SZ.Def + +type internal OneOp9A () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + addBND rhlp + rhlp.SzComputers.[int SZ.P].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Dir].Render rhlp + newInsInfo rhlp Opcode.CALLFar oprs + +type internal OneOp9B () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.WAIT oprs + +type internal OneOp9C () = + inherit ParsingJob () + override __.Run rhlp = + if hasOprSz rhlp.Prefixes then + let szcond = if is64bit rhlp then SzCond.D64 else SzCond.Nor + render rhlp Opcode.PUSHF szcond OD.No SZ.Def + elif is64bit rhlp then render rhlp Opcode.PUSHFQ SzCond.D64 OD.No SZ.Def + else render rhlp Opcode.PUSHFD SzCond.Nor OD.No SZ.Def + +type internal OneOp9D () = + inherit ParsingJob () + override __.Run rhlp = + if hasOprSz rhlp.Prefixes then + let szcond = if is64bit rhlp then SzCond.D64 else SzCond.Nor + render rhlp Opcode.POPF szcond OD.No SZ.Def + elif is64bit rhlp then render rhlp Opcode.POPFQ SzCond.D64 OD.No SZ.Def + else render rhlp Opcode.POPFD SzCond.Nor OD.No SZ.Def + +type internal OneOp9E () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.SAHF oprs + +type internal OneOp9F () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.LAHF oprs + +type internal OneOpA0 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RaxFar].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpA1 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RaxFar].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpA2 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.FarRax].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpA3 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.FarRax].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpA4 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + rhlp.OperationSize <- 8 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.MOVSB oprs + +type internal OneOpA5 () = + inherit ParsingJob () + override __.Run rhlp = + if hasOprSz rhlp.Prefixes then + render rhlp Opcode.MOVSW SzCond.Nor OD.No SZ.Def + elif hasREXW rhlp.REXPrefix then + render rhlp Opcode.MOVSQ SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.MOVSD SzCond.Nor OD.No SZ.Def + +type internal OneOpA6 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.CMPSB oprs + +type internal OneOpA7 () = + inherit ParsingJob () + override __.Run rhlp = + if hasOprSz rhlp.Prefixes then + render rhlp Opcode.CMPSW SzCond.Nor OD.No SZ.Def + elif hasREXW rhlp.REXPrefix then + render rhlp Opcode.CMPSQ SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.CMPSD SzCond.Nor OD.No SZ.Def + +type internal OneOpA8 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm8].Render rhlp + newInsInfo rhlp Opcode.TEST oprs + +type internal OneOpA9 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm].Render rhlp + newInsInfo rhlp Opcode.TEST oprs + +type internal OneOpAA () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + rhlp.OperationSize <- 8 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.STOSB oprs + +type internal OneOpAB () = + inherit ParsingJob () + override __.Run rhlp = + if hasOprSz rhlp.Prefixes then + render rhlp Opcode.STOSW SzCond.Nor OD.No SZ.Def + elif hasREXW rhlp.REXPrefix then + render rhlp Opcode.STOSQ SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.STOSD SzCond.Nor OD.No SZ.Def + +type internal OneOpAC () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + rhlp.OperationSize <- 8 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.LODSB oprs + +type internal OneOpAD () = + inherit ParsingJob () + override __.Run rhlp = + if hasOprSz rhlp.Prefixes then + render rhlp Opcode.LODSW SzCond.Nor OD.No SZ.Def + elif hasREXW rhlp.REXPrefix then + render rhlp Opcode.LODSQ SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.LODSD SzCond.Nor OD.No SZ.Def + +type internal OneOpAE () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + rhlp.OperationSize <- 8 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.SCASB oprs + +type internal OneOpAF () = + inherit ParsingJob () + override __.Run rhlp = + if hasOprSz rhlp.Prefixes then + render rhlp Opcode.SCASW SzCond.Nor OD.No SZ.Def + elif hasREXW rhlp.REXPrefix then + render rhlp Opcode.SCASQ SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.SCASD SzCond.Nor OD.No SZ.Def + +type internal OneOpB0 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.ALImm8].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpB1 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.CLImm8].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpB2 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.DLImm8].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpB3 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.BLImm8].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpB4 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.AhImm8].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpB5 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.ChImm8].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpB6 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.DhImm8].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpB7 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.BhImm8].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpB8 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RaxImm].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpB9 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RcxImm].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpBA () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RdxImm].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpBB () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RbxImm].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpBC () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RspImm].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpBD () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RbpImm].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpBE () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RsiImm].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpBF () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RdiImm].Render rhlp + newInsInfo rhlp Opcode.MOV oprs + +type internal OneOpC0 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.RmImm8 SZ.Byte OpGroup.G2 + render rhlp op szCond oidx szidx + +type internal OneOpC1 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.RmImm8 SZ.Def OpGroup.G2 + render rhlp op szCond oidx szidx + +type internal OneOpC2 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Imm16].Render rhlp + newInsInfo rhlp Opcode.RETNearImm oprs + +type internal OneOpC3 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.RETNear oprs + +type internal OneOpC4 () = + inherit ParsingJob () + override __.Run rhlp = + if (rhlp.WordSize = WordSize.Bit64) || (rhlp.PeekByte () >= 0xC0uy) then + let mutable rex = rhlp.REXPrefix + let vInfo = getThreeVEXInfo rhlp.BinReader &rex rhlp.CurrPos + rhlp.VEXInfo <- Some vInfo + rhlp.REXPrefix <- rex + rhlp.CurrPos <- rhlp.CurrPos + 2 + match vInfo.VEXType with + | VEXType.VEXTwoByteOp -> parseTwoByteOpcode rhlp + | VEXType.VEXThreeByteOpOne -> parseThreeByteOp1 rhlp + | VEXType.VEXThreeByteOpTwo -> parseThreeByteOp2 rhlp + | _ -> raise ParsingFailureException + else + rhlp.SzComputers.[int SZ.PZ].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprM].Render rhlp + newInsInfo rhlp Opcode.LES oprs + +type internal OneOpC5 () = + inherit ParsingJob () + override __.Run rhlp = + if (rhlp.WordSize = WordSize.Bit64) || (rhlp.PeekByte () >= 0xC0uy) then + let mutable rex = rhlp.REXPrefix + rhlp.VEXInfo <- Some <| getTwoVEXInfo rhlp.BinReader &rex rhlp.CurrPos + rhlp.REXPrefix <- rex + rhlp.CurrPos <- rhlp.CurrPos + 1 + parseTwoByteOpcode rhlp + else + rhlp.SzComputers.[int SZ.PZ].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.GprM].Render rhlp + newInsInfo rhlp Opcode.LDS oprs + +type internal OneOpC6 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.RmImm8 SZ.Byte OpGroup.G11A + render rhlp op szCond oidx szidx + +type internal OneOpC7 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.RmImm SZ.Def OpGroup.G11B + render rhlp op szCond oidx szidx + +type internal OneOpC8 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.ImmImm].Render rhlp + newInsInfo rhlp Opcode.ENTER oprs + +type internal OneOpC9 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.D64 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.LEAVE oprs + +type internal OneOpCA () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Imm16].Render rhlp + newInsInfo rhlp Opcode.RETFarImm oprs + +type internal OneOpCB () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.RETFar oprs + +type internal OneOpCC () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.INT3 oprs + +type internal OneOpCD () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Imm8].Render rhlp + newInsInfo rhlp Opcode.INT oprs + +type internal OneOpCE () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.INTO oprs + +type internal OneOpCF () = + inherit ParsingJob () + override __.Run rhlp = + if hasOprSz rhlp.Prefixes then + render rhlp Opcode.IRETW SzCond.Nor OD.No SZ.Def + elif hasREXW rhlp.REXPrefix then + render rhlp Opcode.IRETQ SzCond.Nor OD.No SZ.Def + else render rhlp Opcode.IRETD SzCond.Nor OD.No SZ.Def + +type internal OneOpD0 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.M1 SZ.Byte OpGroup.G2 + render rhlp op szCond oidx szidx + +type internal OneOpD1 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.M1 SZ.Def OpGroup.G2 + render rhlp op szCond oidx szidx + +type internal OneOpD2 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.RmCL SZ.Byte OpGroup.G2 + render rhlp op szCond oidx szidx + +type internal OneOpD3 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.RmCL SZ.Def OpGroup.G2 + render rhlp op szCond oidx szidx + +type internal OneOpD4 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Imm8].Render rhlp + newInsInfo rhlp Opcode.AAM oprs + +type internal OneOpD5 () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Imm8].Render rhlp + newInsInfo rhlp Opcode.AAD oprs + +type internal OneOpD6 () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOpD7 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.XLATB oprs + +type internal OneOpD8 () = + inherit ParsingJob () + override __.Run rhlp = + let modRM = rhlp.ReadByte () + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + if modRM <= 0xBFuy then + let op = getD8OpWithin00toBF modRM + let effOprSize = getEscEffOprSizeByESCOp 0xD8uy + rhlp.MemEffOprSize <- effOprSize + rhlp.MemEffRegSize <- effOprSize + let o = OperandParsingHelper.parseMemory modRM rhlp + newInsInfo rhlp op (OneOperand o) + else + let opcode, oprs = getD8OverBF modRM + newInsInfo rhlp opcode oprs + +type internal OneOpD9 () = + inherit ParsingJob () + override __.Run rhlp = + let modRM = rhlp.ReadByte () + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + if modRM <= 0xBFuy then + let op = getD9OpWithin00toBF modRM + let effOprSize = getReg modRM |> getD9EscEffOprSizeByModRM + rhlp.MemEffOprSize <- effOprSize + rhlp.MemEffRegSize <- effOprSize + let o = OperandParsingHelper.parseMemory modRM rhlp + newInsInfo rhlp op (OneOperand o) + else + let opcode, oprs = getD9OverBF modRM + newInsInfo rhlp opcode oprs + +type internal OneOpDA () = + inherit ParsingJob () + override __.Run rhlp = + let modRM = rhlp.ReadByte () + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + if modRM <= 0xBFuy then + let op = getDAOpWithin00toBF modRM + let effOprSize = getEscEffOprSizeByESCOp 0xDAuy + rhlp.MemEffOprSize <- effOprSize + rhlp.MemEffRegSize <- effOprSize + let o = OperandParsingHelper.parseMemory modRM rhlp + newInsInfo rhlp op (OneOperand o) + else + let opcode, oprs = getDAOverBF modRM + newInsInfo rhlp opcode oprs + +type internal OneOpDB () = + inherit ParsingJob () + override __.Run rhlp = + let modRM = rhlp.ReadByte () + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + if modRM <= 0xBFuy then + let op = getDBOpWithin00toBF modRM + let effOprSize = getReg modRM |> getDBEscEffOprSizeByModRM + rhlp.MemEffOprSize <- effOprSize + rhlp.MemEffRegSize <- effOprSize + let o = OperandParsingHelper.parseMemory modRM rhlp + newInsInfo rhlp op (OneOperand o) + else + let opcode, oprs = getDBOverBF modRM + newInsInfo rhlp opcode oprs + +type internal OneOpDC () = + inherit ParsingJob () + override __.Run rhlp = + let modRM = rhlp.ReadByte () + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + if modRM <= 0xBFuy then + let op = getDCOpWithin00toBF modRM + let effOprSize = getEscEffOprSizeByESCOp 0xDCuy + rhlp.MemEffOprSize <- effOprSize + rhlp.MemEffRegSize <- effOprSize + let o = OperandParsingHelper.parseMemory modRM rhlp + newInsInfo rhlp op (OneOperand o) + else + let opcode, oprs = getDCOverBF modRM + newInsInfo rhlp opcode oprs + +type internal OneOpDD () = + inherit ParsingJob () + override __.Run rhlp = + let modRM = rhlp.ReadByte () + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + if modRM <= 0xBFuy then + let op = getDDOpWithin00toBF modRM + let effOprSize = getReg modRM |> getDDEscEffOprSizeByModRM + rhlp.MemEffOprSize <- effOprSize + rhlp.MemEffRegSize <- effOprSize + let o = OperandParsingHelper.parseMemory modRM rhlp + newInsInfo rhlp op (OneOperand o) + else + let opcode, oprs = getDDOverBF modRM + newInsInfo rhlp opcode oprs + +type internal OneOpDE () = + inherit ParsingJob () + override __.Run rhlp = + let modRM = rhlp.ReadByte () + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + if modRM <= 0xBFuy then + let op = getDEOpWithin00toBF modRM + let effOprSize = getEscEffOprSizeByESCOp 0xDEuy + rhlp.MemEffOprSize <- effOprSize + rhlp.MemEffRegSize <- effOprSize + let o = OperandParsingHelper.parseMemory modRM rhlp + newInsInfo rhlp op (OneOperand o) + else + let opcode, oprs = getDEOverBF modRM + newInsInfo rhlp opcode oprs + +type internal OneOpDF () = + inherit ParsingJob () + override __.Run rhlp = + let modRM = rhlp.ReadByte () + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + if modRM <= 0xBFuy then + let op = getDFOpWithin00toBF modRM + let effOprSize = getReg modRM |> getDFEscEffOprSizeByModRM + rhlp.MemEffOprSize <- effOprSize + rhlp.MemEffRegSize <- effOprSize + let o = OperandParsingHelper.parseMemory modRM rhlp + newInsInfo rhlp op (OneOperand o) + else + let opcode, oprs = getDFOverBF modRM + newInsInfo rhlp opcode oprs + +type internal OneOpE0 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.LOOPNE oprs + +type internal OneOpE1 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.LOOPE oprs + +type internal OneOpE2 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.LOOP oprs + +type internal OneOpE3 () = + inherit ParsingJob () + override __.Run rhlp = + if hasAddrSz rhlp.Prefixes then + let opcode = if is64bit rhlp then Opcode.JECXZ else Opcode.JCXZ + render rhlp opcode SzCond.F64 OD.Rel8 SZ.Byte + elif is64bit rhlp then render rhlp Opcode.JRCXZ SzCond.F64 OD.Rel8 SZ.Byte + else render rhlp Opcode.JECXZ SzCond.F64 OD.Rel8 SZ.Byte + +type internal OneOpE4 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm8].Render rhlp + newInsInfo rhlp Opcode.IN oprs + +type internal OneOpE5 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.RegImm8].Render rhlp + newInsInfo rhlp Opcode.IN oprs + +type internal OneOpE6 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Imm8Reg].Render rhlp + newInsInfo rhlp Opcode.OUT oprs + +type internal OneOpE7 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Imm8Reg].Render rhlp + newInsInfo rhlp Opcode.OUT oprs + +type internal OneOpE8 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel].Render rhlp + newInsInfo rhlp Opcode.CALLNear oprs + +type internal OneOpE9 () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.D64].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel].Render rhlp + newInsInfo rhlp Opcode.JMPNear oprs + +type internal OneOpEA () = + inherit ParsingJob () + override __.Run rhlp = +#if !EMULATION + ensure32 rhlp +#endif + addBND rhlp + rhlp.SzComputers.[int SZ.P].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.Dir].Render rhlp + newInsInfo rhlp Opcode.JMPFar oprs + +type internal OneOpEB () = + inherit ParsingJob () + override __.Run rhlp = + addBND rhlp + rhlp.SzComputers.[int SZ.Byte].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.Rel8].Render rhlp + newInsInfo rhlp Opcode.JMPNear oprs + +type internal OneOpEC () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.ALDx].Render rhlp + newInsInfo rhlp Opcode.IN oprs + +type internal OneOpED () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.EaxDx].Render rhlp + newInsInfo rhlp Opcode.IN oprs + +type internal OneOpEE () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.DxAL].Render rhlp + newInsInfo rhlp Opcode.OUT oprs + +type internal OneOpEF () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers.[int OD.DxEax].Render rhlp + newInsInfo rhlp Opcode.OUT oprs + +type internal OneOpF0 () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOpF1 () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOpF2 () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOpF3 () = + inherit ParsingJob () + override __.Run _rhlp = raise ParsingFailureException + +type internal OneOpF4 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.HLT oprs + +type internal OneOpF5 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.CMC oprs + +type internal OneOpF6 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.Mem SZ.Byte OpGroup.G3A + render rhlp op szCond oidx szidx + +type internal OneOpF7 () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.Mem SZ.Def OpGroup.G3B + render rhlp op szCond oidx szidx + +type internal OneOpF8 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.CLC oprs + +type internal OneOpF9 () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.STC oprs + +type internal OneOpFA () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.CLI oprs + +type internal OneOpFB () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.STI oprs + +type internal OneOpFC () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.CLD oprs + +type internal OneOpFD () = + inherit ParsingJob () + override __.Run rhlp = + rhlp.SzComputers.[int SZ.Def].Render rhlp SzCond.F64 + let oprs = rhlp.OprParsers.[int OD.No].Render rhlp + newInsInfo rhlp Opcode.STD oprs + +type internal OneOpFE () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.No SZ.Def OpGroup.G4 + render rhlp op szCond oidx szidx + +type internal OneOpFF () = + inherit ParsingJob () + override __.Run rhlp = + let struct (op, oidx, szidx, szCond) = + parseGrpOpKind rhlp OD.No SZ.Def OpGroup.G5 + if isBranch op then addBND rhlp else () + render rhlp op szCond oidx szidx diff --git a/src/FrontEnd/Intel/IntelRegExprs.fs b/src/FrontEnd/BinLifter/Intel/IntelRegExprs.fs similarity index 66% rename from src/FrontEnd/Intel/IntelRegExprs.fs rename to src/FrontEnd/BinLifter/Intel/IntelRegExprs.fs index 240946c5..bad2f9a7 100644 --- a/src/FrontEnd/Intel/IntelRegExprs.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelRegExprs.fs @@ -22,46 +22,54 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.Intel +namespace B2R2.FrontEnd.BinLifter.Intel open B2R2 -open B2R2.BinIR.LowUIR.AST +open B2R2.BinIR.LowUIR + +/// This is a fatal error that happens when B2R2 tries to access non-existing +/// register symbol. This exception should not happen in general. +exception internal InvalidRegAccessException type internal RegExprs (wordSize) = - let var sz t name = var sz t name (IntelRegisterSet.singleton t) + let var sz t name = AST.var sz t name (IntelRegisterSet.singleton t) let reg64 wordSize t name = - if wordSize = WordSize.Bit32 then unDef 64 name else var 64 t name + if wordSize = WordSize.Bit32 then AST.undef 64 name + else var 64 t name let reg32 wordSize t name r64 = if wordSize = WordSize.Bit32 then var 32 t name - else extractLow 32 r64 + else AST.xtlo 32 r64 let reg32ext wordSize name r64 = - if wordSize = WordSize.Bit32 then unDef 32 name - else extractLow 32 r64 + if wordSize = WordSize.Bit32 then AST.undef 32 name + else AST.xtlo 32 r64 let reg16 wordSize r32 r64 = - extractLow 16 (if wordSize = WordSize.Bit32 then r32 else r64) + AST.xtlo 16 (if wordSize = WordSize.Bit32 then r32 else r64) let reg16ext wordSize name r64 = - if wordSize = WordSize.Bit32 then unDef 16 name - else extractLow 16 r64 + if wordSize = WordSize.Bit32 then AST.undef 16 name + else AST.xtlo 16 r64 let regL8 wordSize r32 r64 = - extractLow 8 (if wordSize = WordSize.Bit32 then r32 else r64) + AST.xtlo 8 (if wordSize = WordSize.Bit32 then r32 else r64) let regH8 wordSize r32 r64 = - extract (if wordSize = WordSize.Bit32 then r32 else r64) 8 8 + AST.extract (if wordSize = WordSize.Bit32 then r32 else r64) 8 8 let regL8ext wordSize name r64 = - if wordSize = WordSize.Bit32 then unDef 16 name else extractLow 8 r64 + if wordSize = WordSize.Bit32 then AST.undef 16 name + else AST.xtlo 8 r64 +#if DEBUG let assert64Bit wordSize = if wordSize = WordSize.Bit64 then () else raise InvalidRegAccessException let assert32Bit wordSize = if wordSize = WordSize.Bit32 then () else raise InvalidRegAccessException +#endif (* Registers *) let rax = reg64 wordSize (Register.toRegID Register.RAX) "RAX" @@ -127,6 +135,12 @@ type internal RegExprs (wordSize) = let k5 = var 64 (Register.toRegID Register.K5) "K5" let k6 = var 64 (Register.toRegID Register.K6) "K6" let k7 = var 64 (Register.toRegID Register.K7) "K7" + let dr0 = var 32 (Register.toRegID Register.DR0) "DR0" + let dr1 = var 32 (Register.toRegID Register.DR1) "DR1" + let dr2 = var 32 (Register.toRegID Register.DR2) "DR2" + let dr3 = var 32 (Register.toRegID Register.DR3) "DR3" + let dr6 = var 32 (Register.toRegID Register.DR6) "DR6" + let dr7 = var 32 (Register.toRegID Register.DR7) "DR7" (* QWORD regs *) member val RAX = rax with get @@ -201,8 +215,8 @@ type internal RegExprs (wordSize) = member val SIL = regL8ext wordSize "SIL" rsi with get member val DIL = regL8ext wordSize "DIL" rdi with get (* Program counters *) - member val EIP = pcVar 32 "EIP" - member val RIP = pcVar 64 "RIP" + member val EIP = AST.pcvar 32 "EIP" + member val RIP = AST.pcvar 64 "RIP" (* Segment selector *) member val CS = var 16 (Register.toRegID Register.CS) "CS" member val DS = var 16 (Register.toRegID Register.DS) "DS" @@ -558,21 +572,21 @@ type internal RegExprs (wordSize) = member val ST7A = st7a member val ST7B = st7b (* x87 FPU Top register *) - member val FTOP = extract fsw 3 11 + member val FTOP = AST.extract fsw 3 11 (* x87 FPU Tag word sections*) - member val FTW0 = extract ftw 2 0 - member val FTW1 = extract ftw 2 2 - member val FTW2 = extract ftw 2 4 - member val FTW3 = extract ftw 2 6 - member val FTW4 = extract ftw 2 8 - member val FTW5 = extract ftw 2 10 - member val FTW6 = extract ftw 2 12 - member val FTW7 = extract ftw 2 14 + member val FTW0 = AST.extract ftw 2 0 + member val FTW1 = AST.extract ftw 2 2 + member val FTW2 = AST.extract ftw 2 4 + member val FTW3 = AST.extract ftw 2 6 + member val FTW4 = AST.extract ftw 2 8 + member val FTW5 = AST.extract ftw 2 10 + member val FTW6 = AST.extract ftw 2 12 + member val FTW7 = AST.extract ftw 2 14 (* x87 Status Word Flags *) - member val FSWC0 = extract fsw 1 8 - member val FSWC1 = extract fsw 1 9 - member val FSWC2 = extract fsw 1 10 - member val FSWC3 = extract fsw 1 14 + member val FSWC0 = AST.extract fsw 1 8 + member val FSWC1 = AST.extract fsw 1 9 + member val FSWC2 = AST.extract fsw 1 10 + member val FSWC3 = AST.extract fsw 1 14 (* Opmask registers *) member val K0 = k0 with get member val K1 = k1 with get @@ -582,17 +596,56 @@ type internal RegExprs (wordSize) = member val K5 = k5 with get member val K6 = k6 with get member val K7 = k7 with get + (* Debug registers *) + member val DR0 = dr0 with get + member val DR1 = dr1 with get + member val DR2 = dr2 with get + member val DR3 = dr3 with get + member val DR6 = dr6 with get + member val DR7 = dr7 with get member __.GetRegVar (name) = match name with - | R.RAX -> assert64Bit wordSize; __.RAX - | R.RBX -> assert64Bit wordSize; __.RBX - | R.RCX -> assert64Bit wordSize; __.RCX - | R.RDX -> assert64Bit wordSize; __.RDX - | R.RSP -> assert64Bit wordSize; __.RSP - | R.RBP -> assert64Bit wordSize; __.RBP - | R.RSI -> assert64Bit wordSize; __.RSI - | R.RDI -> assert64Bit wordSize; __.RDI + | R.RAX -> +#if DEBUG + assert64Bit wordSize +#endif + __.RAX + | R.RBX -> +#if DEBUG + assert64Bit wordSize +#endif + __.RBX + | R.RCX -> +#if DEBUG + assert64Bit wordSize +#endif + __.RCX + | R.RDX -> +#if DEBUG + assert64Bit wordSize +#endif + __.RDX + | R.RSP -> +#if DEBUG + assert64Bit wordSize +#endif + __.RSP + | R.RBP -> +#if DEBUG + assert64Bit wordSize +#endif + __.RBP + | R.RSI -> +#if DEBUG + assert64Bit wordSize +#endif + __.RSI + | R.RDI -> +#if DEBUG + assert64Bit wordSize +#endif + __.RDI | R.EAX -> __.EAX | R.EBX -> __.EBX | R.ECX -> __.ECX @@ -617,44 +670,196 @@ type internal RegExprs (wordSize) = | R.BH -> __.BH | R.CH -> __.CH | R.DH -> __.DH - | R.R8 -> assert64Bit wordSize; __.R8 - | R.R9 -> assert64Bit wordSize; __.R9 - | R.R10 -> assert64Bit wordSize; __.R10 - | R.R11 -> assert64Bit wordSize; __.R11 - | R.R12 -> assert64Bit wordSize; __.R12 - | R.R13 -> assert64Bit wordSize; __.R13 - | R.R14 -> assert64Bit wordSize; __.R14 - | R.R15 -> assert64Bit wordSize; __.R15 - | R.R8D -> assert64Bit wordSize; __.R8D - | R.R9D -> assert64Bit wordSize; __.R9D - | R.R10D -> assert64Bit wordSize; __.R10D - | R.R11D -> assert64Bit wordSize; __.R11D - | R.R12D -> assert64Bit wordSize; __.R12D - | R.R13D -> assert64Bit wordSize; __.R13D - | R.R14D -> assert64Bit wordSize; __.R14D - | R.R15D -> assert64Bit wordSize; __.R15D - | R.R8W -> assert64Bit wordSize; __.R8W - | R.R9W -> assert64Bit wordSize; __.R9W - | R.R10W -> assert64Bit wordSize; __.R10W - | R.R11W -> assert64Bit wordSize; __.R11W - | R.R12W -> assert64Bit wordSize; __.R12W - | R.R13W -> assert64Bit wordSize; __.R13W - | R.R14W -> assert64Bit wordSize; __.R14W - | R.R15W -> assert64Bit wordSize; __.R15W - | R.R8L -> assert64Bit wordSize; __.R8L - | R.R9L -> assert64Bit wordSize; __.R9L - | R.R10L -> assert64Bit wordSize; __.R10L - | R.R11L -> assert64Bit wordSize; __.R11L - | R.R12L -> assert64Bit wordSize; __.R12L - | R.R13L -> assert64Bit wordSize; __.R13L - | R.R14L -> assert64Bit wordSize; __.R14L - | R.R15L -> assert64Bit wordSize; __.R15L - | R.SPL -> assert64Bit wordSize; __.SPL - | R.BPL -> assert64Bit wordSize; __.BPL - | R.SIL -> assert64Bit wordSize; __.SIL - | R.DIL -> assert64Bit wordSize; __.DIL - | R.EIP -> assert32Bit wordSize; __.EIP - | R.RIP -> assert64Bit wordSize; __.RIP + | R.R8 -> +#if DEBUG + assert64Bit wordSize +#endif + __.R8 + | R.R9 -> +#if DEBUG + assert64Bit wordSize +#endif + __.R9 + | R.R10 -> +#if DEBUG + assert64Bit wordSize +#endif + __.R10 + | R.R11 -> +#if DEBUG + assert64Bit wordSize +#endif + __.R11 + | R.R12 -> +#if DEBUG + assert64Bit wordSize +#endif + __.R12 + | R.R13 -> +#if DEBUG + assert64Bit wordSize +#endif + __.R13 + | R.R14 -> +#if DEBUG + assert64Bit wordSize +#endif + __.R14 + | R.R15 -> +#if DEBUG + assert64Bit wordSize +#endif + __.R15 + | R.R8D -> +#if DEBUG + assert64Bit wordSize +#endif + __.R8D + | R.R9D -> +#if DEBUG + assert64Bit wordSize +#endif + __.R9D + | R.R10D -> +#if DEBUG + assert64Bit wordSize +#endif + __.R10D + | R.R11D -> +#if DEBUG + assert64Bit wordSize +#endif + __.R11D + | R.R12D -> +#if DEBUG + assert64Bit wordSize +#endif + __.R12D + | R.R13D -> +#if DEBUG + assert64Bit wordSize +#endif + __.R13D + | R.R14D -> +#if DEBUG + assert64Bit wordSize +#endif + __.R14D + | R.R15D -> +#if DEBUG + assert64Bit wordSize +#endif + __.R15D + | R.R8W -> +#if DEBUG + assert64Bit wordSize +#endif + __.R8W + | R.R9W -> +#if DEBUG + assert64Bit wordSize +#endif + __.R9W + | R.R10W -> +#if DEBUG + assert64Bit wordSize +#endif + __.R10W + | R.R11W -> +#if DEBUG + assert64Bit wordSize +#endif + __.R11W + | R.R12W -> +#if DEBUG + assert64Bit wordSize +#endif + __.R12W + | R.R13W -> +#if DEBUG + assert64Bit wordSize +#endif + __.R13W + | R.R14W -> +#if DEBUG + assert64Bit wordSize +#endif + __.R14W + | R.R15W -> +#if DEBUG + assert64Bit wordSize +#endif + __.R15W + | R.R8L -> +#if DEBUG + assert64Bit wordSize +#endif + __.R8L + | R.R9L -> +#if DEBUG + assert64Bit wordSize +#endif + __.R9L + | R.R10L -> +#if DEBUG + assert64Bit wordSize +#endif + __.R10L + | R.R11L -> +#if DEBUG + assert64Bit wordSize +#endif + __.R11L + | R.R12L -> +#if DEBUG + assert64Bit wordSize +#endif + __.R12L + | R.R13L -> +#if DEBUG + assert64Bit wordSize +#endif + __.R13L + | R.R14L -> +#if DEBUG + assert64Bit wordSize +#endif + __.R14L + | R.R15L -> +#if DEBUG + assert64Bit wordSize +#endif + __.R15L + | R.SPL -> +#if DEBUG + assert64Bit wordSize +#endif + __.SPL + | R.BPL -> +#if DEBUG + assert64Bit wordSize +#endif + __.BPL + | R.SIL -> +#if DEBUG + assert64Bit wordSize +#endif + __.SIL + | R.DIL -> +#if DEBUG + assert64Bit wordSize +#endif + __.DIL + | R.EIP -> +#if DEBUG + assert32Bit wordSize +#endif + __.EIP + | R.RIP -> +#if DEBUG + assert64Bit wordSize +#endif + __.RIP | R.CS -> __.CS | R.DS -> __.DS | R.ES -> __.ES @@ -671,7 +876,11 @@ type internal RegExprs (wordSize) = | R.CR2 -> __.CR2 | R.CR3 -> __.CR3 | R.CR4 -> __.CR4 - | R.CR8 -> assert64Bit wordSize; __.CR8 + | R.CR8 -> +#if DEBUG + assert64Bit wordSize +#endif + __.CR8 | R.OF -> __.OF | R.DF -> __.DF | R.IF -> __.IF @@ -713,14 +922,14 @@ type internal RegExprs (wordSize) = | R.MXCSR -> __.MXCSR | R.MXCSRMASK -> __.MXCSRMASK | R.PKRU -> __.PKRU - | R.ST0 -> concat __.ST0B __.ST0A - | R.ST1 -> concat __.ST1B __.ST1A - | R.ST2 -> concat __.ST2B __.ST2A - | R.ST3 -> concat __.ST3B __.ST3A - | R.ST4 -> concat __.ST4B __.ST4A - | R.ST5 -> concat __.ST5B __.ST5A - | R.ST6 -> concat __.ST6B __.ST6A - | R.ST7 -> concat __.ST7B __.ST7A + | R.ST0 -> AST.concat __.ST0B __.ST0A + | R.ST1 -> AST.concat __.ST1B __.ST1A + | R.ST2 -> AST.concat __.ST2B __.ST2A + | R.ST3 -> AST.concat __.ST3B __.ST3A + | R.ST4 -> AST.concat __.ST4B __.ST4A + | R.ST5 -> AST.concat __.ST5B __.ST5A + | R.ST6 -> AST.concat __.ST6B __.ST6A + | R.ST7 -> AST.concat __.ST7B __.ST7A | R.K0 -> __.K0 | R.K1 -> __.K1 | R.K2 -> __.K2 @@ -729,6 +938,12 @@ type internal RegExprs (wordSize) = | R.K5 -> __.K5 | R.K6 -> __.K6 | R.K7 -> __.K7 + | R.DR0 -> __.DR0 + | R.DR1 -> __.DR1 + | R.DR2 -> __.DR2 + | R.DR3 -> __.DR3 + | R.DR6 -> __.DR6 + | R.DR7 -> __.DR7 | _ -> failwith "Unhandled register." member __.GetPseudoRegVar name pos = @@ -749,22 +964,86 @@ type internal RegExprs (wordSize) = | R.XMM6, 2 -> __.ZMM6B | R.XMM7, 1 -> __.ZMM7A | R.XMM7, 2 -> __.ZMM7B - | R.XMM8, 1 -> assert64Bit wordSize; __.ZMM8A - | R.XMM8, 2 -> assert64Bit wordSize; __.ZMM8B - | R.XMM9, 1 -> assert64Bit wordSize; __.ZMM9A - | R.XMM9, 2 -> assert64Bit wordSize; __.ZMM9B - | R.XMM10, 1 -> assert64Bit wordSize; __.ZMM10A - | R.XMM10, 2 -> assert64Bit wordSize; __.ZMM10B - | R.XMM11, 1 -> assert64Bit wordSize; __.ZMM11A - | R.XMM11, 2 -> assert64Bit wordSize; __.ZMM11B - | R.XMM12, 1 -> assert64Bit wordSize; __.ZMM12A - | R.XMM12, 2 -> assert64Bit wordSize; __.ZMM12B - | R.XMM13, 1 -> assert64Bit wordSize; __.ZMM13A - | R.XMM13, 2 -> assert64Bit wordSize; __.ZMM13B - | R.XMM14, 1 -> assert64Bit wordSize; __.ZMM14A - | R.XMM14, 2 -> assert64Bit wordSize; __.ZMM14B - | R.XMM15, 1 -> assert64Bit wordSize; __.ZMM15A - | R.XMM15, 2 -> assert64Bit wordSize; __.ZMM15B + | R.XMM8, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8A + | R.XMM8, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8B + | R.XMM9, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9A + | R.XMM9, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9B + | R.XMM10, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10A + | R.XMM10, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10B + | R.XMM11, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11A + | R.XMM11, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11B + | R.XMM12, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12A + | R.XMM12, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12B + | R.XMM13, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13A + | R.XMM13, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13B + | R.XMM14, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14A + | R.XMM14, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14B + | R.XMM15, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15A + | R.XMM15, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15B | R.YMM0, 1 -> __.ZMM0A | R.YMM0, 2 -> __.ZMM0B | R.YMM0, 3 -> __.ZMM0C @@ -797,38 +1076,166 @@ type internal RegExprs (wordSize) = | R.YMM7, 2 -> __.ZMM7B | R.YMM7, 3 -> __.ZMM7C | R.YMM7, 4 -> __.ZMM7D - | R.YMM8, 1 -> assert64Bit wordSize; __.ZMM8A - | R.YMM8, 2 -> assert64Bit wordSize; __.ZMM8B - | R.YMM8, 3 -> assert64Bit wordSize; __.ZMM8C - | R.YMM8, 4 -> assert64Bit wordSize; __.ZMM8D - | R.YMM9, 1 -> assert64Bit wordSize; __.ZMM9A - | R.YMM9, 2 -> assert64Bit wordSize; __.ZMM9B - | R.YMM9, 3 -> assert64Bit wordSize; __.ZMM9C - | R.YMM9, 4 -> assert64Bit wordSize; __.ZMM9D - | R.YMM10, 1 -> assert64Bit wordSize; __.ZMM10A - | R.YMM10, 2 -> assert64Bit wordSize; __.ZMM10B - | R.YMM10, 3 -> assert64Bit wordSize; __.ZMM10C - | R.YMM10, 4 -> assert64Bit wordSize; __.ZMM10D - | R.YMM11, 1 -> assert64Bit wordSize; __.ZMM11A - | R.YMM11, 2 -> assert64Bit wordSize; __.ZMM11B - | R.YMM11, 3 -> assert64Bit wordSize; __.ZMM11C - | R.YMM11, 4 -> assert64Bit wordSize; __.ZMM11D - | R.YMM12, 1 -> assert64Bit wordSize; __.ZMM12A - | R.YMM12, 2 -> assert64Bit wordSize; __.ZMM12B - | R.YMM12, 3 -> assert64Bit wordSize; __.ZMM12C - | R.YMM12, 4 -> assert64Bit wordSize; __.ZMM12D - | R.YMM13, 1 -> assert64Bit wordSize; __.ZMM13A - | R.YMM13, 2 -> assert64Bit wordSize; __.ZMM13B - | R.YMM13, 3 -> assert64Bit wordSize; __.ZMM13C - | R.YMM13, 4 -> assert64Bit wordSize; __.ZMM13D - | R.YMM14, 1 -> assert64Bit wordSize; __.ZMM14A - | R.YMM14, 2 -> assert64Bit wordSize; __.ZMM14B - | R.YMM14, 3 -> assert64Bit wordSize; __.ZMM14C - | R.YMM14, 4 -> assert64Bit wordSize; __.ZMM14D - | R.YMM15, 1 -> assert64Bit wordSize; __.ZMM15A - | R.YMM15, 2 -> assert64Bit wordSize; __.ZMM15B - | R.YMM15, 3 -> assert64Bit wordSize; __.ZMM15C - | R.YMM15, 4 -> assert64Bit wordSize; __.ZMM15D + | R.YMM8, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8A + | R.YMM8, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8B + | R.YMM8, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8C + | R.YMM8, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8D + | R.YMM9, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9A + | R.YMM9, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9B + | R.YMM9, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9C + | R.YMM9, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9D + | R.YMM10, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10A + | R.YMM10, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10B + | R.YMM10, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10C + | R.YMM10, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10D + | R.YMM11, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11A + | R.YMM11, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11B + | R.YMM11, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11C + | R.YMM11, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11D + | R.YMM12, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12A + | R.YMM12, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12B + | R.YMM12, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12C + | R.YMM12, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12D + | R.YMM13, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13A + | R.YMM13, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13B + | R.YMM13, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13C + | R.YMM13, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13D + | R.YMM14, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14A + | R.YMM14, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14B + | R.YMM14, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14C + | R.YMM14, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14D + | R.YMM15, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15A + | R.YMM15, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15B + | R.YMM15, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15C + | R.YMM15, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15D | R.ZMM0, 1 -> __.ZMM0A | R.ZMM0, 2 -> __.ZMM0B | R.ZMM0, 3 -> __.ZMM0C @@ -893,70 +1300,326 @@ type internal RegExprs (wordSize) = | R.ZMM7, 6 -> __.ZMM7F | R.ZMM7, 7 -> __.ZMM7G | R.ZMM7, 8 -> __.ZMM7H - | R.ZMM8, 1 -> assert64Bit wordSize; __.ZMM8A - | R.ZMM8, 2 -> assert64Bit wordSize; __.ZMM8B - | R.ZMM8, 3 -> assert64Bit wordSize; __.ZMM8C - | R.ZMM8, 4 -> assert64Bit wordSize; __.ZMM8D - | R.ZMM8, 5 -> assert64Bit wordSize; __.ZMM8E - | R.ZMM8, 6 -> assert64Bit wordSize; __.ZMM8F - | R.ZMM8, 7 -> assert64Bit wordSize; __.ZMM8G - | R.ZMM8, 8 -> assert64Bit wordSize; __.ZMM8F - | R.ZMM9, 1 -> assert64Bit wordSize; __.ZMM9A - | R.ZMM9, 2 -> assert64Bit wordSize; __.ZMM9B - | R.ZMM9, 3 -> assert64Bit wordSize; __.ZMM9C - | R.ZMM9, 4 -> assert64Bit wordSize; __.ZMM9D - | R.ZMM9, 5 -> assert64Bit wordSize; __.ZMM9E - | R.ZMM9, 6 -> assert64Bit wordSize; __.ZMM9F - | R.ZMM9, 7 -> assert64Bit wordSize; __.ZMM9G - | R.ZMM9, 8 -> assert64Bit wordSize; __.ZMM9F - | R.ZMM10, 1 -> assert64Bit wordSize; __.ZMM10A - | R.ZMM10, 2 -> assert64Bit wordSize; __.ZMM10B - | R.ZMM10, 3 -> assert64Bit wordSize; __.ZMM10C - | R.ZMM10, 4 -> assert64Bit wordSize; __.ZMM10D - | R.ZMM10, 5 -> assert64Bit wordSize; __.ZMM10E - | R.ZMM10, 6 -> assert64Bit wordSize; __.ZMM10F - | R.ZMM10, 7 -> assert64Bit wordSize; __.ZMM10G - | R.ZMM10, 8 -> assert64Bit wordSize; __.ZMM10F - | R.ZMM11, 1 -> assert64Bit wordSize; __.ZMM11A - | R.ZMM11, 2 -> assert64Bit wordSize; __.ZMM11B - | R.ZMM11, 3 -> assert64Bit wordSize; __.ZMM11C - | R.ZMM11, 4 -> assert64Bit wordSize; __.ZMM11D - | R.ZMM11, 5 -> assert64Bit wordSize; __.ZMM11E - | R.ZMM11, 6 -> assert64Bit wordSize; __.ZMM11F - | R.ZMM11, 7 -> assert64Bit wordSize; __.ZMM11G - | R.ZMM11, 8 -> assert64Bit wordSize; __.ZMM11F - | R.ZMM12, 1 -> assert64Bit wordSize; __.ZMM12A - | R.ZMM12, 2 -> assert64Bit wordSize; __.ZMM12B - | R.ZMM12, 3 -> assert64Bit wordSize; __.ZMM12C - | R.ZMM12, 4 -> assert64Bit wordSize; __.ZMM12D - | R.ZMM12, 5 -> assert64Bit wordSize; __.ZMM12E - | R.ZMM12, 6 -> assert64Bit wordSize; __.ZMM12F - | R.ZMM12, 7 -> assert64Bit wordSize; __.ZMM12G - | R.ZMM12, 8 -> assert64Bit wordSize; __.ZMM12F - | R.ZMM13, 1 -> assert64Bit wordSize; __.ZMM13A - | R.ZMM13, 2 -> assert64Bit wordSize; __.ZMM13B - | R.ZMM13, 3 -> assert64Bit wordSize; __.ZMM13C - | R.ZMM13, 4 -> assert64Bit wordSize; __.ZMM13D - | R.ZMM13, 5 -> assert64Bit wordSize; __.ZMM13E - | R.ZMM13, 6 -> assert64Bit wordSize; __.ZMM13F - | R.ZMM13, 7 -> assert64Bit wordSize; __.ZMM13G - | R.ZMM13, 8 -> assert64Bit wordSize; __.ZMM13F - | R.ZMM14, 1 -> assert64Bit wordSize; __.ZMM14A - | R.ZMM14, 2 -> assert64Bit wordSize; __.ZMM14B - | R.ZMM14, 3 -> assert64Bit wordSize; __.ZMM14C - | R.ZMM14, 4 -> assert64Bit wordSize; __.ZMM14D - | R.ZMM14, 5 -> assert64Bit wordSize; __.ZMM14E - | R.ZMM14, 6 -> assert64Bit wordSize; __.ZMM14F - | R.ZMM14, 7 -> assert64Bit wordSize; __.ZMM14G - | R.ZMM14, 8 -> assert64Bit wordSize; __.ZMM14F - | R.ZMM15, 1 -> assert64Bit wordSize; __.ZMM15A - | R.ZMM15, 2 -> assert64Bit wordSize; __.ZMM15B - | R.ZMM15, 3 -> assert64Bit wordSize; __.ZMM15C - | R.ZMM15, 4 -> assert64Bit wordSize; __.ZMM15D - | R.ZMM15, 5 -> assert64Bit wordSize; __.ZMM15E - | R.ZMM15, 6 -> assert64Bit wordSize; __.ZMM15F - | R.ZMM15, 7 -> assert64Bit wordSize; __.ZMM15G - | R.ZMM15, 8 -> assert64Bit wordSize; __.ZMM15F + | R.ZMM8, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8A + | R.ZMM8, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8B + | R.ZMM8, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8C + | R.ZMM8, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8D + | R.ZMM8, 5 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8E + | R.ZMM8, 6 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8F + | R.ZMM8, 7 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8G + | R.ZMM8, 8 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM8F + | R.ZMM9, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9A + | R.ZMM9, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9B + | R.ZMM9, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9C + | R.ZMM9, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9D + | R.ZMM9, 5 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9E + | R.ZMM9, 6 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9F + | R.ZMM9, 7 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9G + | R.ZMM9, 8 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM9F + | R.ZMM10, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10A + | R.ZMM10, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10B + | R.ZMM10, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10C + | R.ZMM10, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10D + | R.ZMM10, 5 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10E + | R.ZMM10, 6 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10F + | R.ZMM10, 7 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10G + | R.ZMM10, 8 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM10F + | R.ZMM11, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11A + | R.ZMM11, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11B + | R.ZMM11, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11C + | R.ZMM11, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11D + | R.ZMM11, 5 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11E + | R.ZMM11, 6 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11F + | R.ZMM11, 7 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11G + | R.ZMM11, 8 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM11F + | R.ZMM12, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12A + | R.ZMM12, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12B + | R.ZMM12, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12C + | R.ZMM12, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12D + | R.ZMM12, 5 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12E + | R.ZMM12, 6 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12F + | R.ZMM12, 7 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12G + | R.ZMM12, 8 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM12F + | R.ZMM13, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13A + | R.ZMM13, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13B + | R.ZMM13, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13C + | R.ZMM13, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13D + | R.ZMM13, 5 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13E + | R.ZMM13, 6 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13F + | R.ZMM13, 7 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13G + | R.ZMM13, 8 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM13F + | R.ZMM14, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14A + | R.ZMM14, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14B + | R.ZMM14, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14C + | R.ZMM14, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14D + | R.ZMM14, 5 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14E + | R.ZMM14, 6 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14F + | R.ZMM14, 7 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14G + | R.ZMM14, 8 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM14F + | R.ZMM15, 1 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15A + | R.ZMM15, 2 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15B + | R.ZMM15, 3 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15C + | R.ZMM15, 4 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15D + | R.ZMM15, 5 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15E + | R.ZMM15, 6 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15F + | R.ZMM15, 7 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15G + | R.ZMM15, 8 -> +#if DEBUG + assert64Bit wordSize +#endif + __.ZMM15F | R.BND0, 1 -> __.BND0A | R.BND0, 2 -> __.BND0B | R.BND1, 1 -> __.BND1A @@ -981,6 +1644,6 @@ type internal RegExprs (wordSize) = | R.ST6, 2 -> __.ST6B | R.ST7, 1 -> __.ST7A | R.ST7, 2 -> __.ST7B - | _ -> raise B2R2.FrontEnd.UnhandledRegExprException + | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/Intel/IntelRegister.fs b/src/FrontEnd/BinLifter/Intel/IntelRegister.fs similarity index 80% rename from src/FrontEnd/Intel/IntelRegister.fs rename to src/FrontEnd/BinLifter/Intel/IntelRegister.fs index ed3f7fc0..f2f3b3e5 100644 --- a/src/FrontEnd/Intel/IntelRegister.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelRegister.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.Intel +namespace B2R2.FrontEnd.BinLifter.Intel open B2R2 open System.Runtime.CompilerServices -[] +[] do () /// This exception occurs when an UnknownReg is explicitly used. This exception @@ -37,344 +37,345 @@ exception UnknownRegException /// /// Registers for x86 (and x86-64). /// -/// Internally, a Register is represented with an integer (we use only 12 bits). -/// The most significant 4 bits (from 8th to 11th bits) represent the register +/// Internally, a Register is represented with an integer (we use only 22 bits). +/// The most significant 10 bits (from 12th to 21th bits) represent the size of +/// the register. The next 4 bits (from 8th to 11th bits) represent the register /// kind, and the reset of 8 bits are used to represent a register ID. There are /// currently 13 kinds of registers including GP, FPU, MMX, etc. /// -/// 11 10 09 08 07 06 05 04 03 02 01 00 (bit position) -/// +----------+----------------------+ -/// | Kind | Register ID. | -/// +----------+----------------------+ +/// 21 ... 13 12 11 10 09 08 07 06 05 04 03 02 01 00 (bit position) +/// +------------+----------+----------------------+ +/// | Size | Kind | Register ID. | +/// +------------+----------+----------------------+ /// /// type Register = /// Accumulator for operands and results data (64bit). - | RAX = 0x0 - /// Pointer to data in the DS segment (64bit). - | RBX = 0x1 + | RAX = 0x40000 /// TCounter for string and loop operations (64bit). - | RCX = 0x2 + | RCX = 0x40001 /// I/O pointer (64bit). - | RDX = 0x3 + | RDX = 0x40002 + /// Pointer to data in the DS segment (64bit). + | RBX = 0x40003 /// Stack pointer (in the SS segment) (64bit). - | RSP = 0x4 + | RSP = 0x40004 /// Pointer to data on the stack (in the SS segment) (64bit). - | RBP = 0x5 + | RBP = 0x40005 /// Pointer to data in the segment pointed to by the DS register (64bit). - | RSI = 0x6 + | RSI = 0x40006 /// Pointer to data in the segment pointed to by the ES register (64bit). - | RDI = 0x7 - /// Accumulator for operands and results data (32bit). - | EAX = 0x8 - /// Pointer to data in the DS segment (32bit). - | EBX = 0x9 - /// TCounter for string and loop operations (32bit). - | ECX = 0xA - /// I/O pointer (32bit). - | EDX = 0xB - /// Stack pointer (in the SS segment) (32bit). - | ESP = 0xC - /// Pointer to data on the stack (in the SS segment) (32bit). - | EBP = 0xD - /// Pointer to data in the segment pointed to by the DS register (32bit). - | ESI = 0xE - /// Pointer to data in the segment pointed to by the ES register (32bit). - | EDI = 0xF - /// General-Purpose Registers (lower 16bits EAX). - | AX = 0x10 - /// General-Purpose Registers (lower 16bits EBX). - | BX = 0x11 - /// General-Purpose Registers (lower 16bits ECX). - | CX = 0x12 - /// General-Purpose Registers (lower 16bits EDX). - | DX = 0x13 - /// General-Purpose Registers (lower 16bits ESP). - | SP = 0x14 - /// General-Purpose Registers (lower 16bits EBP). - | BP = 0x15 - /// General-Purpose Registers (lower 16bits ESI). - | SI = 0x16 - /// General-Purpose Registers (lower 16bits EDI). - | DI = 0x17 - /// General-Purpose Registers (lower 8bits AX). - | AL = 0x18 - /// General-Purpose Registers (lower 8bits BX). - | BL = 0x19 - /// General-Purpose Registers (lower 8bits CX). - | CL = 0x1A - /// General-Purpose Registers (lower 8bits DX). - | DL = 0x1B - /// General-Purpose Registers (Higher 8bits AX). - | AH = 0x1C - /// General-Purpose Registers (Higher 8bits BX). - | BH = 0x1D - /// General-Purpose Registers (Higher 8bits CX). - | CH = 0x1E - /// General-Purpose Registers (Higher 8bits DX). - | DH = 0x1F + | RDI = 0x40007 /// General-Purpose Registers for 64bit Mode. - | R8 = 0x20 + | R8 = 0x40008 /// General-Purpose Registers for 64bit Mode. - | R9 = 0x21 + | R9 = 0x40009 /// General-Purpose Registers for 64bit Mode. - | R10 = 0x22 + | R10 = 0x4000A /// General-Purpose Registers for 64bit Mode. - | R11 = 0x23 + | R11 = 0x4000B /// General-Purpose Registers for 64bit Mode. - | R12 = 0x24 + | R12 = 0x4000C /// General-Purpose Registers for 64bit Mode. - | R13 = 0x25 + | R13 = 0x4000D /// General-Purpose Registers for 64bit Mode. - | R14 = 0x26 + | R14 = 0x4000E /// General-Purpose Registers for 64bit Mode. - | R15 = 0x27 + | R15 = 0x4000F + /// Accumulator for operands and results data (32bit). + | EAX = 0x20010 + /// TCounter for string and loop operations (32bit). + | ECX = 0x20011 + /// I/O pointer (32bit). + | EDX = 0x20012 + /// Pointer to data in the DS segment (32bit). + | EBX = 0x20013 + /// Stack pointer (in the SS segment) (32bit). + | ESP = 0x20014 + /// Pointer to data on the stack (in the SS segment) (32bit). + | EBP = 0x20015 + /// Pointer to data in the segment pointed to by the DS register (32bit). + | ESI = 0x20016 + /// Pointer to data in the segment pointed to by the ES register (32bit). + | EDI = 0x20017 /// General-Purpose Registers for 64bit Mode (Doubleword Register). - | R8D = 0x28 + | R8D = 0x20018 /// General-Purpose Registers for 64bit Mode (Doubleword Register). - | R9D = 0x29 + | R9D = 0x20019 /// General-Purpose Registers for 64bit Mode (Doubleword Register). - | R10D = 0x2A + | R10D = 0x2001A /// General-Purpose Registers for 64bit Mode (Doubleword Register). - | R11D = 0x2B + | R11D = 0x2001B /// General-Purpose Registers for 64bit Mode (Doubleword Register). - | R12D = 0x2C + | R12D = 0x2001C /// General-Purpose Registers for 64bit Mode (Doubleword Register). - | R13D = 0x2D + | R13D = 0x2001D /// General-Purpose Registers for 64bit Mode (Doubleword Register). - | R14D = 0x2E + | R14D = 0x2001E /// General-Purpose Registers for 64bit Mode (Doubleword Register). - | R15D = 0x2F + | R15D = 0x2001F + /// General-Purpose Registers (lower 16bits EAX). + | AX = 0x10020 + /// General-Purpose Registers (lower 16bits ECX). + | CX = 0x10021 + /// General-Purpose Registers (lower 16bits EDX). + | DX = 0x10022 + /// General-Purpose Registers (lower 16bits EBX). + | BX = 0x10023 + /// General-Purpose Registers (lower 16bits ESP). + | SP = 0x10024 + /// General-Purpose Registers (lower 16bits EBP). + | BP = 0x10025 + /// General-Purpose Registers (lower 16bits ESI). + | SI = 0x10026 + /// General-Purpose Registers (lower 16bits EDI). + | DI = 0x10027 /// General-Purpose Registers for 64bit Mode (Word Register). - | R8W = 0x30 + | R8W = 0x10028 /// General-Purpose Registers for 64bit Mode (Word Register). - | R9W = 0x31 + | R9W = 0x10029 /// General-Purpose Registers for 64bit Mode (Word Register). - | R10W = 0x32 + | R10W = 0x1002A /// General-Purpose Registers for 64bit Mode (Word Register). - | R11W = 0x33 + | R11W = 0x1002B /// General-Purpose Registers for 64bit Mode (Word Register). - | R12W = 0x34 + | R12W = 0x1002C /// General-Purpose Registers for 64bit Mode (Word Register). - | R13W = 0x35 + | R13W = 0x1002D /// General-Purpose Registers for 64bit Mode (Word Register). - | R14W = 0x36 + | R14W = 0x1002E /// General-Purpose Registers for 64bit Mode (Word Register). - | R15W = 0x37 + | R15W = 0x1002F + /// General-Purpose Registers (lower 8bits AX). + | AL = 0x8030 + /// General-Purpose Registers (lower 8bits CX). + | CL = 0x8031 + /// General-Purpose Registers (lower 8bits DX). + | DL = 0x8032 + /// General-Purpose Registers (lower 8bits BX). + | BL = 0x8033 + /// General-Purpose Registers (Higher 8bits AX). + | AH = 0x8034 + /// General-Purpose Registers (Higher 8bits CX). + | CH = 0x8035 + /// General-Purpose Registers (Higher 8bits DX). + | DH = 0x8036 + /// General-Purpose Registers (Higher 8bits BX). + | BH = 0x8037 /// General-Purpose Registers for 64bit Mode (Byte Register). - | R8L = 0x38 + | R8L = 0x8038 /// General-Purpose Registers for 64bit Mode (Byte Register). - | R9L = 0x39 + | R9L = 0x8039 /// General-Purpose Registers for 64bit Mode (Byte Register). - | R10L = 0x3A + | R10L = 0x803A /// General-Purpose Registers for 64bit Mode (Byte Register). - | R11L = 0x3B + | R11L = 0x803B /// General-Purpose Registers for 64bit Mode (Byte Register). - | R12L = 0x3C + | R12L = 0x803C /// General-Purpose Registers for 64bit Mode (Byte Register). - | R13L = 0x3D + | R13L = 0x803D /// General-Purpose Registers for 64bit Mode (Byte Register). - | R14L = 0x3E + | R14L = 0x803E /// General-Purpose Registers for 64bit Mode (Byte Register). - | R15L = 0x3F + | R15L = 0x803F /// General-Purpose Registers for 64bit Mode (Byte Register). - | SPL = 0x40 + | SPL = 0x8040 /// General-Purpose Registers for 64bit Mode (Byte Register). - | BPL = 0x41 + | BPL = 0x8041 /// General-Purpose Registers for 64bit Mode (Byte Register). - | SIL = 0x42 + | SIL = 0x8042 /// General-Purpose Registers for 64bit Mode (Byte Register). - | DIL = 0x43 + | DIL = 0x8043 /// Instruction Pointer (32Bit). - | EIP = 0x44 + | EIP = 0x20044 /// Instruction Pointer (64Bit). - | RIP = 0x45 + | RIP = 0x40045 /// x87 FPU registers. - | ST0 = 0x100 + | ST0 = 0x50100 /// x87 FPU registers. - | ST1 = 0x101 + | ST1 = 0x50101 /// x87 FPU registers. - | ST2 = 0x102 + | ST2 = 0x50102 /// x87 FPU registers. - | ST3 = 0x103 + | ST3 = 0x50103 /// x87 FPU registers. - | ST4 = 0x104 + | ST4 = 0x50104 /// x87 FPU registers. - | ST5 = 0x105 + | ST5 = 0x50105 /// x87 FPU registers. - | ST6 = 0x106 + | ST6 = 0x50106 /// x87 FPU registers. - | ST7 = 0x107 + | ST7 = 0x50107 /// C87 FPU Control Word. - | FCW = 0x108 + | FCW = 0x10108 /// x87 FPU Status Word. - | FSW = 0x109 + | FSW = 0x10109 /// x87 FPU Tag Word. - | FTW = 0x10A + | FTW = 0x1010A /// x87 FPU Opcode. - | FOP = 0x10B + | FOP = 0x1010B /// x87 FPU Instruction Pointer Offset. - | FIP = 0x10C + | FIP = 0x4010C /// x87 FPU Instruction Pointer Selector. - | FCS = 0x10D + | FCS = 0x1010D /// x87 FPU Data Pointer Offset. - | FDP = 0x10E + | FDP = 0x4010E /// x87 FPU Data Pointer Selector. - | FDS = 0x10F + | FDS = 0x1010F /// x87 FPU Top indicator bits of Status Word. - | FTOP = 0x110 + | FTOP = 0x2110 /// x87 FPU Tag word section. - | FTW0 = 0x111 + | FTW0 = 0x2111 /// x87 FPU Tag word section. - | FTW1 = 0x112 + | FTW1 = 0x2112 /// x87 FPU Tag word section. - | FTW2 = 0x113 + | FTW2 = 0x2113 /// x87 FPU Tag word section. - | FTW3 = 0x114 + | FTW3 = 0x2114 /// x87 FPU Tag word section. - | FTW4 = 0x115 + | FTW4 = 0x2115 /// x87 FPU Tag word section. - | FTW5 = 0x116 + | FTW5 = 0x2116 /// x87 FPU Tag word section. - | FTW6 = 0x117 + | FTW6 = 0x2117 /// x87 FPU Tag word section. - | FTW7 = 0x118 + | FTW7 = 0x2118 /// x87 FPU Status Word C flag. - | FSWC0 = 0x119 + | FSWC0 = 0x10119 /// x87 FPU Status Word C flag. - | FSWC1 = 0x11A + | FSWC1 = 0x411A /// x87 FPU Status Word C flag. - | FSWC2 = 0x11B + | FSWC2 = 0x411B /// x87 FPU Status Word C flag. - | FSWC3 = 0x11C + | FSWC3 = 0x411C /// MXCSR Control and Status Register. - | MXCSR = 0x11D + | MXCSR = 0x20411D /// MXCSR_MASK. - | MXCSRMASK = 0x11E + | MXCSRMASK = 0x2011E /// MMX registers. - | MM0 = 0x200 + | MM0 = 0x40200 /// MMX registers. - | MM1 = 0x201 + | MM1 = 0x40201 /// MMX registers. - | MM2 = 0x202 + | MM2 = 0x40202 /// MMX registers. - | MM3 = 0x203 + | MM3 = 0x40203 /// MMX registers. - | MM4 = 0x204 + | MM4 = 0x40204 /// MMX registers. - | MM5 = 0x205 + | MM5 = 0x40205 /// MMX registers. - | MM6 = 0x206 + | MM6 = 0x40206 /// MMX registers. - | MM7 = 0x207 + | MM7 = 0x40207 /// XMM registers. - | XMM0 = 0x30F + | XMM0 = 0x80300 /// XMM registers. - | XMM1 = 0x30E + | XMM1 = 0x80301 /// XMM registers. - | XMM2 = 0x30D + | XMM2 = 0x80302 /// XMM registers. - | XMM3 = 0x30C + | XMM3 = 0x80303 /// XMM registers. - | XMM4 = 0x30B + | XMM4 = 0x80304 /// XMM registers. - | XMM5 = 0x30A + | XMM5 = 0x80305 /// XMM registers. - | XMM6 = 0x309 + | XMM6 = 0x80306 /// XMM registers. - | XMM7 = 0x308 + | XMM7 = 0x80307 /// XMM registers. - | XMM8 = 0x307 + | XMM8 = 0x80308 /// XMM registers. - | XMM9 = 0x306 + | XMM9 = 0x80309 /// XMM registers. - | XMM10 = 0x305 + | XMM10 = 0x8030A /// XMM registers. - | XMM11 = 0x304 + | XMM11 = 0x8030B /// XMM registers. - | XMM12 = 0x303 + | XMM12 = 0x8030C /// XMM registers. - | XMM13 = 0x302 + | XMM13 = 0x8030D /// XMM registers. - | XMM14 = 0x301 + | XMM14 = 0x8030E /// XMM registers. - | XMM15 = 0x300 + | XMM15 = 0x8030F /// 256-bit vector registers. - | YMM0 = 0x40F + | YMM0 = 0x100400 /// 256-bit vector registers. - | YMM1 = 0x40E + | YMM1 = 0x100401 /// 256-bit vector registers. - | YMM2 = 0x40D + | YMM2 = 0x100402 /// 256-bit vector registers. - | YMM3 = 0x40C + | YMM3 = 0x100403 /// 256-bit vector registers. - | YMM4 = 0x40B + | YMM4 = 0x100404 /// 256-bit vector registers. - | YMM5 = 0x40A + | YMM5 = 0x100405 /// 256-bit vector registers. - | YMM6 = 0x409 + | YMM6 = 0x100406 /// 256-bit vector registers. - | YMM7 = 0x408 + | YMM7 = 0x100407 /// 256-bit vector registers. - | YMM8 = 0x407 + | YMM8 = 0x100408 /// 256-bit vector registers. - | YMM9 = 0x406 + | YMM9 = 0x100409 /// 256-bit vector registers. - | YMM10 = 0x405 + | YMM10 = 0x10040A /// 256-bit vector registers. - | YMM11 = 0x404 + | YMM11 = 0x10040B /// 256-bit vector registers. - | YMM12 = 0x403 + | YMM12 = 0x10040C /// 256-bit vector registers. - | YMM13 = 0x402 + | YMM13 = 0x10040D /// 256-bit vector registers. - | YMM14 = 0x401 + | YMM14 = 0x10040E /// 256-bit vector registers. - | YMM15 = 0x400 - /// 512-bit vector registers. - | ZMM0 = 0x50F + | YMM15 = 0x10040F /// 512-bit vector registers. - | ZMM1 = 0x50E + | ZMM0 = 0x200500 /// 512-bit vector registers. - | ZMM2 = 0x50D + | ZMM1 = 0x200501 /// 512-bit vector registers. - | ZMM3 = 0x50C + | ZMM2 = 0x200502 /// 512-bit vector registers. - | ZMM4 = 0x50B + | ZMM3 = 0x200503 /// 512-bit vector registers. - | ZMM5 = 0x50A + | ZMM4 = 0x200504 /// 512-bit vector registers. - | ZMM6 = 0x509 + | ZMM5 = 0x200505 /// 512-bit vector registers. - | ZMM7 = 0x508 + | ZMM6 = 0x200506 /// 512-bit vector registers. - | ZMM8 = 0x507 + | ZMM7 = 0x200507 /// 512-bit vector registers. - | ZMM9 = 0x506 + | ZMM8 = 0x200508 /// 512-bit vector registers. - | ZMM10 = 0x505 + | ZMM9 = 0x200509 /// 512-bit vector registers. - | ZMM11 = 0x504 + | ZMM10 = 0x20050A /// 512-bit vector registers. - | ZMM12 = 0x503 + | ZMM11 = 0x20050B /// 512-bit vector registers. - | ZMM13 = 0x502 + | ZMM12 = 0x20050C /// 512-bit vector registers. - | ZMM14 = 0x501 + | ZMM13 = 0x20050D /// 512-bit vector registers. - | ZMM15 = 0x500 + | ZMM14 = 0x20050E /// 512-bit vector registers. - | ES = 0x600 - /// 512-bit vector registers. - | CS = 0x601 + | ZMM15 = 0x20050F + /// Segment registers. + | ES = 0x10600 /// Segment registers. - | SS = 0x602 + | CS = 0x10601 /// Segment registers. - | DS = 0x603 + | SS = 0x10602 /// Segment registers. - | FS = 0x604 + | DS = 0x10603 /// Segment registers. - | GS = 0x605 + | FS = 0x10604 + /// Segment registers. + | GS = 0x10605 /// ES.base. | ESBase = 0x700 /// CS.base. @@ -388,15 +389,15 @@ type Register = /// ES.base. | GSBase = 0x705 /// Control registers. - | CR0 = 0x800 + | CR0 = 0x20800 /// Control registers. - | CR2 = 0x802 + | CR2 = 0x20802 /// Control registers. - | CR3 = 0x803 + | CR3 = 0x20803 /// Control registers. - | CR4 = 0x804 + | CR4 = 0x20804 /// Control registers. - | CR8 = 0x808 + | CR8 = 0x20808 /// Debug registers. | DR0 = 0x900 /// Debug registers. @@ -410,353 +411,353 @@ type Register = /// Debug registers. | DR7 = 0x907 /// BND registers. - | BND0 = 0xA00 + | BND0 = 0x80A00 /// BND registers. - | BND1 = 0xA01 + | BND1 = 0x80A01 /// BND registers. - | BND2 = 0xA02 + | BND2 = 0x80A02 /// BND registers. - | BND3 = 0xA03 + | BND3 = 0x80A03 /// Overflow Flag in EFLAGS Register - | OF = 0xB00 + | OF = 0x1B00 /// Direction Flag in EFLAGS Register - | DF = 0xB01 + | DF = 0x1B01 /// Interrupt Enable Flag in EFLAGS Register - | IF = 0xB02 + | IF = 0x1B02 /// Trap Flag in EFLAGS Register - | TF = 0xB03 + | TF = 0x1B03 /// Sign Flag in EFLAGS Register - | SF = 0xB04 + | SF = 0x1B04 /// Zero Flag in EFLAGS Register - | ZF = 0xB05 + | ZF = 0x1B05 /// Auxiliary Carry Flag in EFLAGS Register - | AF = 0xB06 + | AF = 0x1B06 /// Parity Flag in EFLAGS Register - | PF = 0xB07 + | PF = 0x1B07 /// Carry Flag in EFLAGS Register - | CF = 0xB08 + | CF = 0x1B08 /// Protection-key features register. - | PKRU = 0xC00 + | PKRU = 0x20C00 /// BND Register (lower 64bits BND0). - | BND0A = 0xD80 + | BND0A = 0x40D80 /// BND Register (Higher 64bits BND0). - | BND0B = 0xD81 + | BND0B = 0x40D81 /// BND Register (lower 64bits BND1). - | BND1A = 0xD82 + | BND1A = 0x40D82 /// BND Register (Higher 64bits BND1). - | BND1B = 0xD83 + | BND1B = 0x40D83 /// BND Register (lower 64bits BND2). - | BND2A = 0xD84 + | BND2A = 0x40D84 /// BND Register (Higher 64bits BND2). - | BND2B = 0xD85 + | BND2B = 0x40D85 /// BND Register (lower 64bits BND3). - | BND3A = 0xD86 + | BND3A = 0x40D86 /// BND Register (Higher 64bits BND3). - | BND3B = 0xD87 + | BND3B = 0x40D87 /// ST Register (lower 64bits ST0). - | ST0A = 0xD88 + | ST0A = 0x40D88 /// ST Register (Higher 16bits ST0). - | ST0B = 0xD89 + | ST0B = 0x10D89 /// ST Register (lower 64bits ST1). - | ST1A = 0xD8A + | ST1A = 0x40D8A /// ST Register (Higher 16bits ST1). - | ST1B = 0xD8B + | ST1B = 0x10D8B /// ST Register (lower 64bits ST2). - | ST2A = 0xD8C + | ST2A = 0x40D8C /// ST Register (Higher 16bits ST2). - | ST2B = 0xD8D + | ST2B = 0x10D8D /// ST Register (lower 64bits ST3). - | ST3A = 0xD8E + | ST3A = 0x40D8E /// ST Register (Higher 16bits ST3). - | ST3B = 0xD8F + | ST3B = 0x10D8F /// ST Register (lower 64bits ST4). - | ST4A = 0xD90 + | ST4A = 0x40D90 /// ST Register (Higher 16bits ST4). - | ST4B = 0xD91 + | ST4B = 0x10D91 /// ST Register (lower 64bits ST5). - | ST5A = 0xD92 + | ST5A = 0x40D92 /// ST Register (Higher 16bits ST5). - | ST5B = 0xD93 + | ST5B = 0x10D93 /// ST Register (lower 64bits ST6). - | ST6A = 0xD94 + | ST6A = 0x40D94 /// ST Register (Higher 16bits ST6). - | ST6B = 0xD95 + | ST6B = 0x10D95 /// ST Register (lower 64bits ST7). - | ST7A = 0xD96 + | ST7A = 0x40D96 /// ST Register (Higher 16bits ST7). - | ST7B = 0xD97 + | ST7B = 0x10D97 /// ZMM0A is the 1st 64-bit chunk of ZMM0. - | ZMM0A = 0xD00 + | ZMM0A = 0x40D00 /// ZMM0B is the 2nd 64-bit chunk of ZMM0. - | ZMM0B = 0xD01 + | ZMM0B = 0x40D01 /// ZMM0C is the 3rd 64-bit chunk of ZMM0. - | ZMM0C = 0xD02 + | ZMM0C = 0x40D02 /// ZMM0D is the 4th 64-bit chunk of ZMM0. - | ZMM0D = 0xD03 + | ZMM0D = 0x40D03 /// ZMM0E is the 5th 64-bit chunk of ZMM0. - | ZMM0E = 0xD04 + | ZMM0E = 0x40D04 /// ZMM0F is the 6th 64-bit chunk of ZMM0. - | ZMM0F = 0xD05 + | ZMM0F = 0x40D05 /// ZMM0G is the 7th 64-bit chunk of ZMM0. - | ZMM0G = 0xD06 + | ZMM0G = 0x40D06 /// ZMM0H is the 8th 64-bit chunk of ZMM0. - | ZMM0H = 0xD07 + | ZMM0H = 0x40D07 /// ZMM1A is the 1st 64-bit chunk of ZMM1. - | ZMM1A = 0xD08 + | ZMM1A = 0x40D08 /// ZMM1B is the 2nd 64-bit chunk of ZMM1. - | ZMM1B = 0xD09 + | ZMM1B = 0x40D09 /// ZMM1C is the 3rd 64-bit chunk of ZMM1. - | ZMM1C = 0xD0A + | ZMM1C = 0x40D0A /// ZMM1D is the 4th 64-bit chunk of ZMM1. - | ZMM1D = 0xD0B + | ZMM1D = 0x40D0B /// ZMM1E is the 5th 64-bit chunk of ZMM1. - | ZMM1E = 0xD0C + | ZMM1E = 0x40D0C /// ZMM1F is the 6th 64-bit chunk of ZMM1. - | ZMM1F = 0xD0D + | ZMM1F = 0x40D0D /// ZMM1G is the 7th 64-bit chunk of ZMM1. - | ZMM1G = 0xD0E + | ZMM1G = 0x40D0E /// ZMM1H is the 8th 64-bit chunk of ZMM1. - | ZMM1H = 0xD0F + | ZMM1H = 0x40D0F /// ZMM2A is the 1st 64-bit chunk of ZMM2. - | ZMM2A = 0xD10 + | ZMM2A = 0x40D10 /// ZMM2B is the 2nd 64-bit chunk of ZMM2. - | ZMM2B = 0xD11 + | ZMM2B = 0x40D11 /// ZMM2C is the 3rd 64-bit chunk of ZMM2. - | ZMM2C = 0xD12 + | ZMM2C = 0x40D12 /// ZMM2D is the 4th 64-bit chunk of ZMM2. - | ZMM2D = 0xD13 + | ZMM2D = 0x40D13 /// ZMM2E is the 5th 64-bit chunk of ZMM2. - | ZMM2E = 0xD14 + | ZMM2E = 0x40D14 /// ZMM2F is the 6th 64-bit chunk of ZMM2. - | ZMM2F = 0xD15 + | ZMM2F = 0x40D15 /// ZMM2G is the 7th 64-bit chunk of ZMM2. - | ZMM2G = 0xD16 + | ZMM2G = 0x40D16 /// ZMM2H is the 8th 64-bit chunk of ZMM2. - | ZMM2H = 0xD17 + | ZMM2H = 0x40D17 /// ZMM3A is the 1st 64-bit chunk of ZMM3. - | ZMM3A = 0xD18 + | ZMM3A = 0x40D18 /// ZMM3B is the 2nd 64-bit chunk of ZMM3. - | ZMM3B = 0xD19 + | ZMM3B = 0x40D19 /// ZMM3C is the 3rd 64-bit chunk of ZMM3. - | ZMM3C = 0xD1A + | ZMM3C = 0x40D1A /// ZMM3D is the 4th 64-bit chunk of ZMM3. - | ZMM3D = 0xD1B + | ZMM3D = 0x40D1B /// ZMM3E is the 5th 64-bit chunk of ZMM3. - | ZMM3E = 0xD1C + | ZMM3E = 0x40D1C /// ZMM3F is the 6th 64-bit chunk of ZMM3. - | ZMM3F = 0xD1D + | ZMM3F = 0x40D1D /// ZMM3G is the 7th 64-bit chunk of ZMM3. - | ZMM3G = 0xD1E + | ZMM3G = 0x40D1E /// ZMM3H is the 8th 64-bit chunk of ZMM3. - | ZMM3H = 0xD1F + | ZMM3H = 0x40D1F /// ZMM4A is the 1st 64-bit chunk of ZMM4. - | ZMM4A = 0xD20 + | ZMM4A = 0x40D20 /// ZMM4B is the 2nd 64-bit chunk of ZMM4. - | ZMM4B = 0xD21 + | ZMM4B = 0x40D21 /// ZMM4C is the 3rd 64-bit chunk of ZMM4. - | ZMM4C = 0xD22 + | ZMM4C = 0x40D22 /// ZMM4D is the 4th 64-bit chunk of ZMM4. - | ZMM4D = 0xD23 + | ZMM4D = 0x40D23 /// ZMM4E is the 5th 64-bit chunk of ZMM4. - | ZMM4E = 0xD24 + | ZMM4E = 0x40D24 /// ZMM4F is the 6th 64-bit chunk of ZMM4. - | ZMM4F = 0xD25 + | ZMM4F = 0x40D25 /// ZMM4G is the 7th 64-bit chunk of ZMM4. - | ZMM4G = 0xD26 + | ZMM4G = 0x40D26 /// ZMM4H is the 8th 64-bit chunk of ZMM4. - | ZMM4H = 0xD27 + | ZMM4H = 0x40D27 /// ZMM5A is the 1st 64-bit chunk of ZMM5. - | ZMM5A = 0xD28 + | ZMM5A = 0x40D28 /// ZMM5B is the 2nd 64-bit chunk of ZMM5. - | ZMM5B = 0xD29 + | ZMM5B = 0x40D29 /// ZMM5C is the 3rd 64-bit chunk of ZMM5. - | ZMM5C = 0xD2A + | ZMM5C = 0x40D2A /// ZMM5D is the 4th 64-bit chunk of ZMM5. - | ZMM5D = 0xD2B + | ZMM5D = 0x40D2B /// ZMM5E is the 5th 64-bit chunk of ZMM5. - | ZMM5E = 0xD2C + | ZMM5E = 0x40D2C /// ZMM5F is the 6th 64-bit chunk of ZMM5. - | ZMM5F = 0xD2D + | ZMM5F = 0x40D2D /// ZMM5G is the 7th 64-bit chunk of ZMM5. - | ZMM5G = 0xD2E + | ZMM5G = 0x40D2E /// ZMM5H is the 8th 64-bit chunk of ZMM5. - | ZMM5H = 0xD2F + | ZMM5H = 0x40D2F /// ZMM6A is the 1st 64-bit chunk of ZMM6. - | ZMM6A = 0xD30 + | ZMM6A = 0x40D30 /// ZMM6B is the 2nd 64-bit chunk of ZMM6. - | ZMM6B = 0xD31 + | ZMM6B = 0x40D31 /// ZMM6C is the 3rd 64-bit chunk of ZMM6. - | ZMM6C = 0xD32 + | ZMM6C = 0x40D32 /// ZMM6D is the 4th 64-bit chunk of ZMM6. - | ZMM6D = 0xD33 + | ZMM6D = 0x40D33 /// ZMM6E is the 5th 64-bit chunk of ZMM6. - | ZMM6E = 0xD34 + | ZMM6E = 0x40D34 /// ZMM6F is the 6th 64-bit chunk of ZMM6. - | ZMM6F = 0xD35 + | ZMM6F = 0x40D35 /// ZMM6G is the 7th 64-bit chunk of ZMM6. - | ZMM6G = 0xD36 + | ZMM6G = 0x40D36 /// ZMM6H is the 8th 64-bit chunk of ZMM6. - | ZMM6H = 0xD37 + | ZMM6H = 0x40D37 /// ZMM7A is the 1st 64-bit chunk of ZMM7. - | ZMM7A = 0xD38 + | ZMM7A = 0x40D38 /// ZMM7B is the 2nd 64-bit chunk of ZMM7. - | ZMM7B = 0xD39 + | ZMM7B = 0x40D39 /// ZMM7C is the 3rd 64-bit chunk of ZMM7. - | ZMM7C = 0xD3A + | ZMM7C = 0x40D3A /// ZMM7D is the 4th 64-bit chunk of ZMM7. - | ZMM7D = 0xD3B + | ZMM7D = 0x40D3B /// ZMM7E is the 5th 64-bit chunk of ZMM7. - | ZMM7E = 0xD3C + | ZMM7E = 0x40D3C /// ZMM7F is the 6th 64-bit chunk of ZMM7. - | ZMM7F = 0xD3D + | ZMM7F = 0x40D3D /// ZMM7G is the 7th 64-bit chunk of ZMM7. - | ZMM7G = 0xD3E + | ZMM7G = 0x40D3E /// ZMM7H is the 8th 64-bit chunk of ZMM7. - | ZMM7H = 0xD3F + | ZMM7H = 0x40D3F /// ZMM8A is the 1st 64-bit chunk of ZMM8. - | ZMM8A = 0xD40 + | ZMM8A = 0x40D40 /// ZMM8B is the 2nd 64-bit chunk of ZMM8. - | ZMM8B = 0xD41 + | ZMM8B = 0x40D41 /// ZMM8C is the 3rd 64-bit chunk of ZMM8. - | ZMM8C = 0xD42 + | ZMM8C = 0x40D42 /// ZMM8D is the 4th 64-bit chunk of ZMM8. - | ZMM8D = 0xD43 + | ZMM8D = 0x40D43 /// ZMM8E is the 5th 64-bit chunk of ZMM8. - | ZMM8E = 0xD44 + | ZMM8E = 0x40D44 /// ZMM8F is the 6th 64-bit chunk of ZMM8. - | ZMM8F = 0xD45 + | ZMM8F = 0x40D45 /// ZMM8G is the 7th 64-bit chunk of ZMM8. - | ZMM8G = 0xD46 + | ZMM8G = 0x40D46 /// ZMM8H is the 8th 64-bit chunk of ZMM8. - | ZMM8H = 0xD47 + | ZMM8H = 0x40D47 /// ZMM9A is the 1st 64-bit chunk of ZMM9. - | ZMM9A = 0xD48 + | ZMM9A = 0x40D48 /// ZMM9B is the 2nd 64-bit chunk of ZMM9. - | ZMM9B = 0xD49 + | ZMM9B = 0x40D49 /// ZMM9C is the 3rd 64-bit chunk of ZMM9. - | ZMM9C = 0xD4A + | ZMM9C = 0x40D4A /// ZMM9D is the 4th 64-bit chunk of ZMM9. - | ZMM9D = 0xD4B + | ZMM9D = 0x40D4B /// ZMM9E is the 5th 64-bit chunk of ZMM9. - | ZMM9E = 0xD4C + | ZMM9E = 0x40D4C /// ZMM9F is the 6th 64-bit chunk of ZMM9. - | ZMM9F = 0xD4D + | ZMM9F = 0x40D4D /// ZMM9G is the 7th 64-bit chunk of ZMM9. - | ZMM9G = 0xD4E + | ZMM9G = 0x40D4E /// ZMM9H is the 8th 64-bit chunk of ZMM9. - | ZMM9H = 0xD4F + | ZMM9H = 0x40D4F /// ZMM10A is the 1st 64-bit chunk of ZMM10. - | ZMM10A = 0xD50 + | ZMM10A = 0x40D50 /// ZMM10B is the 2nd 64-bit chunk of ZMM10. - | ZMM10B = 0xD51 + | ZMM10B = 0x40D51 /// ZMM10C is the 3rd 64-bit chunk of ZMM10. - | ZMM10C = 0xD52 + | ZMM10C = 0x40D52 /// ZMM10D is the 4th 64-bit chunk of ZMM10. - | ZMM10D = 0xD53 + | ZMM10D = 0x40D53 /// ZMM10E is the 5th 64-bit chunk of ZMM10. - | ZMM10E = 0xD54 + | ZMM10E = 0x40D54 /// ZMM10F is the 6th 64-bit chunk of ZMM10. - | ZMM10F = 0xD55 + | ZMM10F = 0x40D55 /// ZMM10G is the 7th 64-bit chunk of ZMM10. - | ZMM10G = 0xD56 + | ZMM10G = 0x40D56 /// ZMM10H is the 8th 64-bit chunk of ZMM10. - | ZMM10H = 0xD57 + | ZMM10H = 0x40D57 /// ZMM11A is the 1st 64-bit chunk of ZMM11. - | ZMM11A = 0xD58 + | ZMM11A = 0x40D58 /// ZMM11B is the 2nd 64-bit chunk of ZMM11. - | ZMM11B = 0xD59 + | ZMM11B = 0x40D59 /// ZMM11C is the 3rd 64-bit chunk of ZMM11. - | ZMM11C = 0xD5A + | ZMM11C = 0x40D5A /// ZMM11D is the 4th 64-bit chunk of ZMM11. - | ZMM11D = 0xD5B + | ZMM11D = 0x40D5B /// ZMM11E is the 5th 64-bit chunk of ZMM11. - | ZMM11E = 0xD5C + | ZMM11E = 0x40D5C /// ZMM11F is the 6th 64-bit chunk of ZMM11. - | ZMM11F = 0xD5D + | ZMM11F = 0x40D5D /// ZMM11G is the 7th 64-bit chunk of ZMM11. - | ZMM11G = 0xD5E + | ZMM11G = 0x40D5E /// ZMM11H is the 8th 64-bit chunk of ZMM11. - | ZMM11H = 0xD5F + | ZMM11H = 0x40D5F /// ZMM12A is the 1st 64-bit chunk of ZMM12. - | ZMM12A = 0xD60 + | ZMM12A = 0x40D60 /// ZMM12B is the 2nd 64-bit chunk of ZMM12. - | ZMM12B = 0xD61 + | ZMM12B = 0x40D61 /// ZMM12C is the 3rd 64-bit chunk of ZMM12. - | ZMM12C = 0xD62 + | ZMM12C = 0x40D62 /// ZMM12D is the 4th 64-bit chunk of ZMM12. - | ZMM12D = 0xD63 + | ZMM12D = 0x40D63 /// ZMM12E is the 5th 64-bit chunk of ZMM12. - | ZMM12E = 0xD64 + | ZMM12E = 0x40D64 /// ZMM12F is the 6th 64-bit chunk of ZMM12. - | ZMM12F = 0xD65 + | ZMM12F = 0x40D65 /// ZMM12G is the 7th 64-bit chunk of ZMM12. - | ZMM12G = 0xD66 + | ZMM12G = 0x40D66 /// ZMM12H is the 8th 64-bit chunk of ZMM12. - | ZMM12H = 0xD67 + | ZMM12H = 0x40D67 /// ZMM13A is the 1st 64-bit chunk of ZMM13. - | ZMM13A = 0xD68 + | ZMM13A = 0x40D68 /// ZMM13B is the 2nd 64-bit chunk of ZMM13. - | ZMM13B = 0xD69 + | ZMM13B = 0x40D69 /// ZMM13C is the 3rd 64-bit chunk of ZMM13. - | ZMM13C = 0xD6A + | ZMM13C = 0x40D6A /// ZMM13D is the 4th 64-bit chunk of ZMM13. - | ZMM13D = 0xD6B + | ZMM13D = 0x40D6B /// ZMM13E is the 5th 64-bit chunk of ZMM13. - | ZMM13E = 0xD6C + | ZMM13E = 0x40D6C /// ZMM13F is the 6th 64-bit chunk of ZMM13. - | ZMM13F = 0xD6D + | ZMM13F = 0x40D6D /// ZMM13G is the 7th 64-bit chunk of ZMM13. - | ZMM13G = 0xD6E + | ZMM13G = 0x40D6E /// ZMM13H is the 8th 64-bit chunk of ZMM13. - | ZMM13H = 0xD6F + | ZMM13H = 0x40D6F /// ZMM14A is the 1st 64-bit chunk of ZMM14. - | ZMM14A = 0xD70 + | ZMM14A = 0x40D70 /// ZMM14B is the 2nd 64-bit chunk of ZMM14. - | ZMM14B = 0xD71 + | ZMM14B = 0x40D71 /// ZMM14C is the 3rd 64-bit chunk of ZMM14. - | ZMM14C = 0xD72 + | ZMM14C = 0x40D72 /// ZMM14D is the 4th 64-bit chunk of ZMM14. - | ZMM14D = 0xD73 + | ZMM14D = 0x40D73 /// ZMM14E is the 5th 64-bit chunk of ZMM14. - | ZMM14E = 0xD74 + | ZMM14E = 0x40D74 /// ZMM14F is the 6th 64-bit chunk of ZMM14. - | ZMM14F = 0xD75 + | ZMM14F = 0x40D75 /// ZMM14G is the 7th 64-bit chunk of ZMM14. - | ZMM14G = 0xD76 + | ZMM14G = 0x40D76 /// ZMM14H is the 8th 64-bit chunk of ZMM14. - | ZMM14H = 0xD77 + | ZMM14H = 0x40D77 /// ZMM15A is the 1st 64-bit chunk of ZMM15. - | ZMM15A = 0xD78 + | ZMM15A = 0x40D78 /// ZMM15B is the 2nd 64-bit chunk of ZMM15. - | ZMM15B = 0xD79 + | ZMM15B = 0x40D79 /// ZMM15C is the 3rd 64-bit chunk of ZMM15. - | ZMM15C = 0xD7A + | ZMM15C = 0x40D7A /// ZMM15D is the 4th 64-bit chunk of ZMM15. - | ZMM15D = 0xD7B + | ZMM15D = 0x40D7B /// ZMM15E is the 5th 64-bit chunk of ZMM15. - | ZMM15E = 0xD7C + | ZMM15E = 0x40D7C /// ZMM15F is the 6th 64-bit chunk of ZMM15. - | ZMM15F = 0xD7D + | ZMM15F = 0x40D7D /// ZMM15G is the 7th 64-bit chunk of ZMM15. - | ZMM15G = 0xD7E + | ZMM15G = 0x40D7E /// ZMM15H is the 8th 64-bit chunk of ZMM15. - | ZMM15H = 0xD7F + | ZMM15H = 0x40D7F /// Opmask registers. For EVEX. - | K0 = 0xE00 + | K0 = 0x40E00 /// Opmask registers. For EVEX. - | K1 = 0xE01 + | K1 = 0x40E01 /// Opmask registers. For EVEX. - | K2 = 0xE02 + | K2 = 0x40E02 /// Opmask registers. For EVEX. - | K3 = 0xE03 + | K3 = 0x40E03 /// Opmask registers. For EVEX. - | K4 = 0xE04 + | K4 = 0x40E04 /// Opmask registers. For EVEX. - | K5 = 0xE05 + | K5 = 0x40E05 /// Opmask registers. For EVEX. - | K6 = 0xE06 + | K6 = 0x40E06 /// Opmask registers. For EVEX. - | K7 = 0xE07 + | K7 = 0x40E07 /// Unknown Register. | UnknownReg = 0xF00 @@ -800,12 +801,15 @@ module Register = begin /// character from 'A' to 'H'. For example, XMM0A refers to the first 64-bit /// chunk of XMM0. | PseudoRegister = 0xD + /// OpMask registers of EVEX. + | OpMaskRegister = 0xE let getKind (reg: Register): Kind = (int reg >>> 8) &&& 0b1111 |> LanguagePrimitives.EnumOfValue - let make id (kind: Kind): Register = - (int kind <<< 8) ||| id |> LanguagePrimitives.EnumOfValue + let make id (kind: Kind) size = + (size <<< 12) ||| (int kind <<< 8) ||| id + |> LanguagePrimitives.EnumOfValue let inline ofRegID (n: RegisterID): Register = int n |> LanguagePrimitives.EnumOfValue @@ -813,6 +817,9 @@ module Register = begin let inline toRegID (reg: Register) = LanguagePrimitives.EnumToValue (reg) |> RegisterID.create + let inline getSize (reg: Register) = + int reg >>> 12 |> RegType.fromBitWidth + let ofString (str: string) = match str.ToLower () with | "rax" -> R.RAX @@ -1169,7 +1176,7 @@ module Register = begin | "k5" -> R.K5 | "k6" -> R.K6 | "k7" -> R.K7 - | _ -> failwith "Invalid reg" + | _ -> Utils.impossible () let toString = function | R.RAX -> "RAX" @@ -1517,7 +1524,12 @@ module Register = begin | R.K5 -> "K5" | R.K6 -> "K6" | R.K7 -> "K7" - | _ -> "UnknownReg" + | R.PKRU -> "PKRU" +#if DEBUG + | _ -> Utils.impossible () +#else + | _ -> "?" +#endif let toRegType = function | R.MM0 | R.MM1 | R.MM2 | R.MM3 | R.MM4 | R.MM5 | R.MM6 | R.MM7 @@ -1728,30 +1740,191 @@ module Register = begin | R.MM6 -> [ R.ST6A ] | R.MM7 -> [ R.ST7A ] | e -> failwithf "Unhandled register: %A" e + + let pseudoRegToReg = function + | R.ZMM0A + | R.ZMM0B + | R.ZMM0C + | R.ZMM0D + | R.ZMM0E + | R.ZMM0F + | R.ZMM0G + | R.ZMM0H -> R.ZMM0 + | R.ZMM1A + | R.ZMM1B + | R.ZMM1C + | R.ZMM1D + | R.ZMM1E + | R.ZMM1F + | R.ZMM1G + | R.ZMM1H -> R.ZMM1 + | R.ZMM2A + | R.ZMM2B + | R.ZMM2C + | R.ZMM2D + | R.ZMM2E + | R.ZMM2F + | R.ZMM2G + | R.ZMM2H -> R.ZMM2 + | R.ZMM3A + | R.ZMM3B + | R.ZMM3C + | R.ZMM3D + | R.ZMM3E + | R.ZMM3F + | R.ZMM3G + | R.ZMM3H -> R.ZMM3 + | R.ZMM4A + | R.ZMM4B + | R.ZMM4C + | R.ZMM4D + | R.ZMM4E + | R.ZMM4F + | R.ZMM4G + | R.ZMM4H -> R.ZMM4 + | R.ZMM5A + | R.ZMM5B + | R.ZMM5C + | R.ZMM5D + | R.ZMM5E + | R.ZMM5F + | R.ZMM5G + | R.ZMM5H -> R.ZMM5 + | R.ZMM6A + | R.ZMM6B + | R.ZMM6C + | R.ZMM6D + | R.ZMM6E + | R.ZMM6F + | R.ZMM6G + | R.ZMM6H -> R.ZMM6 + | R.ZMM7A + | R.ZMM7B + | R.ZMM7C + | R.ZMM7D + | R.ZMM7E + | R.ZMM7F + | R.ZMM7G + | R.ZMM7H -> R.ZMM7 + | R.ZMM8A + | R.ZMM8B + | R.ZMM8C + | R.ZMM8D + | R.ZMM8E + | R.ZMM8F + | R.ZMM8G + | R.ZMM8H -> R.ZMM8 + | R.ZMM9A + | R.ZMM9B + | R.ZMM9C + | R.ZMM9D + | R.ZMM9E + | R.ZMM9F + | R.ZMM9G + | R.ZMM9H -> R.ZMM9 + | R.ZMM10A + | R.ZMM10B + | R.ZMM10C + | R.ZMM10D + | R.ZMM10E + | R.ZMM10F + | R.ZMM10G + | R.ZMM10H -> R.ZMM10 + | R.ZMM11A + | R.ZMM11B + | R.ZMM11C + | R.ZMM11D + | R.ZMM11E + | R.ZMM11F + | R.ZMM11G + | R.ZMM11H -> R.ZMM11 + | R.ZMM12A + | R.ZMM12B + | R.ZMM12C + | R.ZMM12D + | R.ZMM12E + | R.ZMM12F + | R.ZMM12G + | R.ZMM12H -> R.ZMM12 + | R.ZMM13A + | R.ZMM13B + | R.ZMM13C + | R.ZMM13D + | R.ZMM13E + | R.ZMM13F + | R.ZMM13G + | R.ZMM13H -> R.ZMM13 + | R.ZMM14A + | R.ZMM14B + | R.ZMM14C + | R.ZMM14D + | R.ZMM14E + | R.ZMM14F + | R.ZMM14G + | R.ZMM14H -> R.ZMM14 + | R.ZMM15A + | R.ZMM15B + | R.ZMM15C + | R.ZMM15D + | R.ZMM15E + | R.ZMM15F + | R.ZMM15G + | R.ZMM15H -> R.ZMM15 + | R.ST0A | R.ST0B -> R.ST0 + | R.ST1A | R.ST1B -> R.ST1 + | R.ST2A | R.ST2B -> R.ST2 + | R.ST3A | R.ST3B -> R.ST3 + | R.ST4A | R.ST4B -> R.ST4 + | R.ST5A | R.ST5B -> R.ST5 + | R.ST6A | R.ST6B -> R.ST6 + | R.ST7A | R.ST7B -> R.ST7 + | e -> failwithf "Unhandled register: %A" e end /// This module defines sets of registers that are frequently grouped by Intel. +/// Table 3-1. Register Codes Associated With +rb, +rw, +rd, +ro module internal RegGroup = begin - let GrpEAX = [| R.AL; R.AX; R.EAX; R.RAX; R.XMM0; R.YMM0; R.ZMM0 |] (* Grp0 *) - let GrpECX = [| R.CL; R.CX; R.ECX; R.RCX; R.XMM1; R.YMM1; R.ZMM1 |] (* Grp1 *) - let GrpEDX = [| R.DL; R.DX; R.EDX; R.RDX; R.XMM2; R.YMM2; R.ZMM2 |] (* Grp2 *) - let GrpEBX = [| R.BL; R.BX; R.EBX; R.RBX; R.XMM3; R.YMM3; R.ZMM3 |] (* Grp3 *) - let GrpAH = [| R.AH; R.SP; R.ESP; R.RSP; R.XMM4; R.YMM4; R.ZMM4 |] (* Grp4 *) - let GrpCH = [| R.CH; R.BP; R.EBP; R.RBP; R.XMM5; R.YMM5; R.ZMM5 |] (* Grp5 *) - let GrpDH = [| R.DH; R.SI; R.ESI; R.RSI; R.XMM6; R.YMM6; R.ZMM6 |] (* Grp6 *) - let GrpBH = [| R.BH; R.DI; R.EDI; R.RDI; R.XMM7; R.YMM7; R.ZMM7 |] (* Grp7 *) + /// Grp 0. + let grpEAX = function + | 64 -> R.RAX + | 32 -> R.EAX + | 16 -> R.AX + | 8 -> R.AL + | 128 -> R.XMM0 + | 256 -> R.YMM0 + | 512 -> R.ZMM0 + | _ -> Utils.impossible () + + /// Grp 1. + let grpECX = function + | 64 -> R.RCX + | 32 -> R.ECX + | 16 -> R.CX + | 8 -> R.CL + | 128 -> R.XMM1 + | 256 -> R.YMM1 + | 512 -> R.ZMM1 + | _ -> Utils.impossible () - let GrpESP = [| R.SPL; R.SP; R.ESP; R.RSP; R.XMM4; R.YMM4; R.ZMM4 |] - let GrpEBP = [| R.BPL; R.BP; R.EBP; R.RBP; R.XMM5; R.YMM5; R.ZMM5 |] - let GrpESI = [| R.SIL; R.SI; R.ESI; R.RSI; R.XMM6; R.YMM6; R.ZMM6 |] - let GrpEDI = [| R.DIL; R.DI; R.EDI; R.RDI; R.XMM7; R.YMM7; R.ZMM7 |] + /// Grp 2. + let grpEDX = function + | 64 -> R.RDX + | 32 -> R.EDX + | 16 -> R.DX + | 8 -> R.DL + | 128 -> R.XMM2 + | 256 -> R.YMM2 + | 512 -> R.ZMM2 + | _ -> Utils.impossible () - let GrpR8 = [| R.R8L; R.R8W; R.R8D; R.R8; R.XMM8; R.YMM8; R.ZMM8 |] - let GrpR9 = [| R.R9L; R.R9W; R.R9D; R.R9; R.XMM9; R.YMM9; R.ZMM9 |] - let GrpR10 = [| R.R10L; R.R10W; R.R10D; R.R10; R.XMM10; R.YMM10; R.ZMM10 |] - let GrpR11 = [| R.R11L; R.R11W; R.R11D; R.R11; R.XMM11; R.YMM11; R.ZMM11 |] - let GrpR12 = [| R.R12L; R.R12W; R.R12D; R.R12; R.XMM12; R.YMM12; R.ZMM12 |] - let GrpR13 = [| R.R13L; R.R13W; R.R13D; R.R13; R.XMM13; R.YMM13; R.ZMM13 |] - let GrpR14 = [| R.R14L; R.R14W; R.R14D; R.R14; R.XMM14; R.YMM14; R.ZMM14 |] - let GrpR15 = [| R.R15L; R.R15W; R.R15D; R.R15; R.XMM15; R.YMM15; R.ZMM15 |] + /// Grp 3. + let grpEBX = function + | 64 -> R.RBX + | 32 -> R.EBX + | 16 -> R.BX + | 8 -> R.BL + | 128 -> R.XMM3 + | 256 -> R.YMM3 + | 512 -> R.ZMM3 + | _ -> Utils.impossible () end diff --git a/src/FrontEnd/BinLifter/Intel/IntelRegisterBay.fs b/src/FrontEnd/BinLifter/Intel/IntelRegisterBay.fs new file mode 100644 index 00000000..100a82ea --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelRegisterBay.fs @@ -0,0 +1,430 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.Intel + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR.LowUIR + +type IntelRegisterBay internal (wordSize, R: RegExprs) = + + inherit RegisterBay () + + override __.GetAllRegExprs () = + if WordSize.is32 wordSize then + [ R.EAX; R.EBX; R.ECX; R.EDX; R.ESP; R.EBP; R.ESI; R.EDI; R.EIP; R.CSBase; + R.DSBase; R.ESBase; R.FSBase; R.GSBase; R.SSBase; R.CR0; R.CR2; R.CR3; + R.CR4; R.OF; R.DF; R.IF; R.TF; R.SF; R.ZF; R.AF; R.PF; R.CF; R.FCW; + R.FSW; R.FTW; R.FOP; R.FIP; R.FCS; R.FDP; R.FDS; R.MXCSR; R.MXCSRMASK; + R.PKRU; R.K0; R.K1; R.K2; R.K3; R.K4; R.K5; R.K6; R.K7; R.ST0A; R.ST0B; + R.ST1A; R.ST1B; R.ST2A; R.ST2B; R.ST3A; R.ST3B; R.ST4A; R.ST4B; R.ST5A; + R.ST5B; R.ST6A; R.ST6B; R.ST7A; R.ST7B; R.ZMM0A; R.ZMM0B; R.ZMM0C; + R.ZMM0D; R.ZMM0E; R.ZMM0F; R.ZMM0G; R.ZMM0H; R.ZMM1A; R.ZMM1B; R.ZMM1C; + R.ZMM1D; R.ZMM1E; R.ZMM1F; R.ZMM1G; R.ZMM1H; R.ZMM2A; R.ZMM2B; R.ZMM2C; + R.ZMM2D; R.ZMM2E; R.ZMM2F; R.ZMM2G; R.ZMM2H; R.ZMM3A; R.ZMM3B; R.ZMM3C; + R.ZMM3D; R.ZMM3E; R.ZMM3F; R.ZMM3G; R.ZMM3H; R.ZMM4A; R.ZMM4B; R.ZMM4C; + R.ZMM4D; R.ZMM4E; R.ZMM4F; R.ZMM4G; R.ZMM4H; R.ZMM5A; R.ZMM5B; R.ZMM5C; + R.ZMM5D; R.ZMM5E; R.ZMM5F; R.ZMM5G; R.ZMM5H; R.ZMM6A; R.ZMM6B; R.ZMM6C; + R.ZMM6D; R.ZMM6E; R.ZMM6F; R.ZMM6G; R.ZMM6H; R.ZMM7A; R.ZMM7B; R.ZMM7C; + R.ZMM7D; R.ZMM7E; R.ZMM7F; R.ZMM7G; R.ZMM7H; R.CS; R.DS; R.ES; R.FS; + R.GS; R.SS; R.DR0; R.DR1; R.DR2; R.DR3; R.DR6; R.DR7 ] + else + [ R.RAX; R.RBX; R.RCX; R.RDX; R.RSP; R.RBP; R.RSI; R.RDI; R.R8; R.R9; + R.R10; R.R11; R.R12; R.R13; R.R14; R.R15; R.RIP; R.CSBase; R.DSBase; + R.ESBase; R.FSBase; R.GSBase; R.SSBase; R.CR0;R.CR2; R.CR3; R.CR4; + R.CR8; R.OF; R.DF; R.IF; R.TF; R.SF; R.ZF; R.AF; R.PF; R.CF; R.FCW; + R.FSW; R.FTW; R.FOP; R.FIP; R.FCS; R.FDP; R.FDS; R.MXCSR; R.MXCSRMASK; + R.PKRU; R.K0; R.K1; R.K2; R.K3; R.K4; R.K5; R.K6; R.K7; R.ST0A; R.ST0B; + R.ST1A; R.ST1B; R.ST2A; R.ST2B; R.ST3A; R.ST3B; R.ST4A; R.ST4B; R.ST5A; + R.ST5B; R.ST6A; R.ST6B; R.ST7A; R.ST7B; R.ZMM0A; R.ZMM0B; R.ZMM0C; + R.ZMM0D; R.ZMM0E; R.ZMM0F; R.ZMM0G; R.ZMM0H; R.ZMM1A; R.ZMM1B; R.ZMM1C; + R.ZMM1D; R.ZMM1E; R.ZMM1F; R.ZMM1G; R.ZMM1H; R.ZMM2A; R.ZMM2B; R.ZMM2C; + R.ZMM2D; R.ZMM2E; R.ZMM2F; R.ZMM2G; R.ZMM2H; R.ZMM3A; R.ZMM3B; R.ZMM3C; + R.ZMM3D; R.ZMM3E; R.ZMM3F; R.ZMM3G; R.ZMM3H; R.ZMM4A; R.ZMM4B; R.ZMM4C; + R.ZMM4D; R.ZMM4E; R.ZMM4F; R.ZMM4G; R.ZMM4H; R.ZMM5A; R.ZMM5B; R.ZMM5C; + R.ZMM5D; R.ZMM5E; R.ZMM5F; R.ZMM5G; R.ZMM5H; R.ZMM6A; R.ZMM6B; R.ZMM6C; + R.ZMM6D; R.ZMM6E; R.ZMM6F; R.ZMM6G; R.ZMM6H; R.ZMM7A; R.ZMM7B; R.ZMM7C; + R.ZMM7D; R.ZMM7E; R.ZMM7F; R.ZMM7G; R.ZMM7H; R.ZMM8A; R.ZMM8B; R.ZMM8C; + R.ZMM8D; R.ZMM8E; R.ZMM8F; R.ZMM8G; R.ZMM8H; R.ZMM9A; R.ZMM9B; R.ZMM9C; + R.ZMM9D; R.ZMM9E; R.ZMM9F; R.ZMM9G; R.ZMM9H; R.ZMM10A; R.ZMM10B; + R.ZMM10C; R.ZMM10D; R.ZMM10E; R.ZMM10F; R.ZMM10G; R.ZMM10H; R.ZMM11A; + R.ZMM11B; R.ZMM11C; R.ZMM11D; R.ZMM11E; R.ZMM11F; R.ZMM11G; R.ZMM11H; + R.ZMM12A; R.ZMM12B; R.ZMM12C; R.ZMM12D; R.ZMM12E; R.ZMM12F; R.ZMM12G; + R.ZMM12H; R.ZMM13A; R.ZMM13B; R.ZMM13C; R.ZMM13D; R.ZMM13E; R.ZMM13F; + R.ZMM13G; R.ZMM13H; R.ZMM14A; R.ZMM14B; R.ZMM14C; R.ZMM14D; R.ZMM14E; + R.ZMM14F; R.ZMM14G; R.ZMM14H; R.ZMM15A; R.ZMM15B; R.ZMM15C; R.ZMM15D; + R.ZMM15E; R.ZMM15F; R.ZMM15G; R.ZMM15H; R.CS; R.DS; R.ES; R.FS; R.GS; + R.SS; R.DR0; R.DR1; R.DR2; R.DR3; R.DR6; R.DR7 ] + + override __.GetAllRegNames () = + __.GetAllRegExprs () + |> List.map (__.RegIDFromRegExpr >> __.RegIDToString) + + override __.GetGeneralRegExprs () = + if WordSize.is32 wordSize then + [ R.EAX; R.EBX; R.ECX; R.EDX; R.ESP; R.EBP; R.ESI; R.EDI; R.EIP + R.OF; R.DF; R.IF; R.SF; R.ZF; R.AF; R.PF; R.CF ] + else + [ R.RAX; R.RBX; R.RCX; R.RDX; R.RSP; R.RBP; R.RSI; R.RDI; R.R8; R.R9 + R.R10; R.R11; R.R12; R.R13; R.R14; R.R15; R.RIP + R.OF; R.DF; R.IF; R.SF; R.ZF; R.AF; R.PF; R.CF ] + + override __.RegIDFromRegExpr (e) = + match e.E with + | Var (_,id, _,_) -> id + | PCVar (regT, _) -> + if regT = 32 then Register.toRegID Register.EIP + else Register.toRegID Register.RIP + | _ -> failwith "not a register expression" + + override __.RegIDToRegExpr (id) = + Register.ofRegID id |> R.GetRegVar + + override __.StrToRegExpr (s: string) = + match s.ToUpper () with + | "RAX" -> R.RAX + | "RBX" -> R.RBX + | "RCX" -> R.RCX + | "RDX" -> R.RDX + | "RSP" -> R.RSP + | "RBP" -> R.RBP + | "RSI" -> R.RSI + | "RDI" -> R.RDI + | "EAX" -> R.EAX + | "EBX" -> R.EBX + | "ECX" -> R.ECX + | "EDX" -> R.EDX + | "ESP" -> R.ESP + | "EBP" -> R.EBP + | "ESI" -> R.ESI + | "EDI" -> R.EDI + | "AX" -> R.AX + | "BX" -> R.BX + | "CX" -> R.CX + | "DX" -> R.DX + | "SP" -> R.SP + | "BP" -> R.BP + | "SI" -> R.SI + | "DI" -> R.DI + | "AL" -> R.AL + | "BL" -> R.BL + | "CL" -> R.CL + | "DL" -> R.DL + | "AH" -> R.AH + | "BH" -> R.BH + | "CH" -> R.CH + | "DH" -> R.DH + | "R8" -> R.R8 + | "R9" -> R.R9 + | "R10" -> R.R10 + | "R11" -> R.R11 + | "R12" -> R.R12 + | "R13" -> R.R13 + | "R14" -> R.R14 + | "R15" -> R.R15 + | "R8D" -> R.R8D + | "R9D" -> R.R9D + | "R10D" -> R.R10D + | "R11D" -> R.R11D + | "R12D" -> R.R12D + | "R13D" -> R.R13D + | "R14D" -> R.R14D + | "R15D" -> R.R15D + | "R8W" -> R.R8W + | "R9W" -> R.R9W + | "R10W" -> R.R10W + | "R11W" -> R.R11W + | "R12W" -> R.R12W + | "R13W" -> R.R13W + | "R14W" -> R.R14W + | "R15W" -> R.R15W + | "R8L" -> R.R8L + | "R9L" -> R.R9L + | "R10L" -> R.R10L + | "R11L" -> R.R11L + | "R12L" -> R.R12L + | "R13L" -> R.R13L + | "R14L" -> R.R14L + | "R15L" -> R.R15L + | "SPL" -> R.SPL + | "BPL" -> R.BPL + | "SIL" -> R.SIL + | "DIL" -> R.DIL + | "EIP" -> R.EIP + | "RIP" -> R.RIP + | "MM0" -> R.MM0 + | "MM1" -> R.MM1 + | "MM2" -> R.MM2 + | "MM3" -> R.MM3 + | "MM4" -> R.MM4 + | "MM5" -> R.MM5 + | "MM6" -> R.MM6 + | "MM7" -> R.MM7 + | "CS" -> R.CS + | "DS" -> R.DS + | "SS" -> R.SS + | "ES" -> R.ES + | "FS" -> R.FS + | "GS" -> R.GS + | "CSBASE" -> R.CSBase + | "DSBASE" -> R.DSBase + | "ESBASE" -> R.ESBase + | "FSBASE" -> R.FSBase + | "GSBASE" -> R.GSBase + | "SSBASE" -> R.SSBase + | "CR0" -> R.CR0 + | "CR2" -> R.CR2 + | "CR3" -> R.CR3 + | "CR4" -> R.CR4 + | "CR8" -> R.CR8 + | "OF" -> R.OF + | "DF" -> R.DF + | "IF" -> R.IF + | "TF" -> R.TF + | "SF" -> R.SF + | "ZF" -> R.ZF + | "AF" -> R.AF + | "PF" -> R.PF + | "CF" -> R.CF + | "K0" -> R.K0 + | "K1" -> R.K1 + | "K2" -> R.K2 + | "K3" -> R.K3 + | "K4" -> R.K4 + | "K5" -> R.K5 + | "K6" -> R.K6 + | "K7" -> R.K7 + | "ST0A" -> R.ST0A + | "ST0B" -> R.ST0B + | "ST1A" -> R.ST1A + | "ST1B" -> R.ST1B + | "ST2A" -> R.ST2A + | "ST2B" -> R.ST2B + | "ST3A" -> R.ST3A + | "ST3B" -> R.ST3B + | "ST4A" -> R.ST4A + | "ST4B" -> R.ST4B + | "ST5A" -> R.ST5A + | "ST5B" -> R.ST5B + | "ST6A" -> R.ST6A + | "ST6B" -> R.ST6B + | "ST7A" -> R.ST7A + | "ST7B" -> R.ST7B + | "FCW" -> R.FCW + | "FSW" -> R.FSW + | "FTW" -> R.FTW + | "FOP" -> R.FOP + | "FIP" -> R.FIP + | "FCS" -> R.FCS + | "FDP" -> R.FDP + | "FDS" -> R.FDS + | "FTOP" -> R.FTOP + | "FTW0" -> R.FTW0 + | "FTW1" -> R.FTW1 + | "FTW2" -> R.FTW2 + | "FTW3" -> R.FTW3 + | "FTW4" -> R.FTW4 + | "FTW5" -> R.FTW5 + | "FTW6" -> R.FTW6 + | "FTW7" -> R.FTW7 + | "FSWC0" -> R.FSWC0 + | "FSWC1" -> R.FSWC1 + | "FSWC2" -> R.FSWC2 + | "FSWC3" -> R.FSWC3 + | "MXCSR" -> R.MXCSR + | "MXCSRMASK" -> R.MXCSRMASK + | "ZMM0A" -> R.ZMM0A + | "ZMM0B" -> R.ZMM0B + | "ZMM0C" -> R.ZMM0C + | "ZMM0D" -> R.ZMM0D + | "ZMM0E" -> R.ZMM0E + | "ZMM0F" -> R.ZMM0F + | "ZMM0G" -> R.ZMM0G + | "ZMM0H" -> R.ZMM0H + | "ZMM1A" -> R.ZMM1A + | "ZMM1B" -> R.ZMM1B + | "ZMM1C" -> R.ZMM1C + | "ZMM1D" -> R.ZMM1D + | "ZMM1E" -> R.ZMM1E + | "ZMM1F" -> R.ZMM1F + | "ZMM1G" -> R.ZMM1G + | "ZMM1H" -> R.ZMM1H + | "ZMM2A" -> R.ZMM2A + | "ZMM2B" -> R.ZMM2B + | "ZMM2C" -> R.ZMM2C + | "ZMM2D" -> R.ZMM2D + | "ZMM2E" -> R.ZMM2E + | "ZMM2F" -> R.ZMM2F + | "ZMM2G" -> R.ZMM2G + | "ZMM2H" -> R.ZMM2H + | "ZMM3A" -> R.ZMM3A + | "ZMM3B" -> R.ZMM3B + | "ZMM3C" -> R.ZMM3C + | "ZMM3D" -> R.ZMM3D + | "ZMM3E" -> R.ZMM3E + | "ZMM3F" -> R.ZMM3F + | "ZMM3G" -> R.ZMM3G + | "ZMM3H" -> R.ZMM3H + | "ZMM4A" -> R.ZMM4A + | "ZMM4B" -> R.ZMM4B + | "ZMM4C" -> R.ZMM4C + | "ZMM4D" -> R.ZMM4D + | "ZMM4E" -> R.ZMM4E + | "ZMM4F" -> R.ZMM4F + | "ZMM4G" -> R.ZMM4G + | "ZMM4H" -> R.ZMM4H + | "ZMM5A" -> R.ZMM5A + | "ZMM5B" -> R.ZMM5B + | "ZMM5C" -> R.ZMM5C + | "ZMM5D" -> R.ZMM5D + | "ZMM5E" -> R.ZMM5E + | "ZMM5F" -> R.ZMM5F + | "ZMM5G" -> R.ZMM5G + | "ZMM5H" -> R.ZMM5H + | "ZMM6A" -> R.ZMM6A + | "ZMM6B" -> R.ZMM6B + | "ZMM6C" -> R.ZMM6C + | "ZMM6D" -> R.ZMM6D + | "ZMM6E" -> R.ZMM6E + | "ZMM6F" -> R.ZMM6F + | "ZMM6G" -> R.ZMM6G + | "ZMM6H" -> R.ZMM6H + | "ZMM7A" -> R.ZMM7A + | "ZMM7B" -> R.ZMM7B + | "ZMM7C" -> R.ZMM7C + | "ZMM7D" -> R.ZMM7D + | "ZMM7E" -> R.ZMM7E + | "ZMM7F" -> R.ZMM7F + | "ZMM7G" -> R.ZMM7G + | "ZMM7H" -> R.ZMM7H + | "ZMM8A" -> R.ZMM8A + | "ZMM8B" -> R.ZMM8B + | "ZMM8C" -> R.ZMM8C + | "ZMM8D" -> R.ZMM8D + | "ZMM8E" -> R.ZMM8E + | "ZMM8F" -> R.ZMM8F + | "ZMM8G" -> R.ZMM8G + | "ZMM8H" -> R.ZMM8H + | "ZMM9A" -> R.ZMM9A + | "ZMM9B" -> R.ZMM9B + | "ZMM9C" -> R.ZMM9C + | "ZMM9D" -> R.ZMM9D + | "ZMM9E" -> R.ZMM9E + | "ZMM9F" -> R.ZMM9F + | "ZMM9G" -> R.ZMM9G + | "ZMM9H" -> R.ZMM9H + | "ZMM10A" -> R.ZMM10A + | "ZMM10B" -> R.ZMM10B + | "ZMM10C" -> R.ZMM10C + | "ZMM10D" -> R.ZMM10D + | "ZMM10E" -> R.ZMM10E + | "ZMM10F" -> R.ZMM10F + | "ZMM10G" -> R.ZMM10G + | "ZMM10H" -> R.ZMM10H + | "ZMM11A" -> R.ZMM11A + | "ZMM11B" -> R.ZMM11B + | "ZMM11C" -> R.ZMM11C + | "ZMM11D" -> R.ZMM11D + | "ZMM11E" -> R.ZMM11E + | "ZMM11F" -> R.ZMM11F + | "ZMM11G" -> R.ZMM11G + | "ZMM11H" -> R.ZMM11H + | "ZMM12A" -> R.ZMM12A + | "ZMM12B" -> R.ZMM12B + | "ZMM12C" -> R.ZMM12C + | "ZMM12D" -> R.ZMM12D + | "ZMM12E" -> R.ZMM12E + | "ZMM12F" -> R.ZMM12F + | "ZMM12G" -> R.ZMM12G + | "ZMM12H" -> R.ZMM12H + | "ZMM13A" -> R.ZMM13A + | "ZMM13B" -> R.ZMM13B + | "ZMM13C" -> R.ZMM13C + | "ZMM13D" -> R.ZMM13D + | "ZMM13E" -> R.ZMM13E + | "ZMM13F" -> R.ZMM13F + | "ZMM13G" -> R.ZMM13G + | "ZMM13H" -> R.ZMM13H + | "ZMM14A" -> R.ZMM14A + | "ZMM14B" -> R.ZMM14B + | "ZMM14C" -> R.ZMM14C + | "ZMM14D" -> R.ZMM14D + | "ZMM14E" -> R.ZMM14E + | "ZMM14F" -> R.ZMM14F + | "ZMM14G" -> R.ZMM14G + | "ZMM14H" -> R.ZMM14H + | "ZMM15A" -> R.ZMM15A + | "ZMM15B" -> R.ZMM15B + | "ZMM15C" -> R.ZMM15C + | "ZMM15D" -> R.ZMM15D + | "ZMM15E" -> R.ZMM15E + | "ZMM15F" -> R.ZMM15F + | "ZMM15G" -> R.ZMM15G + | "ZMM15H" -> R.ZMM15H + | "PKRU" -> R.PKRU + | "DR0" -> R.DR0 + | "DR1" -> R.DR1 + | "DR2" -> R.DR2 + | "DR3" -> R.DR3 + | "DR6" -> R.DR6 + | "DR7" -> R.DR7 + | _ -> raise UnhandledRegExprException + + override __.RegIDFromString str = + Register.ofString str |> Register.toRegID + + override __.RegIDToString rid = + Register.ofRegID rid |> Register.toString + + override __.RegIDToRegType rid = + Register.ofRegID rid |> Register.toRegType + + override __.GetRegisterAliases rid = + Register.ofRegID rid + |> Register.getAliases + |> Array.map Register.toRegID + + override __.ProgramCounter = + if WordSize.is32 wordSize then Register.EIP |> Register.toRegID + else Register.RIP |> Register.toRegID + + override __.StackPointer = + if WordSize.is32 wordSize then Register.ESP |> Register.toRegID + else Register.RSP |> Register.toRegID + |> Some + + override __.FramePointer = + if WordSize.is32 wordSize then Register.EBP |> Register.toRegID + else Register.RBP |> Register.toRegID + |> Some + + override __.IsProgramCounter regid = + __.ProgramCounter = regid + + override __.IsStackPointer regid = + (__.StackPointer |> Option.get) = regid + + override __.IsFramePointer regid = + (__.FramePointer |> Option.get) = regid diff --git a/src/FrontEnd/BinLifter/Intel/IntelRegisterSet.fs b/src/FrontEnd/BinLifter/Intel/IntelRegisterSet.fs new file mode 100644 index 00000000..a439bf84 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelRegisterSet.fs @@ -0,0 +1,481 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.Intel + +open B2R2 + +module private RegisterSetLiteral = + let [] arrLen = 4 + +open RegisterSetLiteral + +type IntelRegisterSet (bitArray: uint64 [], s: Set) = + inherit NonEmptyRegisterSet (bitArray, s) + + new () = IntelRegisterSet (RegisterSet.MakeInternalBitArray arrLen, Set.empty) + + override __.Tag = RegisterSetTag.Intel + + override __.ArrSize = arrLen + + override __.New arr s = new IntelRegisterSet (arr, s) :> RegisterSet + + override __.RegIDToIndex rid = + match Register.ofRegID rid with + | R.EAX -> 0 + | R.EBX -> 1 + | R.ECX -> 2 + | R.EDX -> 3 + | R.ESP -> 4 + | R.EBP -> 5 + | R.ESI -> 6 + | R.EDI -> 7 + | R.RAX -> 8 + | R.RBX -> 9 + | R.RCX -> 10 + | R.RDX -> 11 + | R.RSP -> 12 + | R.RBP -> 13 + | R.RSI -> 14 + | R.RDI -> 15 + | R.R8 -> 16 + | R.R9 -> 17 + | R.R10 -> 18 + | R.R11 -> 19 + | R.R12 -> 20 + | R.R13 -> 21 + | R.R14 -> 22 + | R.R15 -> 23 + | R.SPL -> 24 + | R.BPL -> 25 + | R.SIL -> 26 + | R.DIL -> 27 + | R.ES -> 28 + | R.CS -> 29 + | R.SS -> 30 + | R.DS -> 31 + | R.FS -> 32 + | R.GS -> 33 + | R.ESBase -> 34 + | R.CSBase -> 35 + | R.SSBase -> 36 + | R.DSBase -> 37 + | R.FSBase -> 38 + | R.GSBase -> 39 + | R.OF -> 40 + | R.DF -> 41 + | R.IF -> 42 + | R.TF -> 43 + | R.SF -> 44 + | R.ZF -> 45 + | R.AF -> 46 + | R.PF -> 47 + | R.CF -> 48 + | R.MM0 -> 49 + | R.MM1 -> 50 + | R.MM2 -> 51 + | R.MM3 -> 52 + | R.MM4 -> 53 + | R.MM5 -> 54 + | R.MM6 -> 55 + | R.MM7 -> 56 + | R.ZMM0A -> 57 + | R.ZMM0B -> 58 + | R.ZMM0C -> 59 + | R.ZMM0D -> 60 + | R.ZMM0E -> 61 + | R.ZMM0F -> 62 + | R.ZMM0G -> 63 + | R.ZMM0H -> 64 + | R.ZMM1A -> 65 + | R.ZMM1B -> 66 + | R.ZMM1C -> 67 + | R.ZMM1D -> 68 + | R.ZMM1E -> 69 + | R.ZMM1F -> 70 + | R.ZMM1G -> 71 + | R.ZMM1H -> 72 + | R.ZMM2A -> 73 + | R.ZMM2B -> 74 + | R.ZMM2C -> 75 + | R.ZMM2D -> 76 + | R.ZMM2E -> 77 + | R.ZMM2F -> 78 + | R.ZMM2G -> 79 + | R.ZMM2H -> 80 + | R.ZMM3A -> 81 + | R.ZMM3B -> 82 + | R.ZMM3C -> 83 + | R.ZMM3D -> 84 + | R.ZMM3E -> 85 + | R.ZMM3F -> 86 + | R.ZMM3G -> 87 + | R.ZMM3H -> 88 + | R.ZMM4A -> 89 + | R.ZMM4B -> 90 + | R.ZMM4C -> 91 + | R.ZMM4D -> 92 + | R.ZMM4E -> 93 + | R.ZMM4F -> 94 + | R.ZMM4G -> 95 + | R.ZMM4H -> 96 + | R.ZMM5A -> 97 + | R.ZMM5B -> 98 + | R.ZMM5C -> 99 + | R.ZMM5D -> 100 + | R.ZMM5E -> 101 + | R.ZMM5F -> 102 + | R.ZMM5G -> 103 + | R.ZMM5H -> 104 + | R.ZMM6A -> 105 + | R.ZMM6B -> 106 + | R.ZMM6C -> 107 + | R.ZMM6D -> 108 + | R.ZMM6E -> 109 + | R.ZMM6F -> 110 + | R.ZMM6G -> 111 + | R.ZMM6H -> 112 + | R.ZMM7A -> 113 + | R.ZMM7B -> 114 + | R.ZMM7C -> 115 + | R.ZMM7D -> 116 + | R.ZMM7E -> 117 + | R.ZMM7F -> 118 + | R.ZMM7G -> 119 + | R.ZMM7H -> 120 + | R.ZMM8A -> 121 + | R.ZMM8B -> 122 + | R.ZMM8C -> 123 + | R.ZMM8D -> 124 + | R.ZMM8E -> 125 + | R.ZMM8F -> 126 + | R.ZMM8G -> 127 + | R.ZMM8H -> 128 + | R.ZMM9A -> 129 + | R.ZMM9B -> 130 + | R.ZMM9C -> 131 + | R.ZMM9D -> 132 + | R.ZMM9E -> 133 + | R.ZMM9F -> 134 + | R.ZMM9G -> 135 + | R.ZMM9H -> 136 + | R.ZMM10A -> 137 + | R.ZMM10B -> 138 + | R.ZMM10C -> 139 + | R.ZMM10D -> 140 + | R.ZMM10E -> 141 + | R.ZMM10F -> 142 + | R.ZMM10G -> 143 + | R.ZMM10H -> 144 + | R.ZMM11A -> 145 + | R.ZMM11B -> 146 + | R.ZMM11C -> 147 + | R.ZMM11D -> 148 + | R.ZMM11E -> 149 + | R.ZMM11F -> 150 + | R.ZMM11G -> 151 + | R.ZMM11H -> 152 + | R.ZMM12A -> 153 + | R.ZMM12B -> 154 + | R.ZMM12C -> 155 + | R.ZMM12D -> 156 + | R.ZMM12E -> 157 + | R.ZMM12F -> 158 + | R.ZMM12G -> 159 + | R.ZMM12H -> 160 + | R.ZMM13A -> 161 + | R.ZMM13B -> 162 + | R.ZMM13C -> 163 + | R.ZMM13D -> 164 + | R.ZMM13E -> 165 + | R.ZMM13F -> 166 + | R.ZMM13G -> 167 + | R.ZMM13H -> 168 + | R.ZMM14A -> 169 + | R.ZMM14B -> 170 + | R.ZMM14C -> 171 + | R.ZMM14D -> 172 + | R.ZMM14E -> 173 + | R.ZMM14F -> 174 + | R.ZMM14G -> 175 + | R.ZMM14H -> 176 + | R.ZMM15A -> 177 + | R.ZMM15B -> 178 + | R.ZMM15C -> 179 + | R.ZMM15D -> 180 + | R.ZMM15E -> 181 + | R.ZMM15F -> 182 + | R.ZMM15G -> 183 + | R.ZMM15H -> 184 + | R.BND0A -> 185 + | R.BND0B -> 186 + | R.BND1A -> 187 + | R.BND1B -> 188 + | R.BND2A -> 189 + | R.BND2B -> 190 + | R.BND3A -> 191 + | R.BND3B -> 192 + | R.FCW -> 193 + | R.FSW -> 194 + | R.FTW -> 195 + | R.FOP -> 196 + | R.FIP -> 197 + | R.FCS -> 198 + | R.FDP -> 199 + | R.FDS -> 200 + | R.MXCSR -> 201 + | R.MXCSRMASK -> 202 + | R.PKRU -> 203 + | R.DR0 -> 204 + | R.DR1 -> 205 + | R.DR2 -> 206 + | R.DR3 -> 207 + | R.DR6 -> 208 + | R.DR7 -> 209 + | _ -> -1 + + override __.IndexToRegID index = + match index with + | 0 -> R.EAX + | 1 -> R.EBX + | 2 -> R.ECX + | 3 -> R.EDX + | 4 -> R.ESP + | 5 -> R.EBP + | 6 -> R.ESI + | 7 -> R.EDI + | 8 -> R.RAX + | 9 -> R.RBX + | 10 -> R.RCX + | 11 -> R.RDX + | 12 -> R.RSP + | 13 -> R.RBP + | 14 -> R.RSI + | 15 -> R.RDI + | 16 -> R.R8 + | 17 -> R.R9 + | 18 -> R.R10 + | 19 -> R.R11 + | 20 -> R.R12 + | 21 -> R.R13 + | 22 -> R.R14 + | 23 -> R.R15 + | 24 -> R.SPL + | 25 -> R.BPL + | 26 -> R.SIL + | 27 -> R.DIL + | 28 -> R.ES + | 29 -> R.CS + | 30 -> R.SS + | 31 -> R.DS + | 32 -> R.FS + | 33 -> R.GS + | 34 -> R.ESBase + | 35 -> R.CSBase + | 36 -> R.SSBase + | 37 -> R.DSBase + | 38 -> R.FSBase + | 39 -> R.GSBase + | 40 -> R.OF + | 41 -> R.DF + | 42 -> R.IF + | 43 -> R.TF + | 44 -> R.SF + | 45 -> R.ZF + | 46 -> R.AF + | 47 -> R.PF + | 48 -> R.CF + | 49 -> R.MM0 + | 50 -> R.MM1 + | 51 -> R.MM2 + | 52 -> R.MM3 + | 53 -> R.MM4 + | 54 -> R.MM5 + | 55 -> R.MM6 + | 56 -> R.MM7 + | 57 -> R.ZMM0A + | 58 -> R.ZMM0B + | 59 -> R.ZMM0C + | 60 -> R.ZMM0D + | 61 -> R.ZMM0E + | 62 -> R.ZMM0F + | 63 -> R.ZMM0G + | 64 -> R.ZMM0H + | 65 -> R.ZMM1A + | 66 -> R.ZMM1B + | 67 -> R.ZMM1C + | 68 -> R.ZMM1D + | 69 -> R.ZMM1E + | 70 -> R.ZMM1F + | 71 -> R.ZMM1G + | 72 -> R.ZMM1H + | 73 -> R.ZMM2A + | 74 -> R.ZMM2B + | 75 -> R.ZMM2C + | 76 -> R.ZMM2D + | 77 -> R.ZMM2E + | 78 -> R.ZMM2F + | 79 -> R.ZMM2G + | 80 -> R.ZMM2H + | 81 -> R.ZMM3A + | 82 -> R.ZMM3B + | 83 -> R.ZMM3C + | 84 -> R.ZMM3D + | 85 -> R.ZMM3E + | 86 -> R.ZMM3F + | 87 -> R.ZMM3G + | 88 -> R.ZMM3H + | 89 -> R.ZMM4A + | 90 -> R.ZMM4B + | 91 -> R.ZMM4C + | 92 -> R.ZMM4D + | 93 -> R.ZMM4E + | 94 -> R.ZMM4F + | 95 -> R.ZMM4G + | 96 -> R.ZMM4H + | 97 -> R.ZMM5A + | 98 -> R.ZMM5B + | 99 -> R.ZMM5C + | 100 -> R.ZMM5D + | 101 -> R.ZMM5E + | 102 -> R.ZMM5F + | 103 -> R.ZMM5G + | 104 -> R.ZMM5H + | 105 -> R.ZMM6A + | 106 -> R.ZMM6B + | 107 -> R.ZMM6C + | 108 -> R.ZMM6D + | 109 -> R.ZMM6E + | 110 -> R.ZMM6F + | 111 -> R.ZMM6G + | 112 -> R.ZMM6H + | 113 -> R.ZMM7A + | 114 -> R.ZMM7B + | 115 -> R.ZMM7C + | 116 -> R.ZMM7D + | 117 -> R.ZMM7E + | 118 -> R.ZMM7F + | 119 -> R.ZMM7G + | 120 -> R.ZMM7H + | 121 -> R.ZMM8A + | 122 -> R.ZMM8B + | 123 -> R.ZMM8C + | 124 -> R.ZMM8D + | 125 -> R.ZMM8E + | 126 -> R.ZMM8F + | 127 -> R.ZMM8G + | 128 -> R.ZMM8H + | 129 -> R.ZMM9A + | 130 -> R.ZMM9B + | 131 -> R.ZMM9C + | 132 -> R.ZMM9D + | 133 -> R.ZMM9E + | 134 -> R.ZMM9F + | 135 -> R.ZMM9G + | 136 -> R.ZMM9H + | 137 -> R.ZMM10A + | 138 -> R.ZMM10B + | 139 -> R.ZMM10C + | 140 -> R.ZMM10D + | 141 -> R.ZMM10E + | 142 -> R.ZMM10F + | 143 -> R.ZMM10G + | 144 -> R.ZMM10H + | 145 -> R.ZMM11A + | 146 -> R.ZMM11B + | 147 -> R.ZMM11C + | 148 -> R.ZMM11D + | 149 -> R.ZMM11E + | 150 -> R.ZMM11F + | 151 -> R.ZMM11G + | 152 -> R.ZMM11H + | 153 -> R.ZMM12A + | 154 -> R.ZMM12B + | 155 -> R.ZMM12C + | 156 -> R.ZMM12D + | 157 -> R.ZMM12E + | 158 -> R.ZMM12F + | 159 -> R.ZMM12G + | 160 -> R.ZMM12H + | 161 -> R.ZMM13A + | 162 -> R.ZMM13B + | 163 -> R.ZMM13C + | 164 -> R.ZMM13D + | 165 -> R.ZMM13E + | 166 -> R.ZMM13F + | 167 -> R.ZMM13G + | 168 -> R.ZMM13H + | 169 -> R.ZMM14A + | 170 -> R.ZMM14B + | 171 -> R.ZMM14C + | 172 -> R.ZMM14D + | 173 -> R.ZMM14E + | 174 -> R.ZMM14F + | 175 -> R.ZMM14G + | 176 -> R.ZMM14H + | 177 -> R.ZMM15A + | 178 -> R.ZMM15B + | 179 -> R.ZMM15C + | 180 -> R.ZMM15D + | 181 -> R.ZMM15E + | 182 -> R.ZMM15F + | 183 -> R.ZMM15G + | 184 -> R.ZMM15H + | 185 -> R.BND0A + | 186 -> R.BND0B + | 187 -> R.BND1A + | 188 -> R.BND1B + | 189 -> R.BND2A + | 190 -> R.BND2B + | 191 -> R.BND3A + | 192 -> R.BND3B + | 193 -> R.FCW + | 194 -> R.FSW + | 195 -> R.FTW + | 196 -> R.FOP + | 197 -> R.FIP + | 198 -> R.FCS + | 199 -> R.FDP + | 200 -> R.FDS + | 201 -> R.MXCSR + | 202 -> R.MXCSRMASK + | 203 -> R.PKRU + | 204 -> R.DR0 + | 205 -> R.DR1 + | 206 -> R.DR2 + | 207 -> R.DR3 + | 208 -> R.DR6 + | 209 -> R.DR7 + | _ -> Utils.impossible () + |> Register.toRegID + + override __.ToString () = + sprintf "IntelRegisterSet<%x, %x, %x, %x>" __.BitArray.[0] __.BitArray.[1] + __.BitArray.[2] __.BitArray.[3] + +[] +module IntelRegisterSet = + let singleton rid = IntelRegisterSet().Add(rid) + let empty = IntelRegisterSet () :> RegisterSet diff --git a/src/FrontEnd/BinLifter/Intel/IntelSSELifter.fs b/src/FrontEnd/BinLifter/Intel/IntelSSELifter.fs new file mode 100644 index 00000000..89d3a318 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelSSELifter.fs @@ -0,0 +1,1814 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.Intel.SSELifter + +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.FrontEnd.BinLifter.Intel.Helper +open B2R2.FrontEnd.BinLifter.Intel.LiftingUtils +open B2R2.FrontEnd.BinLifter.Intel.MMXLifter + +let buildMove ins insLen ctxt bufSize = + let ir = IRBuilder (bufSize) + let oprSize = getOperationSize ins + ! | 64 -> + let struct (dst, src) = transTwoOprs ins insLen ctxt + !!ir (dst := src) + | 128 | 256 | 512 -> + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExprVec ins insLen ctxt dst + let src = transOprToExprVec ins insLen ctxt src + List.iter2 (fun d s -> !!ir (d := s)) dst src + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let movaps ins insLen ctxt = buildMove ins insLen ctxt 4 + +let movapd ins insLen ctxt = buildMove ins insLen ctxt 4 + +let movups ins insLen ctxt = buildMove ins insLen ctxt 4 + +let movupd ins insLen ctxt = buildMove ins insLen ctxt 4 + +let movhps ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + !), OprReg r -> + let dst = transOprToExpr ins insLen ctxt dst + !!ir (dst := getPseudoRegVar ctxt r 2) + | OprReg r, OprMem (_, _, _, 64)-> + let src = transOprToExpr ins insLen ctxt src + !!ir (getPseudoRegVar ctxt r 2 := src) + | _ -> raise InvalidOperandException + !>ir insLen + +let movhpd ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + ! + let src = transOprToExpr ins insLen ctxt src + !!ir (getPseudoRegVar ctxt r 2 := src) + | OprMem _, OprReg r -> + let dst = transOprToExpr ins insLen ctxt dst + !!ir (dst := getPseudoRegVar ctxt r 1) + | _ -> raise InvalidOperandException + !>ir insLen + +let movhlps ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr128 ins insLen ctxt dst |> snd + let src = transOprToExpr128 ins insLen ctxt src |> fst + !ir insLen + +let movlpd ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + ! + let src = transOprToExpr ins insLen ctxt src + !!ir (getPseudoRegVar ctxt r 1 := src) + | OprMem _, OprReg r -> + let dst = transOprToExpr ins insLen ctxt dst + !!ir (dst := getPseudoRegVar ctxt r 1) + | _ -> raise InvalidOperandException + !>ir insLen + +let movlps ins insLen ctxt = movlpd ins insLen ctxt + +let movlhps ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr128 ins insLen ctxt dst |> fst + let src = transOprToExpr128 ins insLen ctxt src |> snd + !ir insLen + +let movmskps ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr ins insLen ctxt dst + let srcB, srcA= transOprToExpr128 ins insLen ctxt src + let oprSize = getOperationSize ins + ! 63) (AST.extract srcA 1 31) + let srcB = AST.concat (AST.extract srcB 1 63) (AST.extract srcB 1 31) + !!ir (dst := AST.zext oprSize <| AST.concat srcB srcA) + !>ir insLen + +let movmskpd ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr ins insLen ctxt dst + let src1, src2 = transOprToExpr128 ins insLen ctxt src + let oprSize = getOperationSize ins + ! src2) + let src127 = (AST.sext oprSize (AST.xthi 1 src1)) << AST.num1 oprSize + !!ir (dst := src63 .| src127) + !>ir insLen + +let movss (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + ! + let dst = getPseudoRegVar ctxt r1 1 |> AST.xtlo 32 + let src = getPseudoRegVar ctxt r2 1 |> AST.xtlo 32 + !!ir (dst := src) + | OprReg r1, OprMem _ -> + let dst2, dst1 = getPseudoRegVar128 ctxt r1 + let src = transOprToExpr ins insLen ctxt src + !!ir (dstAssign 32 dst1 src) + !!ir (dst2 := AST.num0 64) + | OprMem _ , OprReg r1 -> + let dst = transOprToExpr ins insLen ctxt dst + let src = getPseudoRegVar ctxt r1 1 |> AST.xtlo 32 + !!ir (dstAssign 32 dst src) + | _ -> raise InvalidOperandException + !>ir insLen + +let movsd (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (4) + if ins.Operands = NoOperand then + GeneralLifter.movs ins insLen ctxt + else + let struct (dst, src) = getTwoOprs ins + ! + let dst = getPseudoRegVar ctxt r1 1 + let src = getPseudoRegVar ctxt r2 1 + !!ir (dst := src) + | OprReg r1, OprMem _ -> + let dst2, dst1 = getPseudoRegVar128 ctxt r1 + let src = transOprToExpr ins insLen ctxt src + !!ir (dst1 := src) + !!ir (dst2 := AST.num0 64) + | OprMem _ , OprReg r1 -> + let dst = transOprToExpr ins insLen ctxt dst + let src = getPseudoRegVar ctxt r1 1 + !!ir (dstAssign 64 dst src) + | _ -> raise InvalidOperandException + !>ir insLen + +let addps ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 (opP AST.fadd) 8 + +let addpd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 (opP AST.fadd) 8 + +let private getFstOperand = function + | OneOperand o -> o + | TwoOperands (o, _) -> o + | ThreeOperands (o, _, _) -> o + | FourOperands (o, _, _, _) -> o + | _ -> raise InvalidOperandException + +let private getTwoSrcOperands = function + | TwoOperands (op1, op2) -> (op1, op2) + | ThreeOperands (_op1, op2, op3) -> (op2, op3) + | _ -> raise InvalidOperandException + +let private handleScalarFPOp (ins: InsInfo) insLen ctxt sz op = + let ir = IRBuilder(8) + let _dst2, dst1 = + ins.Operands |> getFstOperand |> transOprToExpr128 ins insLen ctxt + let src1, src2 = getTwoSrcOperands ins.Operands + let src1 = transOprToExpr64 ins insLen ctxt src1 + let src2 = + if sz = 32 then transOprToExpr32 ins insLen ctxt src2 + else transOprToExpr64 ins insLen ctxt src2 + let dst1, src1 = + if sz = 32 then AST.xtlo 32 dst1, AST.xtlo 32 src1 + else dst1, src1 + let struct (t1, t2, t3) = tmpVars3 ir sz + !ir insLen + +let addss ins insLen ctxt = + handleScalarFPOp ins insLen ctxt 32 AST.fadd + +let addsd ins insLen ctxt = + handleScalarFPOp ins insLen ctxt 64 AST.fadd + +let subps ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 (opP AST.fsub) 8 + +let subpd ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + !ir insLen + +let subss ins insLen ctxt = + handleScalarFPOp ins insLen ctxt 32 AST.fsub + +let subsd ins insLen ctxt = + handleScalarFPOp ins insLen ctxt 64 AST.fsub + +let mulps ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 (opP AST.fmul) 8 + +let mulpd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 (opP AST.fmul) 8 + +let mulss ins insLen ctxt = + handleScalarFPOp ins insLen ctxt 32 AST.fmul + +let mulsd ins insLen ctxt = + handleScalarFPOp ins insLen ctxt 64 AST.fmul + +let divps ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 (opP AST.fdiv) 8 + +let divpd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 (opP AST.fdiv) 8 + +let divss ins insLen ctxt = + handleScalarFPOp ins insLen ctxt 32 AST.fdiv + +let divsd ins insLen ctxt = + handleScalarFPOp ins insLen ctxt 64 AST.fdiv + +let rcpps ins insLen ctxt = + let ir = IRBuilder(8) + let struct (opr1, opr2) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt opr1 + let src2, src1 = transOprToExpr128 ins insLen ctxt opr2 + let dst1b, dst1a = AST.xthi 32 dst1, AST.xtlo 32 dst1 + let dst2b, dst2a = AST.xthi 32 dst2, AST.xtlo 32 dst2 + let src1b, src1a = AST.xthi 32 src1, AST.xtlo 32 src1 + let src2b, src2a = AST.xthi 32 src2, AST.xtlo 32 src2 + let tmp = !*ir 32 + let flt1 = BitVector.ofInt32 0x3f800000 32 |> AST.num + !ir insLen + +let rcpss ins insLen ctxt = + let ir = IRBuilder(4) + let struct (opr1, opr2) = getTwoOprs ins + let dst = transOprToExpr32 ins insLen ctxt opr1 + let src = transOprToExpr32 ins insLen ctxt opr2 + let tmp = !*ir 32 + let flt1 = BitVector.ofInt32 0x3f800000 32 |> AST.num + !ir insLen + +let sqrtps ins insLen ctxt = + let ir = IRBuilder (16) + let struct (opr1, opr2) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt opr1 + let src2, src1 = transOprToExpr128 ins insLen ctxt opr2 + let struct (tmp1, tmp2, tmp3, tmp4) = tmpVars4 ir 32 + ! src1) + !!ir (tmp2 := AST.xthi 32 src1) + !!ir (tmp3 := AST.xtlo 32 src2) + !!ir (tmp4 := AST.xthi 32 src2) + !!ir (AST.xtlo 32 dst1 := AST.unop UnOpType.FSQRT tmp1) + !!ir (AST.xthi 32 dst1 := AST.unop UnOpType.FSQRT tmp2) + !!ir (AST.xtlo 32 dst2 := AST.unop UnOpType.FSQRT tmp3) + !!ir (AST.xthi 32 dst2 := AST.unop UnOpType.FSQRT tmp4) + !>ir insLen + +let sqrtpd ins insLen ctxt = + let ir = IRBuilder (4) + let struct (opr1, opr2) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt opr1 + let src2, src1 = transOprToExpr128 ins insLen ctxt opr2 + !ir insLen + +let sqrtss ins insLen ctxt = + let ir = IRBuilder (4) + let struct (opr1, opr2) = getTwoOprs ins + let dst = transOprToExpr32 ins insLen ctxt opr1 + let src = transOprToExpr32 ins insLen ctxt opr2 + !ir insLen + +let sqrtsd ins insLen ctxt = + let ir = IRBuilder (4) + let struct (opr1, opr2) = getTwoOprs ins + let dst = transOprToExpr64 ins insLen ctxt opr1 + let src = transOprToExpr64 ins insLen ctxt opr2 + !ir insLen + +let rsqrtps ins insLen ctxt = + let ir = IRBuilder(16) + let struct (opr1, opr2) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt opr1 + let src2, src1 = transOprToExpr128 ins insLen ctxt opr2 + let dst1b, dst1a = AST.xthi 32 dst1, AST.xtlo 32 dst1 + let dst2b, dst2a = AST.xthi 32 dst2, AST.xtlo 32 dst2 + let src1b, src1a = AST.xthi 32 src1, AST.xtlo 32 src1 + let src2b, src2a = AST.xthi 32 src2, AST.xtlo 32 src2 + let tmp = !*ir 32 + let flt1 = BitVector.ofInt32 0x3f800000 32 |> AST.num + !ir insLen + +let rsqrtss ins insLen ctxt = + let ir = IRBuilder(4) + let struct (opr1, opr2) = getTwoOprs ins + let dst = transOprToExpr32 ins insLen ctxt opr1 + let src = transOprToExpr32 ins insLen ctxt opr2 + let tmp = !*ir 32 + let flt1 = BitVector.ofInt32 0x3f800000 32 |> AST.num + !ir insLen + +let private minMaxPS ins insLen ctxt compare = + let ir = IRBuilder (16) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + let dst1A, dst1B = AST.xtlo 32 dst1, AST.xthi 32 dst1 + let dst2A, dst2B = AST.xtlo 32 dst2, AST.xthi 32 dst2 + let src1A, src1B = AST.xtlo 32 src1, AST.xthi 32 src1 + let src2A, src2B = AST.xtlo 32 src2, AST.xthi 32 src2 + let struct (val4, val3, val2, val1) = tmpVars4 ir 32 + !ir insLen + +let private minMaxPD ins insLen ctxt compare = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + let struct (val2, val1) = tmpVars2 ir 64 + !ir insLen + +let private minMaxSS ins insLen ctxt compare = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr32 ins insLen ctxt dst + let src = transOprToExpr32 ins insLen ctxt src + let tmp = !*ir 32 + !ir insLen + +let private minMaxSD ins insLen ctxt compare = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr64 ins insLen ctxt dst + let src = transOprToExpr64 ins insLen ctxt src + let tmp = !*ir 64 + !ir insLen + +let maxps ins insLen ctxt = + minMaxPS ins insLen ctxt AST.fgt + +let maxpd ins insLen ctxt = + minMaxPD ins insLen ctxt AST.fgt + +let maxss ins insLen ctxt = + minMaxSS ins insLen ctxt AST.fgt + +let maxsd ins insLen ctxt = + minMaxSD ins insLen ctxt AST.fgt + +let minps ins insLen ctxt = + minMaxPS ins insLen ctxt AST.flt + +let minpd ins insLen ctxt = + minMaxPD ins insLen ctxt AST.flt + +let minss ins insLen ctxt = + minMaxSS ins insLen ctxt AST.flt + +let minsd ins insLen ctxt = + minMaxSD ins insLen ctxt AST.flt + +let cmpps ins insLen ctxt = + let ir = IRBuilder (64) + let struct (op1, op2, op3) = getThreeOprs ins + let dst1, dst2 = transOprToExpr128 ins insLen ctxt op1 + let src1, src2 = transOprToExpr128 ins insLen ctxt op2 + let dst1A, dst1B = AST.xtlo 32 dst1, AST.xthi 32 dst1 + let dst2A, dst2B = AST.xtlo 32 dst2, AST.xthi 32 dst2 + let imm = transOprToExpr ins insLen ctxt op3 |> AST.xtlo 8 + let isNan expr = + (AST.extract expr 8 23 == AST.num (BitVector.unsignedMax 8)) + .& (AST.xtlo 23 expr != AST.num0 23) + let cmpCond c expr1 expr2 = + !!ir (c := AST.b0) + !!ir (c := AST.ite (imm == AST.num0 8) (expr1 == expr2) c) + !!ir (c := AST.ite (imm == AST.num1 8) (AST.flt expr1 expr2) c) + !!ir (c := AST.ite (imm == numI32 2 8) (AST.fle expr1 expr2) c) + !!ir (c := AST.ite (imm == numI32 3 8) (isNan expr1 .| isNan expr2) c) + !!ir (c := AST.ite (imm == numI32 4 8) (expr1 != expr2) c) + !!ir + (c := AST.ite (imm == numI32 5 8) (AST.flt expr1 expr2 |> AST.not) c) + !!ir + (c := AST.ite (imm == numI32 6 8) (AST.fle expr1 expr2 |> AST.not) c) + !!ir (c := AST.ite (imm == numI32 7 8) + (isNan expr1 .| isNan expr2 |> AST.not) c) + let struct (cond1, cond2, cond3, cond4) = tmpVars4 ir 1 + ! src1) + cmpCond cond2 dst1B (AST.xthi 32 src1) + cmpCond cond3 dst2A (AST.xtlo 32 src2) + cmpCond cond4 dst2B (AST.xthi 32 src2) + !!ir (dst1A := AST.ite cond1 (maxNum 32) (AST.num0 32)) + !!ir (dst1B := AST.ite cond2 (maxNum 32) (AST.num0 32)) + !!ir (dst2A := AST.ite cond3 (maxNum 32) (AST.num0 32)) + !!ir (dst2B := AST.ite cond4 (maxNum 32) (AST.num0 32)) + !>ir insLen + +let cmppd ins insLen ctxt = + let ir = IRBuilder (32) + let struct (op1, op2, op3) = getThreeOprs ins + let dst1, dst2 = transOprToExpr128 ins insLen ctxt op1 + let src1, src2 = transOprToExpr128 ins insLen ctxt op2 + let imm = transOprToExpr ins insLen ctxt op3 |> AST.xtlo 8 + let isNan expr = + (AST.extract expr 11 52 == AST.num (BitVector.unsignedMax 11)) + .& (AST.xtlo 52 expr != AST.num0 52) + let cmpCond c expr1 expr2 = + !!ir (c := AST.b0) + !!ir (c := AST.ite (imm == AST.num0 8) (expr1 == expr2) c) + !!ir (c := AST.ite (imm == AST.num1 8) (AST.flt expr1 expr2) c) + !!ir (c := AST.ite (imm == numI32 2 8) (AST.fle expr1 expr2) c) + !!ir (c := AST.ite (imm == numI32 3 8) (isNan expr1 .| isNan expr2) c) + !!ir (c := AST.ite (imm == numI32 4 8) (expr1 != expr2) c) + !!ir + (c := AST.ite (imm == numI32 5 8) (AST.flt expr1 expr2 |> AST.not) c) + !!ir + (c := AST.ite (imm == numI32 6 8) (AST.fle expr1 expr2 |> AST.not) c) + !!ir (c := AST.ite (imm == numI32 7 8) + (isNan expr1 .| isNan expr2 |> AST.not) c) + let struct (cond1, cond2) = tmpVars2 ir 1 + !) (AST.num0 64)) + !!ir (dst2 := AST.ite cond2 (maxNum 64) (AST.num0 64)) + !>ir insLen + +let cmpss ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src, imm) = getThreeOprs ins + let dst = transOprToExpr32 ins insLen ctxt dst + let src = transOprToExpr32 ins insLen ctxt src + let imm = transOprToExpr ins insLen ctxt imm |> AST.xtlo 8 + let n num = numI32 num 8 + let max32 = maxNum 32 + let isNan expr = + (AST.extract expr 8 23 == AST.num (BitVector.unsignedMax 8)) + .& (AST.xtlo 23 expr != AST.num0 23) + let cond = !*ir 1 + ! AST.not) cond) + !!ir (cond := AST.ite (imm == n 6) (AST.fle dst src |> AST.not) cond) + !!ir (cond := AST.ite (imm == n 7) + ((isNan dst) .| (isNan src) |> AST.not) cond) + !!ir (dst := AST.ite cond max32 (AST.num0 32)) + !>ir insLen + +let cmpsd (ins: InsInfo) insLen ctxt = + match ins.Operands with + | NoOperand -> GeneralLifter.cmps ins insLen ctxt + | ThreeOperands (dst, src, imm) -> + let ir = IRBuilder (16) + let dst = transOprToExpr64 ins insLen ctxt dst + let src = transOprToExpr64 ins insLen ctxt src + let imm = transOprToExpr ins insLen ctxt imm |> AST.xtlo 8 + let n i = numI32 i 8 + let max64 = maxNum 64 + let isNan expr = + (AST.extract expr 11 52 == AST.num (BitVector.unsignedMax 11)) + .& (AST.xtlo 52 expr != AST.num0 52) + let cond = !*ir 1 + ! AST.not) cond) + !!ir (cond := AST.ite (imm == n 6) (AST.fle dst src |> AST.not) cond) + !!ir (cond := AST.ite (imm == n 7) + ((isNan dst) .| (isNan src) |> AST.not) cond) + !!ir (dst := AST.ite cond max64 (AST.num0 64)) + !>ir insLen + | _ -> raise InvalidOperandException + +let comiss ins insLen ctxt = + let ir = IRBuilder (16) + let struct (opr1, opr2) = getTwoOprs ins + let opr1 = transOprToExpr32 ins insLen ctxt opr1 + let opr2 = transOprToExpr32 ins insLen ctxt opr2 + let lblNan = ir.NewSymbol "IsNan" + let lblExit = ir.NewSymbol "Exit" + let zf = !.ctxt R.ZF + let pf = !.ctxt R.PF + let cf = !.ctxt R.CF + ! 23 == AST.num (BitVector.unsignedMax 8)) + .& (AST.xtlo 23 expr != AST.num0 23) + !!ir (AST.cjmp (isNan opr1 .| isNan opr2) + (AST.name lblNan) (AST.name lblExit)) + !!ir (AST.lmark lblNan) + !!ir (zf := AST.b1) + !!ir (pf := AST.b1) + !!ir (cf := AST.b1) + !!ir (AST.lmark lblExit) + !!ir (!.ctxt R.OF := AST.b0) + !!ir (!.ctxt R.AF := AST.b0) + !!ir (!.ctxt R.SF := AST.b0) + !>ir insLen + +let comisd ins insLen ctxt = + let ir = IRBuilder (16) + let struct (opr1, opr2) = getTwoOprs ins + let opr1 = transOprToExpr64 ins insLen ctxt opr1 + let opr2 = transOprToExpr64 ins insLen ctxt opr2 + let lblNan = ir.NewSymbol "IsNan" + let lblExit = ir.NewSymbol "Exit" + let zf = !.ctxt R.ZF + let pf = !.ctxt R.PF + let cf = !.ctxt R.CF + ! 52 == AST.num (BitVector.unsignedMax 11)) + .& (AST.xtlo 52 expr != AST.num0 52) + !!ir (AST.cjmp (isNan opr1 .| isNan opr2) + (AST.name lblNan) (AST.name lblExit)) + !!ir (AST.lmark lblNan) + !!ir (zf := AST.b1) + !!ir (pf := AST.b1) + !!ir (cf := AST.b1) + !!ir (AST.lmark lblExit) + !!ir (!.ctxt R.OF := AST.b0) + !!ir (!.ctxt R.AF := AST.b0) + !!ir (!.ctxt R.SF := AST.b0) + !>ir insLen + +let ucomiss ins insLen ctxt = + let ir = IRBuilder (16) + let struct (opr1, opr2) = getTwoOprs ins + let opr1 = transOprToExpr32 ins insLen ctxt opr1 + let opr2 = transOprToExpr32 ins insLen ctxt opr2 + let lblNan = ir.NewSymbol "IsNan" + let lblExit = ir.NewSymbol "Exit" + let zf = !.ctxt R.ZF + let pf = !.ctxt R.PF + let cf = !.ctxt R.CF + ! 23 == AST.num (BitVector.unsignedMax 8)) + .& (AST.xtlo 23 expr != AST.num0 23) + !!ir (AST.cjmp (isNan opr1 .| isNan opr2) + (AST.name lblNan) (AST.name lblExit)) + !!ir (AST.lmark lblNan) + !!ir (zf := AST.b1) + !!ir (pf := AST.b1) + !!ir (cf := AST.b1) + !!ir (AST.lmark lblExit) + !!ir (!.ctxt R.OF := AST.b0) + !!ir (!.ctxt R.AF := AST.b0) + !!ir (!.ctxt R.SF := AST.b0) + !>ir insLen + +let ucomisd ins insLen ctxt = + let ir = IRBuilder (16) + let struct (opr1, opr2) = getTwoOprs ins + let opr1 = transOprToExpr64 ins insLen ctxt opr1 + let opr2 = transOprToExpr64 ins insLen ctxt opr2 + let lblNan = ir.NewSymbol "IsNan" + let lblExit = ir.NewSymbol "Exit" + let zf = !.ctxt R.ZF + let pf = !.ctxt R.PF + let cf = !.ctxt R.CF + ! 52 == AST.num (BitVector.unsignedMax 11)) + .& (AST.xtlo 52 expr != AST.num0 52) + !!ir (AST.cjmp (isNan opr1 .| isNan opr2) + (AST.name lblNan) (AST.name lblExit)) + !!ir (AST.lmark lblNan) + !!ir (zf := AST.b1) + !!ir (pf := AST.b1) + !!ir (cf := AST.b1) + !!ir (AST.lmark lblExit) + !!ir (!.ctxt R.OF := AST.b0) + !!ir (!.ctxt R.AF := AST.b0) + !!ir (!.ctxt R.SF := AST.b0) + !>ir insLen + +let andps ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPand 16 + +let andpd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPand 16 + +let andnps ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPandn 8 + +let andnpd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPandn 8 + +let orps ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPor 16 + +let orpd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPor 16 + +let private opPxor _ = Array.map2 (.|) + +let xorps ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPxor 16 + +let xorpd ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPxor 16 + +let shufps ins insLen ctxt = + let ir = IRBuilder (32) + let struct (dst, src, imm) = getThreeOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + let imm = transOprToExpr ins insLen ctxt imm + let dst1A, dst1B = AST.xtlo 32 dst1, AST.xthi 32 dst1 + let dst2A, dst2B = AST.xtlo 32 dst2, AST.xthi 32 dst2 + let src1A, src1B = AST.xtlo 32 src1, AST.xthi 32 src1 + let src2A, src2B = AST.xtlo 32 src2, AST.xthi 32 src2 + let doShuf cond dst e0 e1 e2 e3 = + !!ir (dst := AST.num0 32) + !!ir (dst := AST.ite (cond == AST.num0 2) e0 dst) + !!ir (dst := AST.ite (cond == AST.num1 2) e1 dst) + !!ir (dst := AST.ite (cond == numI32 2 2) e2 dst) + !!ir (dst := AST.ite (cond == numI32 3 2) e3 dst) + let cond1 = AST.xtlo 2 imm + let cond2 = AST.extract imm 2 2 + let cond3 = AST.extract imm 2 4 + let cond4 = AST.extract imm 2 6 + let struct (tmp1, tmp2, tmp3, tmp4) = tmpVars4 ir 32 + !ir insLen + +let shufpd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src, imm) = getThreeOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + let imm = transOprToExpr ins insLen ctxt imm + let cond1 = AST.xtlo 1 imm + let cond2 = AST.extract imm 1 1 + !ir insLen + +let unpckhps ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, _src1 = transOprToExpr128 ins insLen ctxt src + let dst1A, dst1B = AST.xtlo 32 dst1, AST.xthi 32 dst1 + let dst2A, dst2B = AST.xtlo 32 dst2, AST.xthi 32 dst2 + let src2A, src2B = AST.xtlo 32 src2, AST.xthi 32 src2 + !ir insLen + +let unpckhpd ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, _src1 = transOprToExpr128 ins insLen ctxt src + !ir insLen + +let unpcklps ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let _src2, src1 = transOprToExpr128 ins insLen ctxt src + let _dst1A, dst1B = AST.xtlo 32 dst1, AST.xthi 32 dst1 + let dst2A, dst2B = AST.xtlo 32 dst2, AST.xthi 32 dst2 + let src1A, src1B = AST.xtlo 32 src1, AST.xthi 32 src1 + !ir insLen + +let unpcklpd ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let _src2, src1 = transOprToExpr128 ins insLen ctxt src + !ir insLen + +let cvtpi2ps ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr64 ins insLen ctxt dst + let src = transOprToExpr64 ins insLen ctxt src + let struct (tmp2, tmp1) = tmpVars2 ir 32 + ! src) + !!ir (tmp2 := AST.xthi 32 src) + !!ir (AST.xtlo 32 dst := AST.cast CastKind.IntToFloat 32 tmp1) + !!ir (AST.xthi 32 dst := AST.cast CastKind.IntToFloat 32 tmp2) + !>ir insLen + +let cvtdq2pd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src = transOprToExpr64 ins insLen ctxt src + let struct (tmp1, tmp2) = tmpVars2 ir 32 + ! src) + !!ir (tmp2 := AST.xthi 32 src) + !!ir (dst1 := AST.cast CastKind.IntToFloat 64 tmp1) + !!ir (dst2 := AST.cast CastKind.IntToFloat 64 tmp2) + !>ir insLen + +let cvtpi2pd ins insLen ctxt = cvtdq2pd ins insLen ctxt + +let cvtsi2ss ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr64 ins insLen ctxt dst + let src = transOprToExpr ins insLen ctxt src + ! dst := AST.cast CastKind.IntToFloat 32 src) + !>ir insLen + +let cvtsi2sd ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr64 ins insLen ctxt dst + let src = transOprToExpr ins insLen ctxt src + ! src) + !>ir insLen + +let cvtps2pi ins insLen ctxt rounded = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr ins insLen ctxt dst + let src = transOprToExpr64 ins insLen ctxt src + let struct (tmp1, tmp2) = tmpVars2 ir 32 + let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc + ! src) + !!ir (tmp2 := AST.xthi 32 src) + !!ir (AST.xtlo 32 dst := AST.cast castKind 32 tmp1) + !!ir (AST.xthi 32 dst := AST.cast castKind 32 tmp2) + !>ir insLen + +let cvtps2pd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src = transOprToExpr64 ins insLen ctxt src + let struct (tmp1, tmp2) = tmpVars2 ir 32 + ! src) + !!ir (tmp2 := AST.xthi 32 src) + !!ir (dst1 := AST.cast CastKind.FloatCast 64 tmp1) + !!ir (dst2 := AST.cast CastKind.FloatCast 64 tmp2) + !>ir insLen + +let cvtpd2ps ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + ! dst1 := AST.cast CastKind.FloatCast 32 src1) + !!ir (AST.xthi 32 dst1 := AST.cast CastKind.FloatCast 32 src2) + !!ir (dst2 := AST.num0 64) + !>ir insLen + +let cvtpd2pi ins insLen ctxt rounded = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc + ! dst := AST.cast castKind 32 src1) + !!ir (AST.xthi 32 dst := AST.cast castKind 32 src2) + !>ir insLen + +let cvtpd2dq ins insLen ctxt rounded = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc + ! dst1 := AST.cast castKind 32 src1) + !!ir (AST.xthi 32 dst1 := AST.cast castKind 32 src2) + !!ir (dst2 := AST.num0 64) + !>ir insLen + +let cvtdq2ps ins insLen ctxt = + let ir = IRBuilder (16) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + let struct (tmp1, tmp2, tmp3, tmp4) = tmpVars4 ir 32 + ! src1) + !!ir (tmp2 := AST.xthi 32 src1) + !!ir (tmp3 := AST.xtlo 32 src2) + !!ir (tmp4 := AST.xthi 32 src2) + !!ir (AST.xtlo 32 dst1 := AST.cast CastKind.IntToFloat 32 tmp1) + !!ir (AST.xthi 32 dst1 := AST.cast CastKind.IntToFloat 32 tmp2) + !!ir (AST.xtlo 32 dst2 := AST.cast CastKind.IntToFloat 32 tmp3) + !!ir (AST.xthi 32 dst2 := AST.cast CastKind.IntToFloat 32 tmp4) + !>ir insLen + +let cvtps2dq ins insLen ctxt rounded = + let ir = IRBuilder (16) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + let struct (tmp1, tmp2, tmp3, tmp4) = tmpVars4 ir 32 + let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc + ! src1) + !!ir (tmp2 := AST.xthi 32 src1) + !!ir (tmp3 := AST.xtlo 32 src2) + !!ir (tmp4 := AST.xthi 32 src2) + !!ir (AST.xtlo 32 dst1 := AST.cast castKind 32 tmp1) + !!ir (AST.xthi 32 dst1 := AST.cast castKind 32 tmp2) + !!ir (AST.xtlo 32 dst2 := AST.cast castKind 32 tmp3) + !!ir (AST.xthi 32 dst2 := AST.cast castKind 32 tmp4) + !>ir insLen + +let cvtss2si ins insLen ctxt rounded = + let ir = IRBuilder (4) + let oprSize = getOperationSize ins + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr ins insLen ctxt dst + let src = transOprToExpr32 ins insLen ctxt src + let tmp = !*ir 32 + let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc + ! then + !!ir (dst := AST.cast castKind 64 src) + else + !!ir (tmp := AST.cast castKind 32 src) + !!ir (dstAssign 32 dst tmp) + !>ir insLen + +let cvtss2sd ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr64 ins insLen ctxt dst + let src = transOprToExpr32 ins insLen ctxt src + ! src) + !>ir insLen + +let cvtsd2ss ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr64 ins insLen ctxt dst + let src = transOprToExpr64 ins insLen ctxt src + ! dst := AST.cast CastKind.FloatCast 32 src) + !>ir insLen + +let cvtsd2si ins insLen ctxt rounded = + let ir = IRBuilder (8) + let oprSize = getOperationSize ins + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr ins insLen ctxt dst + let src = transOprToExpr64 ins insLen ctxt src + let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc + let tmp = !*ir 32 + ! then + !!ir (dst := AST.cast castKind 64 src) + else + !!ir (tmp := AST.cast castKind 32 src) + !!ir (dstAssign 32 dst tmp) + !>ir insLen + +let ldmxcsr ins insLen ctxt = + let ir = IRBuilder (4) + let src = transOneOpr ins insLen ctxt + !ir insLen + +let stmxcsr ins insLen ctxt = + let ir = IRBuilder (4) + let dst = transOneOpr ins insLen ctxt + !ir insLen + +let private opAveragePackedInt (packSz: int) = + let dblSz = packSz * 2 + let dblExt expr = AST.zext dblSz expr + let avg e1 e2 = + AST.extract (dblExt e1 .+ dblExt e2 .+ AST.num1 dblSz) packSz 1 + Array.map2 avg + +let private opPavgb _ = opAveragePackedInt 8 + +let pavgb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPavgb 64 + +let private opPavgw _ = opAveragePackedInt 16 + +let pavgw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPavgw 32 + +let pextrw ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src, count) = getThreeOprs ins + let dst = transOprToExpr ins insLen ctxt dst + let count = + transOprToExpr ins insLen ctxt count + |> AST.xtlo 8 .& numU32 7u 8 + let oprSize = getOperationSize ins + ! + match Register.getKind reg with + | Register.Kind.MMX -> + let src = transOprToExpr ins insLen ctxt src + let srcOffset = !*ir 64 + !!ir (srcOffset := AST.zext 64 count) + let t = (src >> (srcOffset .* numU32 16u 64)) .& numU32 0xFFFFu 64 + !!ir (dstAssign oprSize dst (AST.xtlo oprSize t)) + | Register.Kind.XMM -> + let srcB, srcA = getPseudoRegVar128 ctxt reg + let tSrc = !*ir 128 + let srcOffset = !*ir 128 + !!ir (srcOffset := AST.zext 128 count) + !!ir (tSrc := AST.concat srcB srcA) + let t = (tSrc >> (srcOffset .* numU32 16u 128)) .& + numU32 0xFFFFu 128 + !!ir (dstAssign oprSize dst (AST.xtlo oprSize t)) + | _ -> raise InvalidRegisterException + | _ -> raise InvalidOperandException + !>ir insLen + +let pinsrw ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src, count) = getThreeOprs ins + let src = transOprToExpr ins insLen ctxt src + let sel = !*ir 64 + let getImm = function + | OprImm (imm, _) -> imm + | _ -> raise InvalidOperandException + ! + match Register.getSize reg with + | 64 -> + let dst = transOprToExpr ins insLen ctxt dst + let count = transOprToExpr ins insLen ctxt count + let mask = !*ir 64 + !!ir (sel := count .| numI64 3L 64) + let pos = sel .* numU64 0x10UL 64 + !!ir (mask := (numU64 0xffffUL 64) << pos) + !!ir + (dst := (dst .& (AST.not mask)) .| (AST.zext 64 src << pos .& mask)) + | 128 -> + let dst1, dst2 = transOprToExpr128 ins insLen ctxt dst + let mask = !*ir 64 + let count = getImm count + !!ir (sel := numI64 count 64 .| numI64 7L 64) + if count > 3L then + let pos = (sel .- numI32 4 64) .* numI32 16 64 + !!ir (mask := (numU64 0xffffUL 64) << pos) + !!ir (dst1 := (dst1 .& (AST.not mask)) + .| (AST.zext 64 src << pos .& mask)) + else + let pos = sel .* numI32 16 64 + !!ir (mask := (numU64 0xffffUL 64) << pos) + !!ir (dst2 := (dst2 .& (AST.not mask)) + .| (AST.zext 64 src << pos .& mask)) + | _ -> raise InvalidOperandSizeException + | _ -> raise InvalidOperandException + !>ir insLen + +let private opMaxMinPacked cmp = + Array.map2 (fun e1 e2 -> AST.ite (cmp e1 e2) e1 e2) + +let private opPmaxub _ = opMaxMinPacked AST.gt + +let pmaxub ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPmaxub 64 + +let private opPmaxsw _ = opMaxMinPacked AST.sgt + +let pmaxsw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPmaxsw 32 + +let private opPmaxsb _ = opMaxMinPacked AST.sgt + +let pmaxsb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPmaxsb 64 + +let opPminub _ = opMaxMinPacked AST.lt + +let pminub ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPminub 64 + +let private opPminsw _ = opMaxMinPacked AST.slt + +let pminsw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPminsw 32 + +let opPminud _ = opMaxMinPacked AST.lt + +let pminud ins insLen ctxt = + buildPackedInstr ins insLen ctxt 32 opPminud 32 + +let private opPminsb _ = opMaxMinPacked AST.slt + +let pminsb ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPminsb 32 + +let pmovmskb ins insLen ctxt = + let ir = IRBuilder (4) + let oprSize = getOperationSize ins + let struct (dst, src) = getTwoOprs ins + ! r | _ -> raise InvalidOperandException + let arrayInit cnt src = + Array.init cnt (fun i -> AST.extract src 1 (i * 8 + 7)) + match Register.getKind r with + | Register.Kind.MMX -> + let struct (dst, src) = transTwoOprs ins insLen ctxt + let srcSize = TypeCheck.typeOf src + let cnt = RegType.toByteWidth srcSize + let tmps = arrayInit cnt src + !!ir (dstAssign oprSize dst <| AST.zext oprSize (AST.concatArr tmps)) + | Register.Kind.XMM -> + let dst = transOprToExpr ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let srcSize = TypeCheck.typeOf srcA + let cnt = RegType.toByteWidth srcSize + let tmpsA = arrayInit cnt srcA + let tmpsB = arrayInit cnt srcB + let tmps = AST.concat (AST.concatArr tmpsB) (AST.concatArr tmpsA) + !!ir (dstAssign oprSize dst <| AST.zext oprSize tmps) + | Register.Kind.YMM -> + let dst = transOprToExpr ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + let srcSize = TypeCheck.typeOf srcA + let cnt = RegType.toByteWidth srcSize + let tmpsA = arrayInit cnt srcA + let tmpsB = arrayInit cnt srcB + let tmpsC = arrayInit cnt srcC + let tmpsD = arrayInit cnt srcD + let tmps = AST.concat (AST.concat (AST.concatArr tmpsD) (AST.concatArr tmpsC)) + (AST.concat (AST.concatArr tmpsB) (AST.concatArr tmpsA)) + !!ir (dstAssign oprSize dst <| AST.zext oprSize tmps) + | _ -> raise InvalidOperandException + !>ir insLen + +let private opPmulhuw _ = opPmul AST.xthi AST.zext 32 16 + +let pmulhuw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 16 opPmulhuw 32 + +let private opPsadbw _ = + let abs expr = AST.ite (AST.lt expr (AST.num0 8)) (AST.neg expr) (expr) + Array.map2 (fun e1 e2 -> abs (e1 .- e2)) + +let psadbw ins insLen ctxt = + buildPackedInstr ins insLen ctxt 8 opPsadbw 64 + +let pshufw ins insLen ctxt = + let struct (dst, src, ord) = transThreeOprs ins insLen ctxt + let oprSize = getOperationSize ins + let cnt = RegType.toBitWidth oprSize / 16 + let ir = IRBuilder (2 * cnt) + ! !*ir 16) + let n16 = numI32 16 oprSize + let mask2 = numI32 3 16 (* 2-bit mask *) + for i in 1 .. cnt do + let order = + ((AST.xtlo 16 ord) >> (numI32 ((i - 1) * 2) 16)) .& mask2 + let order' = AST.zext oprSize order + !!ir (tmps.[i - 1] := AST.xtlo 16 (src >> (order' .* n16))) + done + !!ir (dst := AST.concatArr tmps) + !>ir insLen + +let pshufd ins insLen ctxt = + let struct (dst, src, ord) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let ord = transOprToExpr ins insLen ctxt ord + let oprSize = getOperationSize ins + let cnt = RegType.toBitWidth oprSize / 32 + let ir = IRBuilder (2 * cnt) + ! !*ir 32) + let n32 = numI32 32 oprSize + let mask2 = numI32 3 32 (* 2-bit mask *) + let tSrc = !*ir oprSize + let tDst = !*ir oprSize + !!ir (tSrc := AST.concat srcB srcA) + for i in 1 .. cnt do + let order = + ((AST.xtlo 32 ord) >> (numI32 ((i - 1) * 2) 32)) .& mask2 + let order' = AST.zext oprSize order + !!ir (tmps.[i - 1] := AST.xtlo 32 (tSrc >> (order' .* n32))) + done + !!ir (tDst := AST.concatArr tmps) + !!ir (dstA := AST.xtlo 64 tDst) + !!ir (dstB := AST.xthi 64 tDst) + !>ir insLen + +let pshuflw ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src, imm) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let imm = transOprToExpr ins insLen ctxt imm + ! !*ir 16) + let n16 = numI32 16 64 + let mask2 = numI32 3 64 (* 2-bit mask *) + for i in 1 .. 4 do + let imm = + ((AST.xtlo 64 imm) >> (numI32 ((i - 1) * 2) 64)) .& mask2 + !!ir (tmps.[i - 1] := AST.xtlo 16 (srcA >> (imm .* n16))) + done + !!ir (dstA := AST.concatArr tmps) + !!ir (dstB := srcB) + !>ir insLen + +let pshufhw ins insLen ctxt = + let struct (dst, src, imm) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let imm = transOprToExpr ins insLen ctxt imm + let ir = IRBuilder (8) + ! !*ir 16) + let n16 = numI32 16 64 + let mask2 = numI32 3 64 (* 2-bit mask *) + for i in 1 .. 4 do + let imm = + ((AST.xtlo 64 imm) >> (numI32 ((i - 1) * 2) 64)) .& mask2 + !!ir (tmps.[i - 1] := AST.xtlo 16 (srcB >> (imm .* n16))) + done + !!ir (dstA := srcA) + !!ir (dstB := AST.concatArr tmps) + !>ir insLen + +let pshufb ins insLen ctxt = + let oprSize = getOperationSize ins + let cnt = RegType.toBitWidth oprSize / 8 + let ir = IRBuilder (2 * cnt) + ! !*ir 8) + let mask = numI32 (cnt - 1) 8 + let genTmps dst src = + for i in 0 .. cnt - 1 do + let cond = AST.extract src 1 (i * 8 + 7) + let idx = (AST.extract src 8 (i * 8)) .& mask + let numShift = AST.zext oprSize idx .* numI32 8 oprSize + !!ir + (tmps.[i] := + AST.ite cond (AST.num0 8) (AST.xtlo 8 (dst >> numShift))) + done + match oprSize with + | 64 -> + let struct (dst, src) = transTwoOprs ins insLen ctxt + genTmps dst src + !!ir (dst := AST.concatArr tmps) + | 128 -> + let struct (dst, src) = getTwoOprs ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let struct (conDst, conSrc) = tmpVars2 ir oprSize + let tDst = !*ir oprSize + !!ir (conDst := AST.concat dstB dstA) + !!ir (conSrc := AST.concat srcB srcA) + genTmps conDst conSrc + !!ir (tDst := AST.concatArr tmps) + !!ir (dstA := AST.xtlo 64 tDst) + !!ir (dstB := AST.xthi 64 tDst) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let movdqa ins insLen ctxt = + buildMove ins insLen ctxt 4 + +let movdqu ins insLen ctxt = + buildMove ins insLen ctxt 4 + +let movq2dq ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src = transOprToExpr ins insLen ctxt src + !) + !>ir insLen + +let movdq2q ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr ins insLen ctxt dst + let _, srcA = transOprToExpr128 ins insLen ctxt src + !ir insLen + +let private opPmuludq _ = + let low32 expr = expr .& numI64 0xffffffffL 64 + Array.map2 (fun e1 e2 -> low32 e1 .* low32 e2) + +let pmuludq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPmuludq 8 + +let paddq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 (opP (.+)) 8 + +let psubq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPsub 8 + +let private shiftDQ ins insLen ctxt shift = + let ir = IRBuilder (8) + let struct (dst, cnt) = getTwoOprs ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let cnt = transOprToExpr ins insLen ctxt cnt |> castNum 8 + let oprSize = getOperationSize ins + let t1 = !*ir 8 + let struct (t2, tDst) = tmpVars2 ir oprSize + !) cnt) (numU32 16u 8) cnt) + !!ir (t2 := AST.concat dstB dstA) + !!ir (tDst := (shift t2 (AST.zext oprSize (t1 .* numU32 8u 8)))) + !!ir (dstA := AST.xtlo 64 tDst) + !!ir (dstB := AST.xthi 64 tDst) + !>ir insLen + +let pslldq ins insLen ctxt = + shiftDQ ins insLen ctxt (<<) + +let psrldq ins insLen ctxt = + shiftDQ ins insLen ctxt (>>) + +let punpckhqdq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPunpckHigh 8 + +let punpcklqdq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPunpckLow 8 + +let movntq ins insLen ctxt = buildMove ins insLen ctxt 4 + +let movntps ins insLen ctxt = buildMove ins insLen ctxt 4 + +let movntpd ins insLen ctxt = buildMove ins insLen ctxt 4 + +let movntdq ins insLen ctxt = buildMove ins insLen ctxt 4 + +let movnti ins insLen ctxt = buildMove ins insLen ctxt 4 + +let lddqu ins insLen ctxt = buildMove ins insLen ctxt 4 + +let movshdup ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + let struct (tmp1, tmp2) = tmpVars2 ir 32 + ! src1) + !!ir (tmp2 := AST.xthi 32 src2) + !!ir (AST.xtlo 32 dst1 := tmp1) + !!ir (AST.xthi 32 dst1 := tmp1) + !!ir (AST.xtlo 32 dst2 := tmp2) + !!ir (AST.xthi 32 dst2 := tmp2) + !>ir insLen + +let movsldup ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src) = getTwoOprs ins + let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ins insLen ctxt src + let struct (tmp1, tmp2) = tmpVars2 ir 32 + ! src1) + !!ir (tmp2 := AST.xtlo 32 src2) + !!ir (AST.xtlo 32 dst1 := tmp1) + !!ir (AST.xthi 32 dst1 := tmp1) + !!ir (AST.xtlo 32 dst2 := tmp2) + !!ir (AST.xthi 32 dst2 := tmp2) + !>ir insLen + +let movddup ins insLen ctxt = + let ir = IRBuilder (4) + let struct (dst, src) = getTwoOprs ins + let dst1, dst0 = transOprToExpr128 ins insLen ctxt dst + let src = transOprToExpr64 ins insLen ctxt src + !ir insLen + +let palignr ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src, imm) = getThreeOprs ins + let imm = transOprToExpr ins insLen ctxt imm + ! -> + let dst = transOprToExpr ins insLen ctxt dst + let src = transOprToExpr ins insLen ctxt src + let t = !*ir 128 + !!ir + (t := (AST.concat dst src) >> (AST.zext 128 (imm .* numU32 8u 64))) + !!ir (dst := AST.xtlo 64 t) + | 128 -> + let dst1, dst2 = transOprToExpr128 ins insLen ctxt dst + let src1, src2 = transOprToExpr128 ins insLen ctxt src + let dst = AST.concat dst1 dst2 + let src = AST.concat src1 src2 + let t = !*ir 256 + !!ir + (t := (AST.concat dst src) >> (AST.zext 256 (imm .* numU32 8u 128))) + !!ir (dst1 := AST.extract t 64 64) + !!ir (dst2 := AST.xtlo 64 t) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let roundsd ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src, imm) = getThreeOprs ins + let dst = transOprToExpr64 ins insLen ctxt dst + let src = transOprToExpr64 ins insLen ctxt src + let imm = transOprToExpr ins insLen ctxt imm + let rc = AST.extract (!.ctxt R.FCW) 2 10 + let tmp = !*ir 2 + let cster castKind = AST.cast castKind 64 src + ! 2) rc (AST.xtlo 2 imm)) + !!ir (dst := AST.num0 64) + !!ir (dst := AST.ite (tmp == AST.num0 2) (cster CastKind.FtoIRound) dst) + !!ir (dst := AST.ite (tmp == AST.num1 2) (cster CastKind.FtoIFloor) dst) + !!ir (dst := AST.ite (tmp == numI32 2 2) (cster CastKind.FtoICeil) dst) + !!ir (dst := AST.ite (tmp == numI32 3 2) (cster CastKind.FtoITrunc) dst) + !>ir insLen + +let pinsrb ins insLen ctxt = + let ir = IRBuilder (8) + let struct (dst, src, count) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ins insLen ctxt dst + let src = transOprToExpr ins insLen ctxt src + let count = transOprToExpr ins insLen ctxt count + let oprSize = getOperationSize ins + let struct (sel, mask, temp, tDst) = tmpVars4 ir oprSize + let sel8 = sel .* numI32 8 oprSize + ! 0) << sel8) .& mask) + !!ir (tDst := ((AST.concat dstB dstA) .& (AST.not mask)) .| temp) + !!ir (dstA := AST.xtlo 64 tDst) + !!ir (dstB := AST.xthi 64 tDst) + !>ir insLen + +let ptest ins insLen ctxt = + let ir = IRBuilder (16) + let struct (src1, src2) = getTwoOprs ins + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + let struct (t1, t2, t3, t4) = tmpVars4 ir 64 + !)) + !!ir (t3 := src2A .& AST.not src1A) + !!ir (t4 := src2B .& AST.not src1B) + !!ir (!.ctxt R.CF := (t3 .| t4) == (AST.num0 64)) + !!ir (!.ctxt R.AF := AST.b0) + !!ir (!.ctxt R.OF := AST.b0) + !!ir (!.ctxt R.PF := AST.b0) + !!ir (!.ctxt R.SF := AST.b0) + !>ir insLen + +let opPcmpeqq _ = opPcmp 64 (==) + +let pcmpeqq ins insLen ctxt = + buildPackedInstr ins insLen ctxt 64 opPcmpeqq 8 + +/// XXX (cleanup required) +/// imm8 control byte operation for PCMPESTRI, PCMPESTRM, etc.. +/// See Chapter 4.1 of the manual vol. 2B. +type Imm8ControlByte = { + PackSize : RegType + NumElems : uint32 + Sign : Sign + Agg : Agg + Polarity : Polarity + OutSelect : OutSelect + Len : Length + Ret : Return +} + +and Sign = + | Signed + | UnSigned + +and Agg = + | EqualAny + | Ranges + | EqualEach + | EqualOrdered + +and Polarity = + | PosPolarity + | NegPolarity + | PosMasked + | NegMasked + +and OutSelect = + | Least + | Most + +and Length = + | Implicit + | Explicit + +and Return = + | Index + | Mask + +let private getPcmpstrInfo opCode (imm: Expr) = + let immByte = match imm.E with + | Num n -> BitVector.getValue n + | _ -> raise InvalidExprException + let agg = match (immByte >>> 2) &&& 3I with + | v when v = 0I -> EqualAny + | v when v = 1I -> Ranges + | v when v = 2I -> EqualEach + | v when v = 3I -> EqualOrdered + | _ -> Utils.impossible () + let pol = match (immByte >>> 4) &&& 3I with + | v when v = 0I -> PosPolarity + | v when v = 1I -> NegPolarity + | v when v = 2I -> PosMasked + | v when v = 3I -> NegMasked + | _ -> Utils.impossible () + let size, nElem = + if immByte &&& 1I = 0I then 8, 16u else 16, 8u + let len, ret = + match opCode with + | Opcode.PCMPISTRI | Opcode.VPCMPISTRI -> Implicit, Index + | Opcode.PCMPESTRI | Opcode.VPCMPESTRI -> Explicit, Index + | Opcode.PCMPISTRM | Opcode.VPCMPISTRM -> Implicit, Mask + | Opcode.PCMPESTRM | Opcode.VPCMPESTRM -> Explicit, Mask + | _ -> raise InvalidOpcodeException + { PackSize = size + NumElems = nElem + Sign = if (immByte >>> 1) &&& 1I = 0I then UnSigned else Signed + Agg = agg + Polarity = pol + OutSelect = if (immByte >>> 6) &&& 1I = 0I then Least else Most + Len = len + Ret = ret } + +let private explicitValidCheck ctrl reg rSz ir = + let tmps = [| for _ in 1u .. ctrl.NumElems -> !*ir 1 |] + let checkNum = numU32 ctrl.NumElems rSz + let rec getValue idx = + let v = AST.lt (numU32 idx rSz) (AST.ite (AST.lt checkNum reg) checkNum reg) + if idx = ctrl.NumElems then () + else !!ir (tmps.[int idx] := v) + getValue (idx + 1u) + getValue 0u + tmps + +let private implicitValidCheck ctrl srcB srcA ir = + let unitWidth = RegType.toBitWidth ctrl.PackSize + let tmps = [| for _ in 1u .. ctrl.NumElems -> !*ir 1 |] + let getSrc idx e = AST.extract e ctrl.PackSize (unitWidth * idx) + let rec getValue idx = + if idx = int ctrl.NumElems then () + else + let half = int ctrl.NumElems / 2 + let e, amount = if idx < half then srcA, idx else srcB, idx - half + let v e = tmps.[idx - 1] .& (getSrc amount e != AST.num0 ctrl.PackSize) + !!ir (tmps.[idx] := v e) + getValue (idx + 1) + !!ir (tmps.[0] := AST.b1 .& (getSrc 0 srcA != AST.num0 ctrl.PackSize)) + getValue 1 + tmps + +let private genValidCheck ins insLen ctxt ctrl e1 e2 ir = + let src1B, src1A = transOprToExpr128 ins insLen ctxt e1 + let src2B, src2A = transOprToExpr128 ins insLen ctxt e2 + match ctrl.Len with + | Implicit -> implicitValidCheck ctrl src1B src1A ir, + implicitValidCheck ctrl src2B src2A ir + | Explicit -> + let regSize, ax, dx = + if hasREXW ins.REXPrefix + then 64, !.ctxt R.RAX, !.ctxt R.RDX + else 32, !.ctxt R.EAX, !.ctxt R.EDX + explicitValidCheck ctrl ax regSize ir, + explicitValidCheck ctrl dx regSize ir + +let private genBoolRes ins insLen ctrl ctxt e1 e2 (ck1: Expr []) (ck2: Expr []) j i cmp = + let src1B, src1A = transOprToExpr128 ins insLen ctxt e1 + let src2B, src2A = transOprToExpr128 ins insLen ctxt e2 + let elemSz = RegType.fromBitWidth <| int ctrl.NumElems + let getSrc s idx = + let unitWidth = RegType.toBitWidth ctrl.PackSize + let amount = unitWidth * idx + let amount = if amount < 64 then amount else amount - 64 + AST.extract s ctrl.PackSize amount + let b = + let e1 = if j < int ctrl.NumElems / 2 then src1A else src1B + let e2 = if i < int ctrl.NumElems / 2 then src2A else src2B + (AST.ite (cmp (getSrc e1 j) (getSrc e2 i)) (AST.num1 elemSz) (AST.num0 elemSz)) + match ctrl.Agg with + | EqualAny | Ranges -> + AST.ite (AST.not ck1.[j] .& AST.not ck2.[i]) (AST.num0 elemSz) + (AST.ite (AST.not ck1.[j] .| AST.not ck2.[i]) (AST.num0 elemSz) b) + | EqualEach -> + AST.ite (AST.not ck1.[i] .& AST.not ck2.[i]) (AST.num1 elemSz) + (AST.ite (AST.not ck1.[i] .| AST.not ck2.[i]) (AST.num0 elemSz) b) + | EqualOrdered -> + AST.ite (AST.not ck1.[j] .& AST.not ck2.[i]) (AST.num1 elemSz) + (AST.ite (AST.not ck1.[j] .& ck2.[i]) (AST.num1 elemSz) + (AST.ite (ck1.[j] .& AST.not ck2.[i]) (AST.num0 elemSz) b)) + +let private aggOpr ins insLen + ctxt ctrl src1 src2 ck1 ck2 (res1 : Expr []) ir = + let nElem = int ctrl.NumElems + let elemSz = RegType.fromBitWidth <| nElem + let boolRes = genBoolRes ins insLen ctrl ctxt src2 src1 ck2 ck1 + let rangesCmp idx = + match ctrl.Sign, idx % 2 = 0 with + | Signed, true -> AST.sge + | Signed, _ -> AST.sle + | _, true -> AST.ge + | _, _ -> AST.le + match ctrl.Agg with + | EqualAny -> + for j in 0 .. nElem - 1 do + let tRes = [| for _ in 1 .. nElem -> !*ir elemSz |] + let boolRes i = boolRes j i (==) + !!ir (tRes.[0] := AST.num0 elemSz .| boolRes 0) + for i in 1 .. nElem - 1 do + !!ir (tRes.[i] := tRes.[i - 1] .| boolRes i) + done + !!ir (res1.[j] := tRes.[nElem - 1] << numI32 j elemSz) + done + | EqualEach -> + for i in 0 .. nElem - 1 do + let boolRes i = boolRes i i (==) + !!ir (res1.[i] := boolRes i << numI32 i elemSz) + done + | EqualOrdered -> + for j in 0 .. nElem - 1 do + let tRes = [| for _ in 1 .. nElem -> !*ir elemSz |] + let boolRes k i = boolRes k i (==) + !!ir (tRes.[0] := numI32 -1 elemSz .& boolRes j 0) + for i in 1 .. nElem - 1 - j do + let k = i + j + !!ir (tRes.[i] := tRes.[i - 1] .& boolRes k i) + done + !!ir (res1.[j] := tRes.[nElem - 1] << numI32 j elemSz) + done + | Ranges -> + for j in 0 .. nElem - 1 do + let tRes = [| for _ in 1 .. nElem -> !*ir elemSz |] + let cmp i = rangesCmp i + let boolRes i = boolRes j i (cmp i) + !!ir (tRes.[0] := AST.num0 elemSz .| (boolRes 0 .& boolRes 1)) + for i in 2 .. 2 .. nElem - 1 do + !!ir + (tRes.[i] := tRes.[i - 1] .| (boolRes i .& boolRes (i + 1))) + done + !!ir (res1.[j] := tRes.[nElem - 1] << numI32 j elemSz) + done + +let private getIntRes2 e ctrInfo (booRes: Expr []) = + let elemSz = RegType.fromBitWidth <| int ctrInfo.NumElems + let elemCnt = ctrInfo.NumElems |> int + match ctrInfo.Polarity with + | PosPolarity | PosMasked -> e + | NegPolarity -> numI32 -1 elemSz <+> e + | NegMasked -> + List.fold (fun acc i -> + let e1 = e .& numI32 (pown 2 i) elemSz + let e2 = (AST.not e) .& numI32 (pown 2 i) elemSz + (AST.ite (booRes.[i]) e2 e1) :: acc) [] [0 .. elemCnt - 1] + |> List.reduce (.|) + +let rec private genOutput ctrl e acc i = + let elemSz = RegType.fromBitWidth <| int ctrl.NumElems + let isSmallOut = ctrl.OutSelect = Least + let e' = e >> numI32 i elemSz + let next = if isSmallOut then i - 1 else i + 1 + let cond = if isSmallOut then i = 0 else i = int ctrl.NumElems - 1 + if cond then AST.ite (AST.xtlo 1 e') (numI32 i elemSz) acc + else genOutput ctrl e (AST.ite (AST.xtlo 1 e') (numI32 i elemSz) acc) next + +let private pcmpStrRet (ins: InsInfo) info ctxt intRes2 ir = + let nElem = int info.NumElems + let elemSz = RegType.fromBitWidth <| nElem + match info.Ret with + | Index -> + let outSz, cx = + if hasREXW ins.REXPrefix then 64, R.RCX else 32, R.ECX + let cx = !.ctxt cx + let nMaxSz = numI32 nElem elemSz + let idx = if info.OutSelect = Least then nElem - 1 else 0 + let out = AST.zext outSz <| genOutput info intRes2 nMaxSz idx + !!ir (dstAssign outSz cx out) + | Mask -> + let xmmB, xmmA = getPseudoRegVar128 ctxt Register.XMM0 + let loop (acc1, acc2) i = + let src = AST.extract intRes2 1 i + if (i < nElem / 2) then (acc1, (AST.zext info.PackSize src) :: acc2) + else ((AST.zext info.PackSize src) :: acc1, acc2) + if info.OutSelect = Least then + !!ir (xmmA := AST.zext 64 intRes2) + !!ir (xmmB := AST.num0 64) + else let r1, r2 = List.fold loop ([], []) [0 .. nElem - 1] + !!ir (xmmB := AST.concatArr (List.toArray r1)) + !!ir (xmmA := AST.concatArr (List.toArray r2)) + +let private getZSFForPCMPSTR ins insLen ctrl ctxt src1 src2 ir = + let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + let getExZSFlag r = + let reg = !.ctxt r + AST.lt (AST.ite (AST.xthi 1 reg) (AST.neg reg) reg) + (numU32 ctrl.NumElems 32) + let rec getImZSFlag acc srcB srcA idx = + let packSz = ctrl.PackSize + let packWidth = RegType.toBitWidth packSz + let half = ctrl.NumElems / 2u |> int + let e, amount = if idx < half then srcA, idx else srcB, idx - half + let v e = e >> numI32 (amount * packWidth) 64 + let next, cond = idx - 1, idx = 0 + if cond then AST.ite (AST.xtlo packSz (v e) == AST.num0 packSz) AST.b1 acc + else let acc = AST.ite (AST.xtlo packSz (v e) == AST.num0 packSz) AST.b1 acc + getImZSFlag acc srcB srcA next + match ctrl.Len with + | Implicit -> + !!ir (!.ctxt R.ZF := + getImZSFlag AST.b0 src2B src2A (ctrl.NumElems - 1u |> int)) + !!ir (!.ctxt R.SF := + getImZSFlag AST.b0 src1B src1A (ctrl.NumElems - 1u |> int)) + | Explicit -> + !!ir (!.ctxt R.ZF := getExZSFlag R.EDX) + !!ir (!.ctxt R.SF := getExZSFlag R.EAX) + +let pcmpstr ins insLen ctxt = + let ir = IRBuilder (64) + ! !*ir elemSz |] + aggOpr ins insLen ctxt ctrl src1 src2 ck1 ck2 res1 ir + !!ir (intRes1 := Array.reduce (.|) res1) + !!ir (intRes2 := getIntRes2 intRes1 ctrl ck2) + pcmpStrRet ins ctrl ctxt intRes2 ir + !!ir (!.ctxt R.CF := intRes2 != AST.num0 elemSz) + getZSFForPCMPSTR ins insLen ctrl ctxt src1 src2 ir + !!ir (!.ctxt R.OF := AST.xtlo 1 intRes2) + !!ir (!.ctxt R.AF := AST.b0) + !!ir (!.ctxt R.PF := AST.b0) + !>ir insLen diff --git a/src/FrontEnd/Intel/IntelSupportedOpcodes.txt b/src/FrontEnd/BinLifter/Intel/IntelSupportedOpcodes.txt similarity index 93% rename from src/FrontEnd/Intel/IntelSupportedOpcodes.txt rename to src/FrontEnd/BinLifter/Intel/IntelSupportedOpcodes.txt index 0aed6494..4d8571b2 100644 --- a/src/FrontEnd/Intel/IntelSupportedOpcodes.txt +++ b/src/FrontEnd/BinLifter/Intel/IntelSupportedOpcodes.txt @@ -514,9 +514,9 @@ INSERTPS INSW /// Call to Interrupt (Interrupt vector specified by immediate byte). INT -/// Call to Interrupt (Interrupt 3—trap to debugger). +/// Call to Interrupt (Interrupt 3-trap to debugger). INT3 -/// Call to Interrupt (InteInterrupt 4—if overflow flag is 1). +/// Call to Interrupt (InteInterrupt 4-if overflow flag is 1). INTO /// Invalidate Internal Caches. INVD @@ -536,47 +536,42 @@ IRETD IRETQ /// Interrupt return (16-bit operand size). IRETW -/// Jump if Condition Is Met (Jump short if above, CF = 0 and ZF = 0). -JNBE -JA +/// Jump if Condition Is Met (Jump near if not below, CF = 0). +JAE +JNC +JNB /// Jump if Condition Is Met (Jump short if below, CF = 1). JC JNAE JB -/// Jump if Condition Is Met (Jump short if below or equal, CF = 1 or ZF). -JNA -JBE /// Jump if Condition Is Met (Jump short if CX register is 0). JCXZ /// Jump if Condition Is Met (Jump short if ECX register is 0). JECXZ -/// Jump if Condition Is Met (Jump short if RCX register is 0). -JRCXZ -/// Jump if Condition Is Met (Jump short if greater, ZF = 0 and SF = OF). -JNLE -JG -/// Jump if Condition Is Met (Jump short if less, SF <> OF). -JNGE -JL -/// Jump if Cond Is Met (Jump short if less or equal, ZF = 1 or SF <> OF). -JNG -JLE +/// Jump if Condition Is Met (Jump near if not less, SF = OF). +JGE +JNL /// Far jmp. JMPFar /// Near jmp. JMPNear -/// Jump if Condition Is Met (Jump near if not below, CF = 0). -JAE -JNC -JNB -/// Jump if Condition Is Met (Jump near if not less, SF = OF). -JGE -JNL +/// Jump if Condition Is Met (Jump short if below or equal, CF = 1 or ZF). +JNA +JBE +/// Jump if Condition Is Met (Jump short if above, CF = 0 and ZF = 0). +JNBE +JA +/// Jump if Cond Is Met (Jump short if less or equal, ZF = 1 or SF <> OF). +JNG +JLE +/// Jump if Condition Is Met (Jump short if less, SF <> OF). +JNGE +JL +/// Jump if Condition Is Met (Jump short if greater, ZF = 0 and SF = OF). +JNLE +JG /// Jump if Condition Is Met (Jump near if not overflow, OF = 0). JNO -/// Jump if Condition Is Met (Jump near if not parity, PF = 0). -JPO -JNP /// Jump if Condition Is Met (Jump near if not sign, SF = 0). JNS /// Jump if Condition Is Met (Jump near if not zero, ZF = 0). @@ -587,6 +582,11 @@ JO /// Jump if Condition Is Met (Jump near if parity, PF = 1). JP JPE +/// Jump if Condition Is Met (Jump near if not parity, PF = 0). +JPO +JNP +/// Jump if Condition Is Met (Jump short if RCX register is 0). +JRCXZ /// Jump if Condition Is Met (Jump short if sign, SF = 1). JS /// Jump if Condition Is Met (Jump short if zero, ZF = 1). @@ -1426,10 +1426,22 @@ VANDPS VBLENDMPD /// Replace the VBLENDVPS instructions (using opmask as select control). VBLENDMPS +/// Variable Blend Packed Double-Precision Floats. +VBLENDVPD /// Broadcast 128 bits of int data in mem to low and high 128-bits in ymm1. VBROADCASTI128 +/// Broadcast low double-precision floating-point element. +VBROADCASTSD /// Broadcast Floating-Point Data. VBROADCASTSS +/// Compare Packed Double-Precision Floating-Point Values. +VCMPPD +/// Compare Packed Single-Precision Floating-Point Values. +VCMPPS +/// Compare Scalar Double-Precision Floating-Point Values. +VCMPSD +/// Scalar Single-Precision Floating-Point Values. +VCMPSS /// Compare Scalar Ordered Double-Precision FP Values and Set EFLAGS. VCOMISD /// Compare Scalar Ordered Single-Precision FP Values and Set EFLAGS. @@ -1438,6 +1450,12 @@ VCOMISS VCOMPRESSPD /// Compress packed SP elements of a vector. VCOMPRESSPS +/// Convert two packed signed doubleword integers. +VCVTDQ2PD +/// Convert Packed Dword Integers to Packed Single-Precision FP Values. +VCVTDQ2PS +/// Convert two packed double-precision floating-point values. +VCVTPD2PS /// Convert Packed Double-Precision FP Values to Packed Quadword Integers. VCVTPD2QQ /// Convert Packed DP FP Values to Packed Unsigned DWord Integers. @@ -1446,6 +1464,8 @@ VCVTPD2UDQ VCVTPD2UQQ /// Convert 16-bit FP values to Single-Precision FP values. VCVTPH2PS +/// Convert Packed Single-Precision FP Values to Packed Dbl-Precision FP Values. +VCVTPS2PD /// Convert Single-Precision FP value to 16-bit FP value. VCVTPS2PH /// Convert Packed SP FP Values to Packed Signed QWord Int Values. @@ -1474,6 +1494,8 @@ VCVTSS2SD VCVTSS2SI /// Convert Scalar Single-Precision FP Value to Unsigned Doubleword Integer. VCVTSS2USI +/// Convert with Trunc Packed Double-Precision FP Val to Packed Dword Integers. +VCVTTPD2DQ /// Convert with Truncation Packed DP FP Values to Packed QWord Integers. VCVTTPD2QQ /// Convert with Truncation Packed DP FP Values to Packed Unsigned DWord Int. @@ -1532,14 +1554,20 @@ VEXP2SS VEXPANDPD /// Load Sparse Packed Single-Precision FP Values from Dense Memory. VEXPANDPS +/// Extract Packed Floating-Point Values. +VEXTRACTF128 /// Extract a vector from a full-length vector with 32-bit granular update. VEXTRACTF32X4 +/// Extract a vector from a full-length vector with 32-bit granular update. +VEXTRACTF32X8 /// Extract a vector from a full-length vector with 64-bit granular update. VEXTRACTF64X2 /// Extract a vector from a full-length vector with 64-bit granular update. VEXTRACTF64X4 /// Extract a vector from a full-length vector with 32-bit granular update. VEXTRACTI32X4 +/// Extract a vector from a full-length vector with 32-bit granular update. +VEXTRACTI32X8 /// Extract a vector from a full-length vector with 64-bit granular update. VEXTRACTI64X2 /// Extract a vector from a full-length vector with 64-bit granular update. @@ -1552,18 +1580,48 @@ VFIXUPIMMPS VFIXUPIMMSD /// Fix Up Special Scalar Float32 Value. VFIXUPIMMSS +/// Fused Multiply-Add of Packed Double-Precision Floating-Point Values. +VFMADD132PD /// Fused Multiply-Add of Scalar Double-Precision Floating-Point Values. VFMADD132SD /// Fused Multiply-Add of Scalar Single-Precision Floating-Point Values. VFMADD132SS +/// Fused Multiply-Add of Packed Double-Precision Floating-Point Values. +VFMADD213PD +/// Fused Multiply-Add of Packed Single-Precision Floating-Point Values. +VFMADD213PS /// Fused Multiply-Add of Scalar Double-Precision Floating-Point Values. VFMADD213SD /// Fused Multiply-Add of Scalar Single-Precision Floating-Point Values. VFMADD213SS +/// Fused Multiply-Add of Packed Double-Precision Floating-Point Value. +VFMADD231PD /// Fused Multiply-Add of Scalar Double-Precision Floating-Point Values. VFMADD231SD /// Fused Multiply-Add of Scalar Single-Precision Floating-Point Values. VFMADD231SS +/// Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values. +VFMSUB132SS +/// Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values. +VFMSUB213PD +/// Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values. +VFMSUB213SD +/// Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values. +VFMSUB231PD +/// Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values. +VFMSUB231SD +/// Fused Negative Multiply-Add of Packed Double-Precision FP Values. +VFNMADD132PD +/// Fused Negative Multiply-Add of Scalar Double-Precision FP Values. +VFNMADD132SD +/// Fused Negative Multiply-Add of Packed Double-Precision FP Values. +VFNMADD213PD +/// Fused Negative Multiply-Add of Scalar Double-Precision FP Values. +VFNMADD213SD +/// Fused Negative Multiply-Add of Packed Double-Precision FP Values. +VFNMADD231PD +/// Fused Negative Multiply-Add of Scalar Double-Precision FP Values. +VFNMADD231SD /// Tests Types Of a Packed Float64 Values. VFPCLASSPD /// Tests Types Of a Packed Float32 Values. @@ -1572,6 +1630,10 @@ VFPCLASSPS VFPCLASSSD /// Tests Types Of a Scalar Float32 Values. VFPCLASSSS +/// Gather Packed SP FP values Using Signed Dword/Qword Indices. +VGATHERDPS +/// Gather Packed DP FP Values Using Signed Dword/Qword Indices. +VGATHERQPD /// Convert Exponents of Packed DP FP Values to DP FP Values. VGETEXPPD /// Convert Exponents of Packed SP FP Values to SP FP Values. @@ -1589,6 +1651,8 @@ VGETMANTSD /// Extract Float32 Vector of Normalized Mantissa from Float32 Vector. VGETMANTSS /// Insert Packed Floating-Point Values. +VINSERTF128 +/// Insert Packed Floating-Point Values. VINSERTF32X4 /// Insert Packed Floating-Point Values. VINSERTF64X2 @@ -1596,16 +1660,36 @@ VINSERTF64X2 VINSERTF64X4 /// Insert Packed Integer Values. VINSERTI128 +/// Insert 256 bits of packed doubleword integer values. +VINSERTI32X8 /// Insert Packed Floating-Point Values. VINSERTI64X2 +/// Insert 256 bits of packed quadword integer values. +VINSERTI64X4 /// Load Unaligned Integer 128 Bits. VLDDQU +/// Return Maximum Packed Double-Precision Floating-Point Values. +VMAXPD +/// Maximum of Packed Single-Precision Floating-Point Values. +VMAXPS +/// Return Maximum Scalar Double-Precision Floating-Point Value. +VMAXSD +/// Return Maximum Scalar Single-Precision Floating-Point Value. +VMAXSS /// Call to VM Monitor. VMCALL /// Clear Virtual-Machine Control Structure. VMCLEAR /// Invoke VM function. VMFUNC +/// Return Minimum Packed Double-Precision Floating-Point Values. +VMINPD +/// Return Minimum Packed Single-Precision Floating-Point Values. +VMINPS +/// Return Minimum Scalar Double-Precision Floating-Point Value. +VMINSD +/// Return Minimum Scalar Single-Precision Floating-Point Value. +VMINSS /// Launch Virtual Machine. VMLAUNCH /// Move Aligned Packed Double-Precision Floating-Point Values. @@ -1826,8 +1910,12 @@ VPERMW VPEXPANDD /// Load Sparse Packed Quadword Integer Values from Dense Memory / Register. VPEXPANDQ +/// Extract DWord. +VPEXTRD /// Extract Word. VPEXTRW +/// Gather packed dword values using signed Dword/Qword indices. +VPGATHERDD /// Packed Horizontal Add (32-bit). VPHADDD /// Packed Horizontal Add and Saturate (16-bit). @@ -1838,12 +1926,16 @@ VPHADDW VPHMINPOSUW /// Packed Horizontal Subtract (32-bit). VPHSUBD -/// Packed Horizontal Subtract and Saturate (16-bit) +/// Packed Horizontal Subtract and Saturate (16-bit). VPHSUBSW /// Packed Horizontal Subtract (16-bit). VPHSUBW /// Insert Byte. VPINSRB +/// Insert Dword. +VPINSRD +/// Insert Qword. +VPINSRQ /// Insert Word. VPINSRW /// Count the number of leading zero bits of packed dword elements. @@ -1940,9 +2032,9 @@ VPMOVUSDB VPMOVUSDW /// Down Convert QWord to Byte. VPMOVUSQB -/// Down Convert QWord to DWord +/// Down Convert QWord to DWord. VPMOVUSQD -/// Down Convert QWord to Dword. +/// Down Convert QWord to Word. VPMOVUSQW /// Down Convert Word to Byte. VPMOVUSWB @@ -2070,6 +2162,8 @@ VPSUBW VPTERLOGD /// Perform bitwise ternary logic operation of three vectors. VPTERLOGQ +/// Bitwise Ternary Logic. +VPTERNLOGD /// Logical Compare. VPTEST /// Perform bitwise AND of byte elems of two vecs and write results to opmask. @@ -2106,6 +2200,10 @@ VPUNPCKLQDQ VPUNPCKLWD /// Logical Exclusive OR. VPXOR +/// Bitwise XOR of packed doubleword integers. +VPXORD +/// Bitwise XOR of packed quadword integers. +VPXORQ /// Range Restriction Calculation For Packed Pairs of Float64 Values. VRANGEPD /// Range Restriction Calculation For Packed Pairs of Float32 Values. @@ -2130,6 +2228,10 @@ VRCP28PS VRCP28SD /// Computes the reciprocal approximation of the low float32 value. VRCP28SS +/// Compute reciprocals of packed single-precision floating-point values. +VRCPPS +/// Compute Reciprocal of Scalar Single-Precision Floating-Point Values. +VRCPSS /// Perform Reduction Transformation on Packed Float64 Values. VREDUCEPD /// Perform Reduction Transformation on Packed Float32 Values. @@ -2146,6 +2248,12 @@ VRNDSCALEPS VRNDSCALESD /// Round Scalar Float32 Value To Include A Given Number Of Fraction Bits. VRNDSCALESS +/// Round Packed Double-Precision Values. +VROUNDPD +/// Round Packed Single-Precision Values. +VROUNDPS +/// Round Scalar Double-Precision Value. +VROUNDSD /// Compute Approximate Reciprocals of Square Roots of Packed Float64 Values. VRSQRT14PD /// Compute Approximate Reciprocals of Square Roots of Packed Float32 Values. @@ -2162,6 +2270,10 @@ VRSQRT28PS VRSQRT28SD /// Computes the reciprocal square root of the low float32 value. VRSQRT28SS +/// Compute Reciprocals of Square Roots of Packed Single-Precision FP Values. +VRSQRTPS +/// Compute Reciprocal of Square Root of Scalar Single-Precision FP Value. +VRSQRTSS /// Multiply packed DP FP elements of a vector by powers. VSCALEPD /// Multiply packed SP FP elements of a vector by powers. diff --git a/src/FrontEnd/BinLifter/Intel/IntelTypes.fs b/src/FrontEnd/BinLifter/Intel/IntelTypes.fs new file mode 100644 index 00000000..f2739ada --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelTypes.fs @@ -0,0 +1,316 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.Intel + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Instruction prefixes. +[] +type Prefix = + /// No prefix. + | PrxNone = 0x0 + /// Lock prefix. + | PrxLOCK = 0x1 + /// REPNE/REPNZ prefix is encoded using F2H. + | PrxREPNZ = 0x2 + /// Bound prefix is encoded using F2H. + | PrxBND = 0x4 + /// REP or REPE/REPZ is encoded using F3H. + | PrxREPZ = 0x8 + /// CS segment prefix. + | PrxCS = 0x10 + /// SS segment prefix. + | PrxSS = 0x20 + /// DS segment prefix. + | PrxDS = 0x40 + /// ES segment prefix. + | PrxES = 0x80 + /// FS segment prefix. + | PrxFS = 0x100 + /// GS segment prefix. + | PrxGS = 0x200 + /// Operand-size override prefix is encoded using 66H. + | PrxOPSIZE = 0x400 + /// 67H - Address-size override prefix. + | PrxADDRSIZE = 0x800 + +/// REX prefixes. +type REXPrefix = + /// No REX: this is to represent the case where there is no REX + | NOREX = 0b0000000 + /// Extension of the ModR/M reg, Opcode reg field (SPL, BPL, ...). + | REX = 0b1000000 + /// Extension of the ModR/M rm, SIB base, Opcode reg field. + | REXB = 0b1000001 + /// Extension of the SIB index field. + | REXX = 0b1000010 + /// Extension of the ModR/M SIB index, base field. + | REXXB = 0b1000011 + /// Extension of the ModR/M reg field. + | REXR = 0b1000100 + /// Extension of the ModR/M reg, r/m field. + | REXRB = 0b1000101 + /// Extension of the ModR/M reg, SIB index field. + | REXRX = 0b1000110 + /// Extension of the ModR/M reg, SIB index, base. + | REXRXB = 0b1000111 + /// Operand 64bit. + | REXW = 0b1001000 + /// REX.B + Operand 64bit. + | REXWB = 0b1001001 + /// REX.X + Operand 64bit. + | REXWX = 0b1001010 + /// REX.XB + Operand 64bit. + | REXWXB = 0b1001011 + /// REX.R + Operand 64bit. + | REXWR = 0b1001100 + /// REX.RB + Operand 64bit. + | REXWRB = 0b1001101 + /// REX.RX + Operand 64bit. + | REXWRX = 0b1001110 + /// REX.RXB + Operand 64bit. + | REXWRXB = 0b1001111 + +/// We define 8 different RegGrp types. Intel instructions use an integer value +/// such as a REG field of a ModR/M value. +type RegGrp = + /// AL/AX/EAX/... + | RG0 = 0 + /// CL/CX/ECX/... + | RG1 = 1 + /// DL/DX/EDX/... + | RG2 = 2 + /// BL/BX/EBX/... + | RG3 = 3 + /// AH/SP/ESP/... + | RG4 = 4 + /// CH/BP/EBP/... + | RG5 = 5 + /// DH/SI/ESI/... + | RG6 = 6 + /// BH/DI/EDI/... + | RG7 = 7 + +/// Opcode groups defined in manual Vol 2. Table A-6. +type OpGroup = + | G1 = 0 + | G1Inv64 = 1 + | G1A = 2 + | G2 = 3 + | G3A = 4 + | G3B = 5 + | G4 = 6 + | G5 = 7 + | G6 = 8 + | G7 = 9 + | G8 = 10 + | G9 = 11 + | G10 = 12 + | G11A = 13 + | G11B = 14 + | G12 = 15 + | G13 = 16 + | G14 = 17 + | G15 = 18 + | G16 = 19 + | G17 = 20 + +/// The scale of Scaled Index. +type Scale = + /// Times 1 + | X1 = 1 + /// Times 2 + | X2 = 2 + /// Times 4 + | X4 = 4 + /// Times 8 + | X8 = 8 + +/// Scaled index. +type ScaledIndex = Register * Scale + +/// Jump target of a branch instruction. +type JumpTarget = + | Absolute of Selector * Addr * OperandSize + | Relative of Offset +and Selector = int16 +and Offset = int64 +and OperandSize = RegType + +/// We define four different types of X86 operands: +/// register, memory, direct address, and immediate. +type Operand = + /// A register operand. + | OprReg of Register + /// OprMem represents a memory operand. The OperandSize here means the memory + /// access size of the operand, i.e., how many bytes do we read/write here. + | OprMem of Register option * ScaledIndex option * Disp option * OperandSize + /// OprDirAddr is a direct branch target address. + | OprDirAddr of JumpTarget + /// OprImm represents an immediate operand. The OperandSize here means the + /// size of the encoded immediate value. + | OprImm of int64 * OperandSize + /// Label is *not* encoded in the actual binary. This is only used when we + /// assemble binaries. + | Label of string * RegType +/// Displacement. +and Disp = int64 + +/// A set of operands in an X86 instruction. +type Operands = + | NoOperand + | OneOperand of Operand + | TwoOperands of Operand * Operand + | ThreeOperands of Operand * Operand * Operand + | FourOperands of Operand * Operand * Operand * Operand + +/// Specific conditions for determining the size of operands. +/// (See Table A-1, Appendix A.2.5 of Vol. 2D). +type SzCond = + /// (d64) When in 64-bit mode, instruction defaults to 64-bit operand size and + /// cannot encode 32-bit operand size. + | D64 = 0 + /// (f64) The operand size is forced to a 64-bit operand size when in 64-bit + /// mode (prefixes that change operand size, e.g., 66 prefix, are ignored for + /// this instruction in 64-bit mode). + | F64 = 1 + /// Normal conditions. This includes all other size conditions in Table A-1. + | Nor = 2 + +/// Types of VEX (Vector Extension). +[] +type VEXType = + /// Original VEX that refers to two-byte opcode map. + | VEXTwoByteOp = 0x1 + /// Original VEX that refers to three-byte opcode map #1. + | VEXThreeByteOpOne = 0x2 + /// Original VEX that refers to three-byte opcode map #2. + | VEXThreeByteOpTwo = 0x4 + /// EVEX Mask + | EVEX = 0x10 + +/// Intel's memory operand is represented by two tables (ModR/M and SIB table). +/// Some memory operands do need SIB table lookups, whereas some memory operands +/// only need to look up the ModR/M table. +type internal MemLookupType = + | SIB (* Need SIB lookup *) + | NOSIB of RegGrp option (* No need *) + +/// Vector destination merging/zeroing: P[23] encodes the destination result +/// behavior which either zeroes the masked elements or leave masked element +/// unchanged. +type ZeroingOrMerging = + | Zeroing + | Merging + +type EVEXPrefix = { + /// Embedded opmask register specifier, P[18:16]. + AAA: uint8 + /// Zeroing/Merging, P[23]. + Z: ZeroingOrMerging + /// Broadcast/RC/SAE Context, P[20]. + B: uint8 +} + +/// Information about Intel vector extension. +type VEXInfo = { + VVVV: byte + VectorLength: RegType + VEXType: VEXType + VPrefixes: Prefix + EVEXPrx: EVEXPrefix option +} + +/// Mandatory prefixes. The 66H, F2H, and F3H prefixes are mandatory for opcode +/// extensions. +type MPref = + /// Indicates the use of 66/F2/F3 prefixes (beyond those already part of the + /// instructions opcode) are not allowed with the instruction. + | MPrxNP = 0 + /// 66 prefix. + | MPrx66 = 1 + /// F3 prefix. + | MPrxF3 = 2 + /// F2 prefix. + | MPrxF2 = 3 + /// 66 & F2 prefix. + | MPrx66F2 = 4 + +[] +type IntelInternalInstruction + (addr, len, wordSz, pref, rex, vex, opcode, oprs, opsz, psz) = + inherit Instruction (addr, len, wordSz) + + /// Prefixes. + member __.Prefixes with get(): Prefix = pref + + /// REX Prefix. + member __.REXPrefix with get(): REXPrefix = rex + + /// VEX information. + member __.VEXInfo with get(): VEXInfo option = vex + + /// Opcode. + member __.Opcode with get(): Opcode = opcode + + /// Operands. + member __.Operands with get(): Operands = oprs + + /// Size of the main operation performed by the instruction. This field is + /// mainly used by our lifter, and we suggest not to use this field for + /// analyzing binaries because there is some ambiguity in deciding the + /// operation size when the instruction semantics are complex. We use this + /// only for the purpose of optimizing the lifting process. + member __.MainOperationSize with get(): RegType = opsz + + /// Size of the memory pointer in the instruction, i.e., how many bytes are + /// required to represent a memory address. This field may hold a dummy value + /// if there's no memory operand. This is mainly used for the lifting purpose + /// along with the MainOperationSize. + member __.PointerSize with get(): RegType = psz + + override __.Equals (rhs) = + match rhs with + | :? IntelInternalInstruction as rhs -> + __.Prefixes = rhs.Prefixes + && __.REXPrefix = rhs.REXPrefix + && __.VEXInfo = rhs.VEXInfo + && __.Opcode = rhs.Opcode + && __.Operands = rhs.Operands + | _ -> false + + override __.GetHashCode () = + let hash = System.HashCode () + hash.Add __.Prefixes + hash.Add __.REXPrefix + hash.Add __.VEXInfo + hash.Add __.Opcode + hash.Add __.Operands + hash.ToHashCode () + +type internal InsInfo = IntelInternalInstruction + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Intel/IntelX87Lifter.fs b/src/FrontEnd/BinLifter/Intel/IntelX87Lifter.fs new file mode 100644 index 00000000..e57ff7a5 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelX87Lifter.fs @@ -0,0 +1,1505 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.Intel.X87Lifter + +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.FrontEnd.BinLifter.Intel.Helper +open B2R2.FrontEnd.BinLifter.Intel.LiftingUtils + +let private undefC0 = AST.undef 1 "C0 is undefined." + +let private undefC1 = AST.undef 1 "C1 is undefined." + +let private undefC2 = AST.undef 1 "C2 is undefined." + +let private undefC3 = AST.undef 1 "C3 is undefined." + +let private allCFlagsUndefined ctxt ir = + !!ir (!.ctxt R.FSWC0 := undefC0) + !!ir (!.ctxt R.FSWC1 := undefC1) + !!ir (!.ctxt R.FSWC2 := undefC2) + !!ir (!.ctxt R.FSWC3 := undefC3) + +let private cflagsUndefined023 ctxt ir = + !!ir (!.ctxt R.FSWC0 := undefC0) + !!ir (!.ctxt R.FSWC2 := undefC2) + !!ir (!.ctxt R.FSWC3 := undefC3) + +let private getFPUPseudoRegVars ctxt r = + getPseudoRegVar ctxt r 2, getPseudoRegVar ctxt r 1 + +let private checkC1Flag ctxt ir topTagReg = + let c1 = !.ctxt R.FSWC1 + let tagV = !.ctxt topTagReg + let rc = AST.extract (!.ctxt R.FCW) 2 10 + !!ir (c1 := AST.ite (rc == numI32 2 2) AST.b1 AST.b0) + !!ir (c1 := AST.ite (tagV == numI32 3 2) AST.b0 c1) + +let private checkFPUOnLoad ctxt ir = + let top = !.ctxt R.FTOP + let c1Flag = !.ctxt R.FSWC1 + let struct (cond1, cond2) = tmpVars2 ir 1 + !!ir (cond1 := top == AST.num0 3) + !!ir (cond2 := (!.ctxt R.FTW0 .+ AST.num1 2) != AST.num0 2) + !!ir (c1Flag := AST.ite (cond1 .& cond2) AST.b1 AST.b0) + !!ir (!.ctxt R.FSWC0 := undefC0) + !!ir (!.ctxt R.FSWC2 := undefC2) + !!ir (!.ctxt R.FSWC3 := undefC3) + !!ir (top := top .- AST.num1 3) + +let private fpuRegValue ctxt reg = + let stb, sta = getFPUPseudoRegVars ctxt reg + AST.concat stb sta + +let private assignFPUReg reg expr80 ctxt ir = + let stb, sta = getFPUPseudoRegVars ctxt reg + !!ir (sta := AST.xtlo 64 expr80) + !!ir (stb := AST.xthi 16 expr80) + +let private getTagValueOnLoad ctxt ir = + let tmp = !*ir 2 + let st0 = fpuRegValue ctxt R.ST0 + let exponent = AST.extract st0 11 52 + let zero = AST.num0 11 + let max = BitVector.unsignedMax 11 |> AST.num + let cond0 = (AST.xtlo 63 st0) == AST.num0 63 + let condSpecial = (exponent == zero) .| (exponent == max) + !!ir (tmp := AST.num0 2) + !!ir (tmp := AST.ite condSpecial (BitVector.ofInt32 2 2 |> AST.num) tmp) + !!ir (tmp := AST.ite cond0 (AST.num1 2) tmp) + tmp + +let private updateTagWordOnLoad ctxt ir = + let top = !.ctxt R.FTOP + let tagWord = !.ctxt R.FTW + let struct (top16, mask, shifter, tagValue16) = tmpVars4 ir 16 + let tagValue = getTagValueOnLoad ctxt ir + let value3 = BitVector.ofInt32 3 16 |> AST.num + !!ir (top16 := AST.cast CastKind.ZeroExt 16 top) + !!ir (shifter := (BitVector.ofInt32 2 16 |> AST.num) .* top16) + !!ir (tagValue16 := AST.cast CastKind.ZeroExt 16 tagValue) + !!ir (tagValue16 := (tagValue16 << shifter)) + !!ir (mask := value3 << shifter) + !!ir (tagWord := tagWord .& (AST.not mask)) + !!ir (tagWord := tagWord .| tagValue16) + +let private updateTagWordOnPop ctxt ir = + let top = !.ctxt R.FTOP + let tagWord = !.ctxt R.FTW + let struct (top16, mask, shifter, tagValue16) = tmpVars4 ir 16 + let value3 = BitVector.ofInt32 3 16 |> AST.num + !!ir (top16 := AST.cast CastKind.ZeroExt 16 top) + !!ir (shifter := (BitVector.ofInt32 2 16 |> AST.num) .* top16) + !!ir (mask := value3 << shifter) + !!ir (tagWord := tagWord .| mask) + +let private shiftFPUStackDown ctxt ir = + !?ir (assignFPUReg R.ST7 (fpuRegValue ctxt R.ST6) ctxt) + !?ir (assignFPUReg R.ST6 (fpuRegValue ctxt R.ST5) ctxt) + !?ir (assignFPUReg R.ST5 (fpuRegValue ctxt R.ST4) ctxt) + !?ir (assignFPUReg R.ST4 (fpuRegValue ctxt R.ST3) ctxt) + !?ir (assignFPUReg R.ST3 (fpuRegValue ctxt R.ST2) ctxt) + !?ir (assignFPUReg R.ST2 (fpuRegValue ctxt R.ST1) ctxt) + !?ir (assignFPUReg R.ST1 (fpuRegValue ctxt R.ST0) ctxt) + +let private popFPUStack ctxt ir = + let top = !.ctxt R.FTOP + let c1Flag = !.ctxt R.FSWC1 + let struct (cond1, cond2) = tmpVars2 ir 1 + !?ir (assignFPUReg R.ST0 (fpuRegValue ctxt R.ST1) ctxt) + !?ir (assignFPUReg R.ST1 (fpuRegValue ctxt R.ST2) ctxt) + !?ir (assignFPUReg R.ST2 (fpuRegValue ctxt R.ST3) ctxt) + !?ir (assignFPUReg R.ST3 (fpuRegValue ctxt R.ST4) ctxt) + !?ir (assignFPUReg R.ST4 (fpuRegValue ctxt R.ST5) ctxt) + !?ir (assignFPUReg R.ST5 (fpuRegValue ctxt R.ST6) ctxt) + !?ir (assignFPUReg R.ST6 (fpuRegValue ctxt R.ST7) ctxt) + !?ir (assignFPUReg R.ST7 (AST.num0 80) ctxt) + !!ir (cond1 := top == AST.num0 3) + !!ir (cond2 := (!.ctxt R.FTW7 .+ AST.num1 2) == AST.num0 2) + !!ir (c1Flag := AST.ite (cond1 .& cond2) (AST.b0) (c1Flag)) + !!ir (!.ctxt R.FSWC0 := undefC0) + !!ir (!.ctxt R.FSWC2 := undefC2) + !!ir (!.ctxt R.FSWC3 := undefC3) + updateTagWordOnPop ctxt ir + !!ir (top := top .+ AST.num1 3) + +let private updateAddrByOffset addr offset = + match addr.E with + (* Save *) + | Load (_, _, { E = BinOp (_, _, { E = BinOp (_, _, reg, _, _) }, _, _) }, _) + -> reg := reg .+ offset (* SIB *) + | Load (_, _, { E = BinOp (_, _, e, _, _) }, _) -> + e := e .+ offset (* Displacemnt *) + | Load (_, _, expr, _) -> expr := expr .+ offset + | _ -> Utils.impossible () + +let private getAddrRegSize e = + match e.E with + (* Save *) + | Load (_, _, { E = Var (t, _, _, _) }, _) -> t + | Load (_, _, { E = BinOp (_, t, _, _, _) }, _) -> t + (* Load *) + | TempVar (t, _) -> t + | _ -> Utils.impossible () + +let private getBaseReg e = + match e.E with + | Load (_, _, { E = BinOp (_, _, { E = BinOp (_, _, reg, _, _) }, _, _) }, _) + -> reg + | Load (_, _, { E = BinOp (_, _, e, _, _) }, _) -> e + | Load (_, _, expr, _) -> expr + | _ -> Utils.impossible () + +let private extendAddr src regType = + match src.E with + | Load (e, _, expr, _) -> AST.load e regType expr + | _ -> Utils.impossible () + +let private m14Stenv dst ctxt ir = + let tmp = !*ir 112 + !!ir (tmp := AST.num0 112) + !!ir (AST.xtlo 48 tmp := + AST.concat (!.ctxt R.FCW) (AST.concat (!.ctxt R.FSW) (!.ctxt R.FTW))) + !!ir (AST.extract tmp 16 48 := AST.xtlo 16 (!.ctxt R.FIP)) + !!ir (AST.extract tmp 11 64 := AST.xtlo 11 (!.ctxt R.FOP)) + !!ir (AST.extract tmp 4 76 := AST.extract (!.ctxt R.FIP) 4 16) + !!ir (AST.extract tmp 16 80 := AST.xtlo 16 (!.ctxt R.FDP)) + !!ir (AST.xthi 4 tmp := AST.extract (!.ctxt R.FDP) 4 16) + !!ir (dst := tmp) + +let private m14fldenv src ctxt ir = + let tmp = !*ir 112 + !!ir (tmp := src) + !!ir (!.ctxt R.FCW := AST.xtlo 16 tmp) + !!ir (!.ctxt R.FSW := AST.extract tmp 16 16) + !!ir (!.ctxt R.FTW := AST.extract tmp 16 32) + !!ir (AST.xtlo 16 (!.ctxt R.FIP) := AST.extract tmp 16 48) + !!ir (AST.xtlo 11 (!.ctxt R.FOP) := AST.extract tmp 11 64) + !!ir (AST.extract (!.ctxt R.FIP) 4 16 := AST.extract tmp 4 76) + !!ir (AST.xtlo 16 (!.ctxt R.FDP) := AST.extract tmp 16 80) + !!ir (AST.extract (!.ctxt R.FDP) 4 16 := AST.xthi 4 tmp) + +let private m28fldenv src ctxt ir = + let tmp = !*ir 224 + !!ir (tmp := src) + !!ir (!.ctxt R.FCW := AST.xtlo 16 tmp) + !!ir (!.ctxt R.FSW := AST.extract tmp 16 32) + !!ir (!.ctxt R.FTW := AST.extract tmp 16 64) + !!ir (AST.xtlo 16 (!.ctxt R.FIP) := AST.extract tmp 16 96) + !!ir (AST.xtlo 11 (!.ctxt R.FOP) := AST.extract tmp 11 128) + !!ir (AST.extract (!.ctxt R.FIP) 16 16 := AST.extract tmp 16 139) + !!ir (AST.xtlo 16 (!.ctxt R.FDP) := AST.extract tmp 16 160) + !!ir (AST.extract (!.ctxt R.FDP) 16 16 := AST.extract tmp 16 204) + +let private m28fstenv dst ctxt ir = + let tmp = !*ir 224 + !!ir (tmp := AST.num0 224) + !!ir (AST.xtlo 16 tmp := !.ctxt R.FCW) + !!ir (AST.extract tmp 16 32 := !.ctxt R.FSW) + !!ir (AST.extract tmp 16 64 := !.ctxt R.FTW) + !!ir (AST.extract tmp 16 96 := AST.xtlo 16 (!.ctxt R.FIP)) + !!ir (AST.extract tmp 11 128 := AST.xtlo 11 (!.ctxt R.FOP)) + !!ir (AST.extract tmp 16 139 := AST.extract (!.ctxt R.FIP) 16 16) + !!ir (AST.extract tmp 16 160 := AST.xtlo 16 (!.ctxt R.FDP)) + !!ir (AST.extract tmp 16 204 := AST.extract (!.ctxt R.FDP) 16 16) + !!ir (dst := tmp) + +let private ftrig _ins insLen ctxt trigFunc = + let ir = IRBuilder (32) + let st0 = fpuRegValue ctxt R.ST0 + let float80SignUnmask = BitVector.signedMax 80 |> AST.num + let maxLimit = numI64 (1L <<< 63) 64 + let maxFloat = AST.cast CastKind.IntToFloat 80 maxLimit + let num3 = BitVector.ofInt32 3 2 |> AST.num + let c0 = !.ctxt R.FSWC0 + let c1 = !.ctxt R.FSWC1 + let c2 = !.ctxt R.FSWC2 + let c3 = !.ctxt R.FSWC3 + let lblOutOfRange = ir.NewSymbol "IsOutOfRange" + let lblInRange = ir.NewSymbol "IsInRange" + let tmp = !*ir 80 + !ir insLen + +let private fpuFBinOp (ins: InsInfo) insLen ctxt binOp doPop leftToRight = + let ir = IRBuilder (64) + let res = !*ir 80 + ! + let st0 = fpuRegValue ctxt R.ST0 + let st1 = fpuRegValue ctxt R.ST1 + if leftToRight then !!ir (res := binOp st0 st1) + else !!ir (res := binOp st1 st0) + !?ir (assignFPUReg R.ST1 res ctxt) + !?ir (checkC1Flag ctxt) R.FTW6 + | OneOperand opr -> + let oprExpr = transOprToFloat80 ins insLen ctxt opr + let st0 = fpuRegValue ctxt R.ST0 + if leftToRight then !!ir (res := binOp st0 oprExpr) + else !!ir (res := binOp oprExpr st0) + !?ir (assignFPUReg R.ST0 res ctxt) + !?ir (checkC1Flag ctxt) R.FTW7 + | TwoOperands (OprReg reg1, opr2) -> + let oprExpr1 = !.ctxt reg1 + let oprExpr2 = transOprToExpr ins insLen ctxt opr2 + if leftToRight then !!ir (res := binOp oprExpr1 oprExpr2) + else !!ir (res := binOp oprExpr2 oprExpr1) + !?ir (assignFPUReg reg1 res ctxt) + | _ -> raise InvalidOperandException + if doPop then !?ir (popFPUStack ctxt) else () + !>ir insLen + +let private fpuIntOp ins insLen ctxt binOp leftToRight = + let ir = IRBuilder (8) + let st0 = fpuRegValue ctxt R.ST0 + let oprExpr = transOneOpr ins insLen ctxt + let tmp = !*ir 80 + ! oprExpr) + if leftToRight then !!ir (tmp := binOp st0 tmp) + else !!ir (tmp := binOp tmp st0) + !?ir (assignFPUReg R.ST0 tmp ctxt) + !>ir insLen + +let private bcdToInt intgr bcd ir = + let getDigit startPos = + AST.extract bcd 4 startPos |> AST.sext 64 + let n num = + numI64 num 64 + !!ir (intgr := AST.num0 64) + !!ir (intgr := intgr .+ getDigit 0) + !!ir (intgr := intgr .+ (getDigit 4 .* n 10L)) + !!ir (intgr := intgr .+ (getDigit 8 .* n 100L)) + !!ir (intgr := intgr .+ (getDigit 12 .* n 1000L)) + !!ir (intgr := intgr .+ (getDigit 16 .* n 10000L)) + !!ir (intgr := intgr .+ (getDigit 20 .* n 100000L)) + !!ir (intgr := intgr .+ (getDigit 24 .* n 1000000L)) + !!ir (intgr := intgr .+ (getDigit 28 .* n 10000000L)) + !!ir (intgr := intgr .+ (getDigit 32 .* n 100000000L)) + !!ir (intgr := intgr .+ (getDigit 36 .* n 1000000000L)) + !!ir (intgr := intgr .+ (getDigit 40 .* n 10000000000L)) + !!ir (intgr := intgr .+ (getDigit 44 .* n 100000000000L)) + !!ir (intgr := intgr .+ (getDigit 48 .* n 1000000000000L)) + !!ir (intgr := intgr .+ (getDigit 52 .* n 10000000000000L)) + !!ir (intgr := intgr .+ (getDigit 56 .* n 100000000000000L)) + !!ir (intgr := intgr .+ (getDigit 60 .* n 1000000000000000L)) + !!ir (intgr := intgr .+ (getDigit 64 .* n 10000000000000000L)) + !!ir (intgr := intgr .+ (getDigit 68 .* n 100000000000000000L)) + +let private intTobcd bcd intgr ir = + let n10 = numI32 10 64 + let mod10 = intgr .% n10 |> AST.zext 4 + let digitAt startPos = AST.extract bcd 4 startPos + let rec doAssign startPos = + if startPos >= 72 then () + else + !!ir (digitAt startPos := mod10) + !!ir (intgr := intgr ./ n10) + doAssign (startPos + 4) + doAssign 0 + +let private fpuLoad insLen ctxt oprExpr = + let ir = IRBuilder (64) + let tmp = !*ir 80 + ! oprExpr) + !?ir (checkFPUOnLoad ctxt) + !?ir (shiftFPUStackDown ctxt) + !?ir (assignFPUReg R.ST0 tmp ctxt) + !?ir (updateTagWordOnLoad ctxt) + !>ir insLen + +let fld ins insLen ctxt = + let oprExpr = transOneOpr ins insLen ctxt + fpuLoad insLen ctxt oprExpr + +let ffst (ins: InsInfo) insLen ctxt doPop = + let ir = IRBuilder (32) + let opr, oprExpr = + match ins.Operands with + | OneOperand opr -> opr, transOprToExpr ins insLen ctxt opr + | _ -> raise InvalidOperandException + let st0 = fpuRegValue ctxt R.ST0 + let sz = TypeCheck.typeOf oprExpr + let tmp = !*ir sz + ! !?ir (assignFPUReg r tmp ctxt) + | _ -> !!ir (oprExpr := tmp) + !?ir (checkC1Flag ctxt) R.FTW7 + !?ir (cflagsUndefined023 ctxt) + if doPop then !?ir (popFPUStack ctxt) else () + !>ir insLen + +let fild ins insLen ctxt = + let ir = IRBuilder (32) + let oprExpr = transOneOpr ins insLen ctxt + let tmp = !*ir 80 + ! oprExpr) + !?ir (checkFPUOnLoad ctxt) + !?ir (shiftFPUStackDown ctxt) + !?ir (assignFPUReg R.ST0 tmp ctxt) + !?ir (updateTagWordOnLoad ctxt) + !>ir insLen + +let fist ins insLen ctxt doPop = + let ir = IRBuilder (32) + let oprExpr = transOneOpr ins insLen ctxt + let sz = TypeCheck.typeOf oprExpr + let st0 = fpuRegValue ctxt R.ST0 + let tmp1 = !*ir sz + let tmp2 = !*ir 2 + let num2 = numI32 2 2 + let cstK castKind = AST.cast castKind sz st0 + ! 10) + !!ir (tmp1 := AST.ite (tmp2 == AST.num0 2) + (cstK CastKind.FtoIRound) (cstK CastKind.FtoITrunc)) + !!ir + (tmp1 := AST.ite (tmp2 == AST.num1 2) (cstK CastKind.FtoIFloor) tmp1) + !!ir (tmp1 := AST.ite (tmp2 == num2) (cstK CastKind.FtoICeil) tmp1) + !!ir (oprExpr := tmp1) + !!ir (!.ctxt R.FSWC1 := AST.ite (tmp2 == num2) AST.b1 AST.b0) + !?ir (cflagsUndefined023 ctxt) + if doPop then !?ir (popFPUStack ctxt) else () + !>ir insLen + +let fisttp ins insLen ctxt = + let ir = IRBuilder (64) + let oprExpr = transOneOpr ins insLen ctxt + let sz = TypeCheck.typeOf oprExpr + let st0 = fpuRegValue ctxt R.ST0 + !ir insLen + +let fbld ins insLen ctxt = + let ir = IRBuilder (64) + let src = transOneOpr ins insLen ctxt + let sign = AST.xthi 1 src + let intgr = !*ir 64 + let bcdNum = !*ir 72 + let tmp = !*ir 80 + ! intgr := sign) + !!ir (tmp := AST.cast CastKind.IntToFloat 80 intgr) + !?ir (checkFPUOnLoad ctxt) + !?ir (shiftFPUStackDown ctxt) + !?ir (assignFPUReg R.ST0 tmp ctxt) + !?ir (updateTagWordOnLoad ctxt) + !>ir insLen + +let fbstp ins insLen ctxt = + let ir = IRBuilder (64) + let dst = transOneOpr ins insLen ctxt + let st0 = fpuRegValue ctxt R.ST0 + let sign = AST.xthi 1 st0 + let intgr = !*ir 64 + let bcdNum = !*ir 72 + let tmp = !*ir 80 + ! st0) + !?ir (intTobcd bcdNum intgr) + !!ir (tmp := AST.num0 80) + !!ir (AST.xthi 1 tmp := sign) + !!ir (AST.xtlo 72 tmp := bcdNum) + !!ir (dst := tmp) + !>ir insLen + +let fxch (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (16) + let tmp = !*ir 80 + let st0 = fpuRegValue ctxt R.ST0 + ! + let oprExpr = transOprToExpr ins insLen ctxt opr + !!ir (tmp := st0) + !?ir (assignFPUReg R.ST0 oprExpr ctxt) + !?ir (assignFPUReg reg tmp ctxt) + | NoOperand -> + let st1 = fpuRegValue ctxt R.ST1 + !!ir (tmp := st0) + !?ir (assignFPUReg R.ST0 st1 ctxt) + !?ir (assignFPUReg R.ST1 tmp ctxt) + | _ -> raise InvalidOperandException + !!ir (!.ctxt R.FSWC1 := AST.b0) + !?ir (cflagsUndefined023 ctxt) + !>ir insLen + +let private fcmov (ins: InsInfo) insLen ctxt cond = + let ir = IRBuilder (8) + let src = + match ins.Operands with + | TwoOperands (_, src) -> src + | _ -> raise InvalidOperandException + let src = transOprToExpr ins insLen ctxt src + let st0b, st0a = getFPUPseudoRegVars ctxt R.ST0 + ! src) st0a) + !!ir (st0b := AST.ite cond (AST.xthi 16 src) st0b) + !!ir (!.ctxt R.FSWC0 := undefC0) + !!ir (!.ctxt R.FSWC2 := undefC2) + !!ir (!.ctxt R.FSWC3 := undefC3) + !>ir insLen + +let fcmove ins insLen ctxt = + !.ctxt R.ZF |> fcmov ins insLen ctxt + +let fcmovne ins insLen ctxt = + !.ctxt R.ZF |> AST.not |> fcmov ins insLen ctxt + +let fcmovb ins insLen ctxt = + !.ctxt R.CF |> fcmov ins insLen ctxt + +let fcmovbe ins insLen ctxt = + (!.ctxt R.CF .| !.ctxt R.ZF) |> fcmov ins insLen ctxt + +let fcmovnb ins insLen ctxt = + !.ctxt R.CF |> AST.not |> fcmov ins insLen ctxt + +let fcmovnbe ins insLen ctxt = + let cond1 = !.ctxt R.CF |> AST.not + let cond2 = !.ctxt R.ZF |> AST.not + cond1 .& cond2 |> fcmov ins insLen ctxt + +let fcmovu ins insLen ctxt = + !.ctxt R.PF |> fcmov ins insLen ctxt + +let fcmovnu ins insLen ctxt = + !.ctxt R.PF |> AST.not |> fcmov ins insLen ctxt + +let fpuadd ins insLen ctxt doPop = + fpuFBinOp ins insLen ctxt AST.fadd doPop true + +let fiadd ins insLen ctxt = + fpuIntOp ins insLen ctxt AST.fadd true + +let fpusub ins insLen ctxt doPop = + fpuFBinOp ins insLen ctxt AST.fsub doPop true + +let fisub ins insLen ctxt = + fpuIntOp ins insLen ctxt AST.fsub true + +let fsubr ins insLen ctxt doPop = + fpuFBinOp ins insLen ctxt AST.fsub doPop false + +let fisubr ins insLen ctxt = + fpuIntOp ins insLen ctxt AST.fsub false + +let fpumul ins insLen ctxt doPop = + fpuFBinOp ins insLen ctxt AST.fmul doPop true + +let fimul ins insLen ctxt = + fpuIntOp ins insLen ctxt AST.fmul true + +let fpudiv ins insLen ctxt doPop = + fpuFBinOp ins insLen ctxt AST.fdiv doPop true + +let fidiv ins insLen ctxt = + fpuIntOp ins insLen ctxt AST.fdiv true + +let fdivr ins insLen ctxt doPop = + fpuFBinOp ins insLen ctxt AST.fdiv doPop false + +let fidivr ins insLen ctxt = + fpuIntOp ins insLen ctxt AST.fdiv false + +let fprem _ins insLen ctxt round = + let ir = IRBuilder (32) + let st0 = fpuRegValue ctxt R.ST0 + let st1 = fpuRegValue ctxt R.ST1 + let caster = if round then CastKind.FtoIRound else CastKind.FtoITrunc + let lblLT64 = ir.NewSymbol "ExpDiffInRange" + let lblGT64 = ir.NewSymbol "ExpDiffOutOfRange" + let lblExit = ir.NewSymbol "Exit" + let expDiff = !*ir 15 + let struct (tmp80A, tmp80B, tmpres) = tmpVars3 ir 80 + let tmp64 = !*ir 64 + ! 64 .- AST.extract st1 15 64) + !!ir (AST.cjmp (AST.lt expDiff (numI32 64 15)) + (AST.name lblLT64) (AST.name lblGT64)) + !!ir (AST.lmark lblLT64) + !!ir (tmp80A := AST.fdiv st0 st1) + !!ir (tmp64 := AST.cast caster 64 tmp80A) + !!ir (tmp80B := AST.fmul st1 (AST.cast CastKind.IntToFloat 80 tmp64)) + !!ir (tmpres := AST.fsub st0 tmp80B) + !?ir (assignFPUReg R.ST0 tmpres ctxt) + !!ir (!.ctxt R.FSWC2 := AST.b0) + !!ir (!.ctxt R.FSWC1 := AST.xtlo 1 tmp64) + !!ir (!.ctxt R.FSWC3 := AST.extract tmp64 1 1) + !!ir (!.ctxt R.FSWC0 := AST.extract tmp64 1 2) + !!ir (AST.jmp (AST.name lblExit)) + !!ir (AST.lmark lblGT64) + !!ir (!.ctxt R.FSWC2 := AST.b1) + !!ir (tmp64 := (AST.zext 64 expDiff) .- numI32 63 64) + !!ir (tmp64 := tmp64 .* numI32 2 64) + !!ir (tmp80B := AST.cast CastKind.IntToFloat 80 tmp64) + !!ir (tmp80A := AST.fdiv (AST.fdiv st0 st1) tmp80B) + !!ir (tmp64 := AST.cast CastKind.FtoITrunc 64 tmp80A) + !!ir (tmp80A := AST.cast CastKind.IntToFloat 80 tmp64) + !!ir (tmp80A := AST.fsub st0 (AST.fmul st1 (AST.fmul tmp80A tmp80B))) + !?ir (assignFPUReg R.ST0 tmp80A ctxt) + !!ir (AST.lmark lblExit) + !>ir insLen + +let fabs _ins insLen ctxt = + let ir = IRBuilder (8) + let st0b, _st0a = getFPUPseudoRegVars ctxt R.ST0 + ! 15 := AST.b1) + !!ir (!.ctxt R.FSWC1 := AST.b0) + !!ir (!.ctxt R.FSWC0 := undefC0) + !!ir (!.ctxt R.FSWC2 := undefC2) + !!ir (!.ctxt R.FSWC3 := undefC3) + !>ir insLen + +let fchs _ins insLen ctxt = + let ir = IRBuilder (8) + let st0b, _st0a = getFPUPseudoRegVars ctxt R.ST0 + let tmp = !*ir 1 + ! st0b) + !!ir (AST.xthi 1 st0b := AST.not tmp) + !!ir (!.ctxt R.FSWC1 := AST.b0) + !!ir (!.ctxt R.FSWC0 := undefC0) + !!ir (!.ctxt R.FSWC2 := undefC2) + !!ir (!.ctxt R.FSWC3 := undefC3) + !>ir insLen + +let frndint _ins insLen ctxt = + let ir = IRBuilder (32) + let st0 = fpuRegValue ctxt R.ST0 + let t0 = !*ir 80 + let t1 = !*ir 64 + let t2 = !*ir 2 + let num2 = numI32 2 2 + let cstK castKind = AST.cast castKind 64 st0 + ! 10) + !!ir (t1 := AST.ite (t2 == AST.num0 2) + (cstK CastKind.FtoIRound) (cstK CastKind.FtoITrunc)) + !!ir (t1 := AST.ite (t2 == AST.num1 2) (cstK CastKind.FtoIFloor) t1) + !!ir (t1 := AST.ite (t2 == num2) (cstK CastKind.FtoICeil) t1) + !!ir (t0 := AST.cast CastKind.IntToFloat 80 t1) + !?ir (assignFPUReg R.ST0 t0 ctxt) + !!ir (!.ctxt R.FSWC1 := AST.ite (t2 == num2) AST.b1 AST.b0) + !?ir (cflagsUndefined023 ctxt) + !>ir insLen + +let fscale _ins insLen ctxt = + let ir = IRBuilder (16) + let struct (tmp1, tmp2) = tmpVars2 ir 64 + let tmp3 = !*ir 80 + let st0 = fpuRegValue ctxt R.ST0 + let st1 = fpuRegValue ctxt R.ST1 + ! st1) + !!ir (tmp2 := numI32 1 64 << tmp1) + !!ir (tmp3 := AST.cast CastKind.IntToFloat 80 tmp2) + !!ir (tmp3 := AST.fmul st0 tmp3) + !?ir (assignFPUReg R.ST0 tmp3 ctxt) + !?ir (checkC1Flag ctxt) R.FTW6 + !?ir (cflagsUndefined023 ctxt) + !>ir insLen + +let fsqrt _ins insLen ctxt = + let ir = IRBuilder (8) + let st0 = fpuRegValue ctxt R.ST0 + let tmp = !*ir 80 + !ir insLen + +let fxtract _ins insLen ctxt = + let ir = IRBuilder (64) + let st0 = fpuRegValue ctxt R.ST0 + let tmp = !*ir 80 + let exponent = !*ir 64 + let significand = !*ir 80 + !) + !!ir (significand := AST.num0 80) + !!ir (AST.xtlo 64 significand := AST.xtlo 64 st0) + !!ir (AST.xthi 1 significand := AST.xthi 1 st0) + !!ir (AST.extract significand 15 64 := numI32 16383 15) + !!ir (AST.xtlo 15 exponent := AST.extract st0 15 64) + !!ir (exponent := exponent .- numI32 16383 64) + !!ir (tmp := AST.cast CastKind.IntToFloat 80 exponent) + !?ir (assignFPUReg R.ST0 tmp ctxt) + !?ir (checkFPUOnLoad ctxt) + !?ir (shiftFPUStackDown ctxt) + !?ir (assignFPUReg R.ST0 significand ctxt) + !?ir (updateTagWordOnLoad ctxt) + !?ir (checkC1Flag ctxt) R.FTW7 + !?ir (cflagsUndefined023 ctxt) + !>ir insLen + +let fcom (ins: InsInfo) insLen ctxt nPop unordered = + let ir = IRBuilder (64) + let lblNan = ir.NewSymbol "IsNan" + let lblExit = ir.NewSymbol "Exit" + let c0 = !.ctxt R.FSWC0 + let c2 = !.ctxt R.FSWC2 + let c3 = !.ctxt R.FSWC3 + let im = !.ctxt R.FCW |> AST.xtlo 1 + let struct (tmp1, tmp2) = tmpVars2 ir 80 + ! + !!ir (tmp1 := fpuRegValue ctxt R.ST0) + !!ir (tmp2 := fpuRegValue ctxt R.ST1) + | OneOperand opr -> + let oprExpr = transOprToFloat80 ins insLen ctxt opr + !!ir (tmp1 := fpuRegValue ctxt R.ST0) + !!ir (tmp2 := oprExpr) + | TwoOperands (o1, o2) -> + let o1 = transOprToFloat80 ins insLen ctxt o1 + let o2 = transOprToFloat80 ins insLen ctxt o2 + !!ir (tmp1 := o1) + !!ir (tmp2 := o2) + | _ -> raise InvalidOperandException + !!ir (c0 := AST.ite (AST.flt tmp1 tmp2) AST.b1 AST.b0) + !!ir (c2 := AST.b0) + !!ir (c3 := AST.ite (tmp1 == tmp2) AST.b1 AST.b0) + let isNan expr = + (AST.extract expr 15 64 == AST.num (BitVector.unsignedMax 15)) + .& (AST.xtlo 62 expr != AST.num0 62) + let cond = + if unordered then + let tmp1qNanCond = isNan tmp1 .& (AST.extract tmp1 1 62 == AST.b1) + let tmp2qNanCond = isNan tmp2 .& (AST.extract tmp2 1 62 == AST.b1) + tmp1qNanCond .| tmp2qNanCond .& (im == AST.b0) + else isNan tmp1 .| isNan tmp2 .& (im == AST.b0) + !!ir (AST.cjmp cond (AST.name lblNan) (AST.name lblExit)) + !!ir (AST.lmark lblNan) + !!ir (c0 := AST.b1) + !!ir (c2 := AST.b1) + !!ir (c3 := AST.b1) + !!ir (AST.lmark lblExit) + !!ir (!.ctxt R.FSWC1 := AST.b0) + if nPop > 0 then !?ir (popFPUStack ctxt) else () + if nPop = 2 then !?ir (popFPUStack ctxt) else () + !>ir insLen + +let ficom ins insLen ctxt doPop = + let ir = IRBuilder (32) + let oprExpr = transOneOpr ins insLen ctxt + let st0 = fpuRegValue ctxt R.ST0 + let tmp = !*ir 80 + ! oprExpr) + !!ir (!.ctxt R.FSWC0 := AST.ite (AST.flt st0 tmp) AST.b1 AST.b0) + !!ir (!.ctxt R.FSWC2 := AST.b0) + !!ir (!.ctxt R.FSWC3 := AST.ite (st0 == tmp) AST.b1 AST.b0) + !!ir (!.ctxt R.FSWC1 := AST.b0) + if doPop then !?ir (popFPUStack ctxt) else () + !>ir insLen + +let fcomi ins insLen ctxt doPop = + let ir = IRBuilder (64) + let struct (opr1, opr2) = transTwoOprs ins insLen ctxt + let im = !.ctxt R.FCW |> AST.xtlo 1 + let lblQNan = ir.NewSymbol "IsQNan" + let lblNan = ir.NewSymbol "IsNan" + let lblExit = ir.NewSymbol "Exit" + let lblCond = ir.NewSymbol "IsNanCond" + let zf = !.ctxt R.ZF + let pf = !.ctxt R.PF + let cf = !.ctxt R.CF + ! 64 == AST.num (BitVector.unsignedMax 15)) + .& (AST.xtlo 62 opr1 != AST.num0 62) + let opr2NanCond = + (AST.extract opr2 15 64 == AST.num (BitVector.unsignedMax 15)) + .& (AST.xtlo 62 opr2 != AST.num0 62) + let cond = opr1NanCond .| opr2NanCond .& (im == AST.b0) + match ins.Opcode with + | Opcode.FCOMI | Opcode.FCOMIP -> + !!ir (AST.cjmp cond (AST.name lblNan) (AST.name lblExit)) + | Opcode.FUCOMI | Opcode.FUCOMIP -> + let opr1qNanCond = opr1NanCond .& (AST.extract opr1 1 62 == AST.b1) + let opr2qNanCond = opr2NanCond .& (AST.extract opr2 1 62 == AST.b1) + !!ir (AST.cjmp (opr1qNanCond .| opr2qNanCond) + (AST.name lblQNan) (AST.name lblCond)) + !!ir (AST.lmark lblQNan) + !!ir (zf:= AST.b1) + !!ir (pf := AST.b1) + !!ir (cf := AST.b1) + !!ir (AST.jmp (AST.name lblExit)) + !!ir (AST.lmark lblCond) + !!ir (AST.cjmp cond (AST.name lblNan) (AST.name lblExit)) + | _ -> raise InvalidOpcodeException + !!ir (AST.lmark lblNan) + !!ir (zf := AST.b1) + !!ir (pf := AST.b1) + !!ir (cf := AST.b1) + !!ir (AST.lmark lblExit) + if doPop then !?ir (popFPUStack ctxt) else () + !>ir insLen + +let ftst _ins insLen ctxt = + let ir = IRBuilder (16) + let st0 = fpuRegValue ctxt R.ST0 + let num0V = AST.num0 80 + let c0 = !.ctxt R.FSWC0 + let c2 = !.ctxt R.FSWC2 + let c3 = !.ctxt R.FSWC3 + let lblNan = ir.NewSymbol "IsNan" + let lblExit = ir.NewSymbol "Exit" + ! 64 + let st0NanCond = + (st0Exponent == AST.num (BitVector.unsignedMax 15)) + .& (AST.xtlo 62 st0 != AST.num0 62) + !!ir (AST.cjmp st0NanCond (AST.name lblNan) (AST.name lblExit)) + !!ir (AST.lmark lblNan) + !!ir (c0 := AST.b1) + !!ir (c2 := AST.b1) + !!ir (c3 := AST.b1) + !!ir (AST.lmark lblExit) + !!ir (!.ctxt R.FSWC1 := AST.b0) + !>ir insLen + +let fxam _ins insLen ctxt = + let ir = IRBuilder (8) + let st0 = fpuRegValue ctxt R.ST0 + let exponent = AST.extract st0 15 64 + let maxExponent = BitVector.unsignedMax 15 |> AST.num + let tag7 = !.ctxt R.FTW7 + let nanCond = + (exponent == maxExponent) .& (AST.xtlo 62 st0 != AST.num0 62) + let c3Cond1 = (tag7 == numI32 3 2) .| (exponent == AST.num0 15) + let c2Cond0 = (tag7 == numI32 3 2) .| (st0 == AST.num0 80) .| nanCond + let c0Cond1 = (tag7 == numI32 3 2) .| (exponent == maxExponent) + ! st0) + !!ir (!.ctxt R.FSWC3 := AST.ite (c3Cond1) AST.b1 AST.b0) + !!ir (!.ctxt R.FSWC2 := AST.ite (c2Cond0) AST.b0 AST.b1) + !!ir (!.ctxt R.FSWC0 := AST.ite (c0Cond1) AST.b1 AST.b0) + !>ir insLen + +let fsin ins insLen ctxt = + ftrig ins insLen ctxt AST.fsin + +let fcos ins insLen ctxt = + ftrig ins insLen ctxt AST.fcos + +let fsincos _ins insLen ctxt = + let ir = IRBuilder (64) + let st0 = fpuRegValue ctxt R.ST0 + let c0 = !.ctxt R.FSWC0 + let c1 = !.ctxt R.FSWC1 + let c2 = !.ctxt R.FSWC2 + let c3 = !.ctxt R.FSWC3 + let float80SignUnmask = BitVector.signedMax 80 |> AST.num + let maxLimit = numI64 (1L <<< 63) 64 + let maxFloat = AST.cast CastKind.IntToFloat 80 maxLimit + let num3 = BitVector.ofInt32 3 2 |> AST.num + let lblOutOfRange = ir.NewSymbol "IsOutOfRange" + let lblInRange = ir.NewSymbol "IsInRange" + let struct (tmp1, tmp2) = tmpVars2 ir 80 + !ir insLen + +let fptan _ins insLen ctxt = + let ir = IRBuilder (64) + let st0 = fpuRegValue ctxt R.ST0 + let float80SignUnmask = BitVector.signedMax 80 |> AST.num + let maxLimit = numI64 (1L <<< 63) 64 + let maxFloat = AST.cast CastKind.IntToFloat 80 maxLimit + let num3 = BitVector.ofInt32 3 2 |> AST.num + let c0 = !.ctxt R.FSWC0 + let c1 = !.ctxt R.FSWC1 + let c2 = !.ctxt R.FSWC2 + let c3 = !.ctxt R.FSWC3 + let lblOutOfRange = ir.NewSymbol "IsOutOfRange" + let lblInRange = ir.NewSymbol "IsInRange" + let tmp = !*ir 80 + let tmp64 = !*ir 64 + !) + !!ir (tmp := AST.cast CastKind.FloatCast 80 tmp64) + !?ir (checkFPUOnLoad ctxt) + !?ir (shiftFPUStackDown ctxt) + !?ir (assignFPUReg R.ST0 tmp ctxt) + !?ir (updateTagWordOnLoad ctxt) + !>ir insLen + +let fpatan _ins insLen ctxt = + let ir = IRBuilder (16) + let c1 = !.ctxt R.FSWC1 + let tmp = !*ir 80 + !ir insLen + +let f2xm1 _isn insLen ctxt = + let ir = IRBuilder (16) + let st0 = fpuRegValue ctxt R.ST0 + let flt1 = AST.num1 32 |> AST.cast CastKind.IntToFloat 80 + let flt2 = numI32 2 32 |> AST.cast CastKind.IntToFloat 80 + let tmp = !*ir 80 + !ir insLen + +let fyl2x _ins insLen ctxt = + let ir = IRBuilder (64) + let st0 = fpuRegValue ctxt R.ST0 + let st1 = fpuRegValue ctxt R.ST1 + let flt2 = numI32 2 32 |> AST.cast CastKind.IntToFloat 80 + let struct (t1, t2) = tmpVars2 ir 80 + !ir insLen + +let fyl2xp1 _ins insLen ctxt = + let ir = IRBuilder (64) + let st0 = fpuRegValue ctxt R.ST0 + let st1 = fpuRegValue ctxt R.ST1 + let flt2 = numI32 2 32 |> AST.cast CastKind.IntToFloat 80 + let f1 = numI32 1 32 |> AST.cast CastKind.IntToFloat 80 + let tmp = !*ir 80 + !ir insLen + +let fld1 _ins insLen ctxt = + let oprExpr = BitVector.ofUInt64 0x3FF0000000000000UL 64 |> AST.num + fpuLoad insLen ctxt oprExpr + +let fldz _ins insLen ctxt = + let oprExpr = AST.num0 64 + fpuLoad insLen ctxt oprExpr + +let fldpi _ins insLen ctxt = + let oprExpr = BitVector.ofUInt64 4614256656552045848UL 64 |> AST.num + fpuLoad insLen ctxt oprExpr + +let fldl2e _ins insLen ctxt = + let oprExpr = BitVector.ofUInt64 4599094494223104509UL 64 |> AST.num + fpuLoad insLen ctxt oprExpr + +let fldln2 _ins insLen ctxt = + let oprExpr = BitVector.ofUInt64 4604418534313441775UL 64 |> AST.num + fpuLoad insLen ctxt oprExpr + +let fldl2t _ins insLen ctxt = + let oprExpr = BitVector.ofUInt64 4614662735865160561UL 64 |> AST.num + fpuLoad insLen ctxt oprExpr + +let fldlg2 _ins insLen ctxt = + let oprExpr = BitVector.ofUInt64 4599094494223104511UL 64 |> AST.num + fpuLoad insLen ctxt oprExpr + +let fincstp _ins insLen ctxt = + let ir = IRBuilder (16) + let top = !.ctxt R.FTOP + !) + !!ir (!.ctxt R.FSWC1 := AST.b0) + !!ir (!.ctxt R.FSWC0 := undefC0) + !!ir (!.ctxt R.FSWC2 := undefC2) + !!ir (!.ctxt R.FSWC3 := undefC3) + !>ir insLen + +let fdecstp _ins insLen ctxt = + let ir = IRBuilder (8) + let top = !.ctxt R.FTOP + !) + !!ir (!.ctxt R.FSWC1 := AST.b0) + !!ir (!.ctxt R.FSWC0 := undefC0) + !!ir (!.ctxt R.FSWC2 := undefC2) + !!ir (!.ctxt R.FSWC3 := undefC3) + !>ir insLen + +let ffree (ins: InsInfo) insLen ctxt = + let ir = IRBuilder (8) + let top = !.ctxt R.FTOP + let tagWord = !.ctxt R.FTW + let struct (top16, shifter, tagValue) = tmpVars3 ir 16 + let value3 = BitVector.ofInt32 3 16 |> AST.num + let offset = + match ins.Operands with + | OneOperand (OprReg R.ST0) -> BitVector.ofInt32 0 16 |> AST.num + | OneOperand (OprReg R.ST1) -> BitVector.ofInt32 1 16 |> AST.num + | OneOperand (OprReg R.ST2) -> BitVector.ofInt32 2 16 |> AST.num + | OneOperand (OprReg R.ST3) -> BitVector.ofInt32 3 16 |> AST.num + | OneOperand (OprReg R.ST4) -> BitVector.ofInt32 4 16 |> AST.num + | OneOperand (OprReg R.ST5) -> BitVector.ofInt32 5 16 |> AST.num + | OneOperand (OprReg R.ST6) -> BitVector.ofInt32 6 16 |> AST.num + | OneOperand (OprReg R.ST7) -> BitVector.ofInt32 7 16 |> AST.num + | _ -> raise InvalidOperandException + ! top) + !!ir (top16 := top16 .+ offset) + !!ir (shifter := (BitVector.ofInt32 2 16 |> AST.num) .* top16) + !!ir (tagValue := (value3 << shifter)) + !!ir (tagWord := tagWord .| tagValue) + !>ir insLen + +(* FIXME: check all unmasked pending floating point exceptions. *) +let private checkFPUExceptions ctxt ir = () + +let private clearFPU ctxt ir = + let cw = BitVector.ofInt32 895 16 |> AST.num + let tw = BitVector.maxUInt16 |> AST.num + !!ir (!.ctxt R.FCW := cw) + !!ir (!.ctxt R.FSW := AST.num0 16) + !!ir (!.ctxt R.FTW := tw) + +let finit _ins insLen ctxt = + let ir = IRBuilder (32) + !ir insLen + +let fninit _ins insLen ctxt = + let ir = IRBuilder (16) + !ir insLen + +let fclex _ins insLen ctxt = + let ir = IRBuilder (8) + let stsWrd = !.ctxt R.FSW + ! stsWrd := AST.num0 7) + !!ir (AST.xthi 1 stsWrd := AST.b0) + !!ir (!.ctxt R.FSWC0 := undefC0) + !!ir (!.ctxt R.FSWC1 := undefC1) + !!ir (!.ctxt R.FSWC2 := undefC2) + !!ir (!.ctxt R.FSWC3 := undefC3) + !>ir insLen + +let fstcw ins insLen ctxt = + let ir = IRBuilder (16) + let oprExpr = transOneOpr ins insLen ctxt + !ir insLen + +let fnstcw ins insLen ctxt = + let ir = IRBuilder (8) + let oprExpr = transOneOpr ins insLen ctxt + !ir insLen + +let fldcw ins insLen ctxt = + let ir = IRBuilder (8) + let oprExpr = transOneOpr ins insLen ctxt + !ir insLen + +let fstenv ins insLen ctxt = + let ir = IRBuilder (16) + let dst = transOneOpr ins insLen ctxt + ! -> m14Stenv dst ctxt ir + | 224 -> m28fstenv dst ctxt ir + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let fldenv ins insLen ctxt = + let ir = IRBuilder (16) + let src = transOneOpr ins insLen ctxt + ! -> m14fldenv src ctxt ir + | 224 -> m28fldenv src ctxt ir + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let private stSts dst ctxt ir = + let dst = extendAddr dst 80 + let offset = numI32 10 (getAddrRegSize dst) + !!ir (dst := !.ctxt R.ST0) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := !.ctxt R.ST1) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := !.ctxt R.ST2) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := !.ctxt R.ST3) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := !.ctxt R.ST4) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := !.ctxt R.ST5) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := !.ctxt R.ST6) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := !.ctxt R.ST7) + !!ir (updateAddrByOffset dst offset) + +let fsave ins insLen ctxt = + let ir = IRBuilder (32) + let dst = transOneOpr ins insLen ctxt + let baseReg = getBaseReg dst + let regSave = !*ir (getAddrRegSize dst) + let addrRegSize = getAddrRegSize dst + ! + m14Stenv eDst ctxt ir + !!ir (updateAddrByOffset eDst (numI32 28 addrRegSize)) + stSts eDst ctxt ir + !!ir (!.ctxt R.FCW := numI32 0x037F 16) + !!ir (!.ctxt R.FSW := AST.num0 16) + !!ir (!.ctxt R.FTW := numI32 0xFFFF 16) + !!ir (!.ctxt R.FDP := AST.num0 64) + !!ir (!.ctxt R.FIP := AST.num0 64) + !!ir (!.ctxt R.FOP := AST.num0 16) + !!ir (baseReg := regSave) + !>ir insLen + +let private ldSts src ctxt ir = + !?ir (assignFPUReg R.ST0 (AST.xtlo 80 src) ctxt) + !?ir (assignFPUReg R.ST1 (AST.extract src 80 80) ctxt) + !?ir (assignFPUReg R.ST2 (AST.extract src 80 160) ctxt) + !?ir (assignFPUReg R.ST3 (AST.extract src 80 240) ctxt) + !?ir (assignFPUReg R.ST4 (AST.extract src 80 320) ctxt) + !?ir (assignFPUReg R.ST5 (AST.extract src 80 400) ctxt) + !?ir (assignFPUReg R.ST6 (AST.extract src 80 480) ctxt) + !?ir (assignFPUReg R.ST7 (AST.extract src 80 560) ctxt) + +let frstor ins insLen ctxt = + let ir = IRBuilder (32) + let src = transOneOpr ins insLen ctxt + ! -> + m14fldenv (AST.xtlo 112 src) ctxt ir + | 864 -> + m28fldenv (AST.xtlo 224 src) ctxt ir + | _ -> raise InvalidOperandSizeException + ldSts (AST.xthi 640 src) ctxt ir + !>ir insLen + +let fstsw ins insLen ctxt = + let ir = IRBuilder (16) + let oprExpr = transOneOpr ins insLen ctxt + !ir insLen + +let fnstsw ins insLen ctxt = + let ir = IRBuilder (8) + let oprExpr = transOneOpr ins insLen ctxt + !ir insLen + +let wait _ins insLen ctxt = + let ir = IRBuilder (8) + !ir insLen + +let fnop _ins insLen ctxt = + let ir = IRBuilder (8) + !ir insLen + +let private saveFxsaveMMX ctxt addr offset ir = + let r64 = AST.num0 64 + let mRegs = + [ r64 + !.ctxt R.MM0; r64; !.ctxt R.MM1; r64; !.ctxt R.MM2; r64; !.ctxt R.MM3 + r64 + !.ctxt R.MM4; r64; !.ctxt R.MM5; r64; !.ctxt R.MM6; r64; !.ctxt R.MM7 ] + List.iter (fun reg -> !!ir (updateAddrByOffset addr offset) + !!ir (addr := reg)) mRegs + +let private loadFxrstorMMX ctxt addr ir = + let offset = AST.num (BitVector.ofInt32 16 (getAddrRegSize addr)) + let mRegs = [ R.MM0; R.MM1; R.MM2; R.MM3; R.MM4; R.MM5; R.MM6; R.MM7 ] + List.iter (fun reg -> !!ir (updateAddrByOffset addr (offset)) + !!ir (!.ctxt reg := addr)) mRegs + +let private saveFxsaveXMM ctxt addr offset xRegs ir = + let pv r = getPseudoRegVar128 ctxt r + let exprs = + List.fold(fun acc r -> let r2, r1 = pv r in r1 :: (r2 :: acc)) [] xRegs + List.iter (fun reg -> !!ir (updateAddrByOffset addr offset) + !!ir (addr := reg)) exprs + +let private loadFxrstorXMM ctxt addr xRegs ir = + let pv r = getPseudoRegVar128 ctxt r + let offset = AST.num (BitVector.ofInt32 8 (getAddrRegSize addr)) + let exprs = + List.fold (fun acc r -> let r2, r1 = pv r in r1 :: (r2 :: acc)) [] xRegs + List.iter (fun reg -> !!ir (updateAddrByOffset addr offset) + !!ir (reg := addr)) exprs + +let private save64BitPromotedFxsave ctxt dst ir = + let reserved8 = AST.num0 8 + let num3 = numI32 3 2 + let struct (t0, t1, t2, t3) = tmpVars4 ir 1 + let struct (t4, t5, t6, t7) = tmpVars4 ir 1 + let abrTagW = !*ir 8 + let offset = AST.num (BitVector.ofInt32 8 (getAddrRegSize dst)) + let regSave = !*ir (getAddrRegSize dst) + let baseReg = getBaseReg dst + let xRegs = + [ R.XMM0; R.XMM1; R.XMM2; R.XMM3; R.XMM4; R.XMM5; R.XMM6; R.XMM7; + R.XMM8; R.XMM9; R.XMM10; R.XMM11; R.XMM12; R.XMM13; R.XMM14; R.XMM15 ] + !!ir (regSave := baseReg) + !!ir (abrTagW := + AST.concat (AST.concat (AST.concat t7 t6) (AST.concat t5 t4)) + (AST.concat (AST.concat t3 t2) (AST.concat t1 t0))) + !!ir (t0 := (!.ctxt R.FTW0 != num3)) + !!ir (t1 := (!.ctxt R.FTW1 != num3)) + !!ir (t2 := (!.ctxt R.FTW2 != num3)) + !!ir (t3 := (!.ctxt R.FTW3 != num3)) + !!ir (t4 := (!.ctxt R.FTW4 != num3)) + !!ir (t5 := (!.ctxt R.FTW5 != num3)) + !!ir (t6 := (!.ctxt R.FTW6 != num3)) + !!ir (t7 := (!.ctxt R.FTW7 != num3)) + !!ir (dst := + AST.concat (AST.concat (!.ctxt R.FOP) (AST.concat reserved8 abrTagW)) + (AST.concat (!.ctxt R.FSW) (!.ctxt R.FCW))) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := !.ctxt R.FIP) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := !.ctxt R.FDP) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := AST.concat (!.ctxt R.MXCSRMASK) (!.ctxt R.MXCSR)) + saveFxsaveMMX ctxt dst offset ir + saveFxsaveXMM ctxt dst offset (List.rev xRegs) ir + !!ir (baseReg := regSave) + +let private save64BitDefaultFxsave ctxt dst ir = + let reserved8 = AST.num0 8 + let reserved16 = AST.num0 16 + let num3 = numI32 3 2 + let struct (t0, t1, t2, t3) = tmpVars4 ir 1 + let struct (t4, t5, t6, t7) = tmpVars4 ir 1 + let abrTagW = !*ir 8 + let offset = AST.num (BitVector.ofInt32 8 (getAddrRegSize dst)) + let regSave = !*ir (getAddrRegSize dst) + let baseReg = getBaseReg dst + let xRegs = + [ R.XMM0; R.XMM1; R.XMM2; R.XMM3; R.XMM4; R.XMM5; R.XMM6; R.XMM7; + R.XMM8; R.XMM9; R.XMM10; R.XMM11; R.XMM12; R.XMM13; R.XMM14; R.XMM15 ] + !!ir (regSave := baseReg) + !!ir (t0 := (!.ctxt R.FTW0 != num3)) + !!ir (t1 := (!.ctxt R.FTW1 != num3)) + !!ir (t2 := (!.ctxt R.FTW2 != num3)) + !!ir (t3 := (!.ctxt R.FTW3 != num3)) + !!ir (t4 := (!.ctxt R.FTW4 != num3)) + !!ir (t5 := (!.ctxt R.FTW5 != num3)) + !!ir (t6 := (!.ctxt R.FTW6 != num3)) + !!ir (t7 := (!.ctxt R.FTW7 != num3)) + !!ir (abrTagW := + AST.concat (AST.concat (AST.concat t7 t6) (AST.concat t5 t4)) + (AST.concat (AST.concat t3 t2) (AST.concat t1 t0))) + !!ir (dst := + AST.concat (AST.concat (!.ctxt R.FOP) (AST.concat reserved8 abrTagW)) + (AST.concat (!.ctxt R.FSW) (!.ctxt R.FCW))) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := AST.concat (AST.xtlo 32 (!.ctxt R.FIP)) + (AST.concat (!.ctxt R.FCS) reserved16)) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := AST.concat (AST.xtlo 32 (!.ctxt R.FDP)) + (AST.concat (!.ctxt R.FDS) reserved16)) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := AST.concat (!.ctxt R.MXCSRMASK) (!.ctxt R.MXCSR)) + saveFxsaveMMX ctxt dst offset ir + saveFxsaveXMM ctxt dst offset (List.rev xRegs) ir + !!ir (baseReg := regSave) + +let private saveLegacyFxsave ctxt dst ir = + let reserved8 = AST.num0 8 + let reserved16 = AST.num0 16 + let num3 = numI32 3 2 + let struct (t0, t1, t2, t3) = tmpVars4 ir 1 + let struct (t4, t5, t6, t7) = tmpVars4 ir 1 + let abrTagW = !*ir 8 + let offset = AST.num (BitVector.ofInt32 8 (getAddrRegSize dst)) + let regSave = !*ir (getAddrRegSize dst) + let baseReg = getBaseReg dst + let xRegs = [ R.XMM0; R.XMM1; R.XMM2; R.XMM3; R.XMM4; R.XMM5; R.XMM6; R.XMM7 ] + !!ir (regSave := baseReg) + !!ir (t0 := (!.ctxt R.FTW0 != num3)) + !!ir (t1 := (!.ctxt R.FTW1 != num3)) + !!ir (t2 := (!.ctxt R.FTW2 != num3)) + !!ir (t3 := (!.ctxt R.FTW3 != num3)) + !!ir (t4 := (!.ctxt R.FTW4 != num3)) + !!ir (t5 := (!.ctxt R.FTW5 != num3)) + !!ir (t6 := (!.ctxt R.FTW6 != num3)) + !!ir (t7 := (!.ctxt R.FTW7 != num3)) + !!ir (abrTagW := + AST.concat (AST.concat (AST.concat t7 t6) (AST.concat t5 t4)) + (AST.concat (AST.concat t3 t2) (AST.concat t1 t0))) + !!ir (dst := + AST.concat (AST.concat (!.ctxt R.FOP) (AST.concat reserved8 abrTagW)) + (AST.concat (!.ctxt R.FSW) (!.ctxt R.FCW))) + !!ir (updateAddrByOffset dst offset) + !!ir + (dst := AST.concat (AST.xtlo 32 (!.ctxt R.FIP)) + (AST.concat (!.ctxt R.FCS) reserved16)) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := AST.concat (AST.xtlo 32 (!.ctxt R.FDP)) + (AST.concat (!.ctxt R.FDS) reserved16)) + !!ir (updateAddrByOffset dst offset) + !!ir (dst := AST.concat (!.ctxt R.MXCSRMASK) (!.ctxt R.MXCSR)) + saveFxsaveMMX ctxt dst offset ir + saveFxsaveXMM ctxt dst offset (List.rev xRegs) ir + !!ir (baseReg := regSave) + +let private load64BitPromotedFxrstor ctxt src ir = + let offset = AST.num (BitVector.ofInt32 8 (getAddrRegSize src)) + let xRegs = + [ R.XMM0; R.XMM1; R.XMM2; R.XMM3; R.XMM4; R.XMM5; R.XMM6; R.XMM7; + R.XMM8; R.XMM9; R.XMM10; R.XMM11; R.XMM12; R.XMM13; R.XMM14; R.XMM15 ] + let tSrc = !*ir 64 + !!ir (tSrc := src) + !!ir (!.ctxt R.FCW := AST.xtlo 16 tSrc) + !!ir (!.ctxt R.FSW := AST.extract tSrc 16 16) + !!ir (!.ctxt R.FTW := AST.extract tSrc 8 32) + !!ir (!.ctxt R.FOP := AST.extract tSrc 16 48) + !!ir (updateAddrByOffset src offset) + !!ir (tSrc := src) + !!ir (!.ctxt R.FIP := tSrc) + !!ir (updateAddrByOffset src offset) + !!ir (tSrc := src) + !!ir (!.ctxt R.FDP := tSrc) + !!ir (updateAddrByOffset src offset) + !!ir (tSrc := src) + !!ir (!.ctxt R.MXCSR := AST.xtlo 32 tSrc) + !!ir (!.ctxt R.MXCSRMASK := AST.xthi 32 tSrc) + loadFxrstorMMX ctxt src ir + loadFxrstorXMM ctxt src xRegs ir + +let private load64BitDefaultFxrstor ctxt src ir = + let offset = AST.num (BitVector.ofInt32 8 (getAddrRegSize src)) + let regSave = !*ir (getAddrRegSize src) + let baseReg = getBaseReg src + let struct (t0, t1, t2, t3) = tmpVars4 ir 2 + let struct (t4, t5, t6, t7) = tmpVars4 ir 2 + let tmp8 = !*ir 8 + let zero2 = AST.num0 2 + let three2 = numI32 3 2 + let xRegs = + [ R.XMM0; R.XMM1; R.XMM2; R.XMM3; R.XMM4; R.XMM5; R.XMM6; R.XMM7; + R.XMM8; R.XMM9; R.XMM10; R.XMM11; R.XMM12; R.XMM13; R.XMM14; R.XMM15 ] + !!ir (regSave := baseReg) + !!ir (tmp8 := AST.extract src 8 32) + !!ir (t0 := AST.ite (AST.xtlo 1 tmp8) zero2 three2) + !!ir (t1 := AST.ite (AST.extract tmp8 1 1) zero2 three2) + !!ir (t2 := AST.ite (AST.extract tmp8 1 2) zero2 three2) + !!ir (t3 := AST.ite (AST.extract tmp8 1 3) zero2 three2) + !!ir (t4 := AST.ite (AST.extract tmp8 1 4) zero2 three2) + !!ir (t5 := AST.ite (AST.extract tmp8 1 5) zero2 three2) + !!ir (t6 := AST.ite (AST.extract tmp8 1 6) zero2 three2) + !!ir (t7 := AST.ite (AST.extract tmp8 1 7) zero2 three2) + !!ir (!.ctxt R.FCW := AST.xtlo 16 src) + !!ir (!.ctxt R.FSW := AST.extract src 16 16) + !!ir (!.ctxt R.FTW := + AST.concat (AST.concat (AST.concat t7 t6) (AST.concat t5 t4)) + (AST.concat (AST.concat t3 t2) (AST.concat t1 t0))) + !!ir (!.ctxt R.FOP := AST.extract src 16 48) + !!ir (updateAddrByOffset src offset) + !!ir (AST.xtlo 32 (!.ctxt R.FIP) := AST.xtlo 32 src) + !!ir (!.ctxt R.FCS := AST.extract src 16 32) + !!ir (updateAddrByOffset src offset) + !!ir (AST.xtlo 32 (!.ctxt R.FDP) := AST.xtlo 32 src) + !!ir (!.ctxt R.FDS := AST.extract src 16 32) + !!ir (updateAddrByOffset src offset) + !!ir (!.ctxt R.MXCSR := AST.xtlo 32 src) + !!ir (!.ctxt R.MXCSRMASK := AST.xthi 32 src) + loadFxrstorMMX ctxt src ir + loadFxrstorXMM ctxt src (List.rev xRegs) ir + !!ir (baseReg := regSave) + +let private loadLegacyFxrstor ctxt src ir = + let offset = AST.num (BitVector.ofInt32 8 (getAddrRegSize src)) + let xRegs = [ R.XMM0; R.XMM1; R.XMM2; R.XMM3; R.XMM4; R.XMM5; R.XMM6; R.XMM7 ] + let tSrc = !*ir 64 + let struct (t0, t1, t2, t3) = tmpVars4 ir 1 + let struct (t4, t5, t6, t7) = tmpVars4 ir 1 + let abrTagW = !*ir 8 + let num0, num3 = numI32 0 2, numI32 3 2 + !!ir (abrTagW := + AST.concat (AST.concat (AST.concat t7 t6) (AST.concat t5 t4)) + (AST.concat (AST.concat t3 t2) (AST.concat t1 t0))) + !!ir (tSrc := src) + !!ir (!.ctxt R.FCW := AST.xtlo 16 tSrc) + !!ir (!.ctxt R.FSW := AST.extract tSrc 16 16) + !!ir (abrTagW := AST.extract tSrc 8 32) + !!ir (!.ctxt R.FTW0 := AST.ite t0 num0 num3) + !!ir (!.ctxt R.FTW1 := AST.ite t1 num0 num3) + !!ir (!.ctxt R.FTW2 := AST.ite t2 num0 num3) + !!ir (!.ctxt R.FTW3 := AST.ite t3 num0 num3) + !!ir (!.ctxt R.FTW4 := AST.ite t4 num0 num3) + !!ir (!.ctxt R.FTW5 := AST.ite t5 num0 num3) + !!ir (!.ctxt R.FTW6 := AST.ite t6 num0 num3) + !!ir (!.ctxt R.FTW7 := AST.ite t7 num0 num3) + !!ir (!.ctxt R.FOP := AST.extract tSrc 16 48) + !!ir (updateAddrByOffset src offset) + !!ir (tSrc := src) + !!ir (AST.xtlo 32 (!.ctxt R.FIP) := AST.xtlo 32 tSrc) + !!ir (!.ctxt R.FCS := AST.extract tSrc 16 32) + !!ir (updateAddrByOffset src offset) + !!ir (tSrc := src) + !!ir (AST.xtlo 32 (!.ctxt R.FDP) := AST.xtlo 32 tSrc) + !!ir (!.ctxt R.FDS := AST.extract tSrc 16 32) + !!ir (updateAddrByOffset src offset) + !!ir (tSrc := src) + !!ir (!.ctxt R.MXCSR := AST.xtlo 32 tSrc) + !!ir (!.ctxt R.MXCSRMASK := AST.xthi 32tSrc) + loadFxrstorMMX ctxt src ir + loadFxrstorXMM ctxt src xRegs ir + +let fxrstor ins insLen ctxt = + let ir = IRBuilder (128) + let src = transOneOpr ins insLen ctxt + let eSrc = extendAddr src 64 + ! then + if hasREXW ins.REXPrefix then load64BitPromotedFxrstor ctxt eSrc ir + else load64BitDefaultFxrstor ctxt eSrc ir + else loadLegacyFxrstor ctxt eSrc ir + !>ir insLen + +let fxsave ins insLen ctxt = + let ir = IRBuilder (128) + let dst = transOneOpr ins insLen ctxt + let eDst = extendAddr dst 64 + ! then + if hasREXW ins.REXPrefix then save64BitPromotedFxsave ctxt eDst ir + else save64BitDefaultFxsave ctxt eDst ir + else saveLegacyFxsave ctxt eDst ir + !>ir insLen diff --git a/src/FrontEnd/BinLifter/Intel/README.md b/src/FrontEnd/BinLifter/Intel/README.md new file mode 100644 index 00000000..eba27463 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/README.md @@ -0,0 +1,11 @@ +# B2R2.FrontEnd.BinLifter.Intel + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.BinLifter.Intel Package? + +`B2R2.FrontEnd.BinLifter.Intel` includes x86/x86-64 parsers and lifters. diff --git a/src/FrontEnd/BinLifter/MIPS/B2R2.FrontEnd.BinLifter.MIPS.fsproj b/src/FrontEnd/BinLifter/MIPS/B2R2.FrontEnd.BinLifter.MIPS.fsproj new file mode 100644 index 00000000..7accec48 --- /dev/null +++ b/src/FrontEnd/BinLifter/MIPS/B2R2.FrontEnd.BinLifter.MIPS.fsproj @@ -0,0 +1,36 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 MIPS frontend. + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FrontEnd/MIPS/MIPS.fs b/src/FrontEnd/BinLifter/MIPS/MIPS.fs similarity index 75% rename from src/FrontEnd/MIPS/MIPS.fs rename to src/FrontEnd/BinLifter/MIPS/MIPS.fs index 88a8507c..c7e9ede5 100644 --- a/src/FrontEnd/MIPS/MIPS.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPS.fs @@ -22,15 +22,16 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.MIPS +namespace B2R2.FrontEnd.BinLifter.MIPS -open B2R2.FrontEnd +open B2R2 +open B2R2.FrontEnd.BinLifter /// Translation context for MIPS instructions. -type MIPSTranslationContext (isa) = +type MIPSTranslationContext internal (isa, regexprs) = inherit TranslationContext (isa) /// Register expressions. - member val private RegExprs: RegExprs = RegExprs (isa.WordSize) + member val private RegExprs: RegExprs = regexprs override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar override __.GetPseudoRegVar _id _pos = failwith "Implement" @@ -38,7 +39,17 @@ type MIPSTranslationContext (isa) = /// instruction type (Instruction). type MIPSParser (wordSize, arch) = inherit Parser () - override __.Parse binReader _ctxt addr pos = + override __.Parse binReader addr pos = Parser.parse binReader arch wordSize addr pos :> Instruction + override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () + +module Basis = + let init (isa: ISA) = + let regexprs = RegExprs (isa.WordSize) + struct ( + MIPSTranslationContext (isa, regexprs) :> TranslationContext, + MIPSRegisterBay (isa.WordSize, regexprs) :> RegisterBay + ) + // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/MIPS/MIPSDisasm.fs b/src/FrontEnd/BinLifter/MIPS/MIPSDisasm.fs similarity index 75% rename from src/FrontEnd/MIPS/MIPSDisasm.fs rename to src/FrontEnd/BinLifter/MIPS/MIPSDisasm.fs index 8aabf1f3..d2239bdd 100644 --- a/src/FrontEnd/MIPS/MIPSDisasm.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSDisasm.fs @@ -22,9 +22,10 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.MIPS.Disasm +module internal B2R2.FrontEnd.BinLifter.MIPS.Disasm -open B2R2.FrontEnd +open B2R2 +open B2R2.FrontEnd.BinLifter let condToString = function | Condition.F -> ".f" @@ -178,57 +179,56 @@ let inline appendFmt insInfo opcode = | None -> opcode | Some f -> opcode + fmtToString f -let inline buildOpcode ins builder acc = +let inline buildOpcode ins (builder: DisasmBuilder<_>) = let str = opCodeToString ins.Opcode |> appendCond ins |> appendFmt ins - builder AsmWordKind.Mnemonic str acc + builder.Accumulate AsmWordKind.Mnemonic str -let inline relToString pc offset builder acc = +let inline relToString pc offset (builder: DisasmBuilder<_>) = let targetAddr = pc + uint64 offset - builder AsmWordKind.Value ("0x" + targetAddr.ToString("X")) acc + builder.Accumulate AsmWordKind.Value (String.u64ToHex targetAddr) -let oprToString insInfo opr delim builder acc = +let oprToString insInfo opr delim (builder: DisasmBuilder<_>) = match opr with | OpReg reg -> - builder AsmWordKind.String delim acc - |> builder AsmWordKind.Variable (Register.toString reg) + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.Variable (Register.toString reg) | OpImm imm | OpShiftAmount imm -> - builder AsmWordKind.String delim acc - |> builder AsmWordKind.Value ("0x" + imm.ToString ("X")) + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.Value (String.u64ToHex imm) | OpMem (b, off, _) -> - builder AsmWordKind.String delim acc - |> builder AsmWordKind.Value (off.ToString ("D")) - |> builder AsmWordKind.String "(" - |> builder AsmWordKind.Variable (Register.toString b) - |> builder AsmWordKind.String ")" + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.Value (off.ToString ("D")) + builder.Accumulate AsmWordKind.String "(" + builder.Accumulate AsmWordKind.Variable (Register.toString b) + builder.Accumulate AsmWordKind.String ")" | OpAddr (Relative offset) -> - builder AsmWordKind.String delim acc - |> relToString insInfo.Address offset builder + builder.Accumulate AsmWordKind.String delim + relToString insInfo.Address offset builder // Never gets matched. Only used in intermediate stage mips assembly parser. | GoToLabel _ -> raise InvalidOperandException -let buildOprs insInfo builder acc = +let buildOprs insInfo (builder: DisasmBuilder<_>) = match insInfo.Operands with - | NoOperand -> acc + | NoOperand -> () | OneOperand opr -> - oprToString insInfo opr " " builder acc + oprToString insInfo opr " " builder | TwoOperands (opr1, opr2) -> - oprToString insInfo opr1 " " builder acc - |> oprToString insInfo opr2 ", " builder + oprToString insInfo opr1 " " builder + oprToString insInfo opr2 ", " builder | ThreeOperands (opr1, opr2, opr3) -> - oprToString insInfo opr1 " " builder acc - |> oprToString insInfo opr2 ", " builder - |> oprToString insInfo opr3 ", " builder + oprToString insInfo opr1 " " builder + oprToString insInfo opr2 ", " builder + oprToString insInfo opr3 ", " builder | FourOperands (opr1, opr2, opr3, opr4) -> - oprToString insInfo opr1 " " builder acc - |> oprToString insInfo opr2 ", " builder - |> oprToString insInfo opr3 ", " builder - |> oprToString insInfo opr4 ", " builder - -let disasm showAddr wordSize insInfo builder acc = - let pc = insInfo.Address - DisasmBuilder.addr pc wordSize showAddr builder acc - |> buildOpcode insInfo builder - |> buildOprs insInfo builder + oprToString insInfo opr1 " " builder + oprToString insInfo opr2 ", " builder + oprToString insInfo opr3 ", " builder + oprToString insInfo opr4 ", " builder + +let disasm wordSize insInfo (builder: DisasmBuilder<_>) = + if builder.ShowAddr then builder.AccumulateAddr () else () + buildOpcode insInfo builder + buildOprs insInfo builder // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/MIPS/MIPSHelper.fs b/src/FrontEnd/BinLifter/MIPS/MIPSHelper.fs similarity index 98% rename from src/FrontEnd/MIPS/MIPSHelper.fs rename to src/FrontEnd/BinLifter/MIPS/MIPSHelper.fs index 4cb44c6a..946f5380 100644 --- a/src/FrontEnd/MIPS/MIPSHelper.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSHelper.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.MIPS.Helper +module internal B2R2.FrontEnd.BinLifter.MIPS.Helper open B2R2 -open B2R2.FrontEnd -open B2R2.FrontEnd.MIPS.Utils +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.MIPS.Utils let isRel2 arch = arch = Arch.MIPS32R2 || arch = Arch.MIPS64R2 let isRel6 arch = arch = Arch.MIPS32R6 || arch = Arch.MIPS64R6 diff --git a/src/FrontEnd/MIPS/MIPSInstruction.fs b/src/FrontEnd/BinLifter/MIPS/MIPSInstruction.fs similarity index 69% rename from src/FrontEnd/MIPS/MIPSInstruction.fs rename to src/FrontEnd/BinLifter/MIPS/MIPSInstruction.fs index 70ee151c..cfec5582 100644 --- a/src/FrontEnd/MIPS/MIPSInstruction.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSInstruction.fs @@ -22,26 +22,19 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.MIPS +namespace B2R2.FrontEnd.BinLifter.MIPS open B2R2 -open B2R2.FrontEnd -open System.Text +open B2R2.FrontEnd.BinLifter /// The internal representation for a MIPS instruction used by our /// disassembler and lifter. type MIPSInstruction (addr, numBytes, insInfo, wordSize) = inherit Instruction (addr, numBytes, wordSize) - let defaultCtxt = ParsingContext.Init () - /// Basic instruction information. member val Info: InsInfo = insInfo - override __.NextParsingContext with get() = defaultCtxt - - override __.AuxParsingContext with get() = None - override __.IsBranch () = match __.Info.Opcode with | Opcode.B | Opcode.BAL | Opcode.BEQ | Opcode.BGEZ | Opcode.BGEZAL @@ -49,6 +42,8 @@ type MIPSInstruction (addr, numBytes, insInfo, wordSize) = | Opcode.JALR | Opcode.JALRHB | Opcode.JR | Opcode.JRHB -> true | _ -> false + override __.IsModeChanging () = false + member __.HasConcJmpTarget () = match __.Info.Operands with | OneOperand (OpAddr _) -> true @@ -81,7 +76,9 @@ type MIPSInstruction (addr, numBytes, insInfo, wordSize) = override __.IsInterrupt () = Utils.futureFeature () - override __.IsExit () = // FIXME + override __.IsExit () = Utils.futureFeature () + + override __.IsBBLEnd () = // FIXME __.IsDirectBranch () || __.IsIndirectBranch () @@ -94,13 +91,27 @@ type MIPSInstruction (addr, numBytes, insInfo, wordSize) = | _ -> false else false - override __.IndirectTrampolineAddr (addr: byref) = + override __.IndirectTrampolineAddr (_addr: byref) = if __.IsBranch () then Utils.futureFeature () else false + override __.Immediate (v: byref) = + match __.Info.Operands with + | OneOperand (OpImm (c)) + | TwoOperands (OpImm (c), _) + | TwoOperands (_, OpImm (c)) + | ThreeOperands (OpImm (c), _, _) + | ThreeOperands (_, OpImm (c), _) + | ThreeOperands (_, _, OpImm (c)) + | FourOperands (OpImm (c), _, _, _) + | FourOperands (_, OpImm (c), _, _) + | FourOperands (_, _, OpImm (c), _) + | FourOperands (_, _, _, OpImm (c)) -> v <- int64 c; true + | _ -> false + override __.GetNextInstrAddrs () = Utils.futureFeature () - override __.InterruptNum (num: byref) = Utils.futureFeature () + override __.InterruptNum (_num: byref) = Utils.futureFeature () override __.IsNop () = __.Info.Opcode = Opcode.NOP @@ -108,25 +119,27 @@ type MIPSInstruction (addr, numBytes, insInfo, wordSize) = override __.Translate ctxt = Lifter.translate __.Info ctxt - member private __.StrBuilder _ (str: string) (acc: StringBuilder) = - acc.Append (str) - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = - let acc = StringBuilder () - let acc = Disasm.disasm showAddr wordSize __.Info __.StrBuilder acc - acc.ToString () + let builder = + DisasmStringBuilder (showAddr, false, wordSize, addr, numBytes) + Disasm.disasm wordSize __.Info builder + builder.Finalize () override __.Disasm () = - let acc = StringBuilder () - let acc = Disasm.disasm false wordSize __.Info __.StrBuilder acc - acc.ToString () + let builder = + DisasmStringBuilder (false, false, wordSize, addr, numBytes) + Disasm.disasm wordSize __.Info builder + builder.Finalize () + + override __.Decompose (showAddr) = + let builder = + DisasmWordBuilder (showAddr, false, wordSize, addr, numBytes, 8) + Disasm.disasm wordSize __.Info builder + builder.Finalize () - member private __.WordBuilder kind str (acc: AsmWordBuilder) = - acc.Append ({ AsmWordKind = kind; AsmWordValue = str }) + override __.IsInlinedAssembly () = false - override __.Decompose () = - AsmWordBuilder (8) - |> Disasm.disasm true wordSize __.Info __.WordBuilder - |> fun b -> b.Finish () + override __.Equals (_) = Utils.futureFeature () + override __.GetHashCode () = Utils.futureFeature () // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/MIPS/MIPSLifter.fs b/src/FrontEnd/BinLifter/MIPS/MIPSLifter.fs similarity index 61% rename from src/FrontEnd/MIPS/MIPSLifter.fs rename to src/FrontEnd/BinLifter/MIPS/MIPSLifter.fs index cb6d0081..6b905d64 100644 --- a/src/FrontEnd/MIPS/MIPSLifter.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSLifter.fs @@ -22,30 +22,30 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.MIPS.Lifter +module internal B2R2.FrontEnd.BinLifter.MIPS.Lifter open B2R2 open B2R2.BinIR open B2R2.BinIR.LowUIR -open B2R2.BinIR.LowUIR.AST -open B2R2.FrontEnd -open B2R2.FrontEnd.MIPS +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.MIPS let inline getRegVar (ctxt: TranslationContext) name = Register.toRegID name |> ctxt.GetRegVar -let inline private ( num -let inline numI32 n t = BitVector.ofInt32 n t |> num -let inline numU64 n t = BitVector.ofUInt64 n t |> num -let inline numI64 n t = BitVector.ofInt64 n t |> num +let inline numU32 n t = BitVector.ofUInt32 n t |> AST.num +let inline numI32 n t = BitVector.ofInt32 n t |> AST.num +let inline numU64 n t = BitVector.ofUInt64 n t |> AST.num +let inline numI64 n t = BitVector.ofInt64 n t |> AST.num let bvOfBaseAddr (ctxt: TranslationContext) addr = numU64 addr ctxt.WordBitSize @@ -55,12 +55,12 @@ let bvOfInstrLen (ctxt: TranslationContext) insInfo = let transOprToExpr insInfo ctxt = function | OpReg reg -> getRegVar ctxt reg | OpImm imm - | OpShiftAmount imm -> ctxt.WordBitSize |> BitVector.ofUInt64 imm |> num + | OpShiftAmount imm -> ctxt.WordBitSize |> BitVector.ofUInt64 imm |> AST.num | OpMem (b, o, sz) -> - loadLE sz (getRegVar ctxt b .+ numI64 o ctxt.WordBitSize) + AST.loadLE sz (getRegVar ctxt b .+ numI64 o ctxt.WordBitSize) | OpAddr (Relative o) -> numI64 (int64 insInfo.Address + o + int64 insInfo.NumBytes) ctxt.WordBitSize - |> loadLE ctxt.WordBitSize + |> AST.loadLE ctxt.WordBitSize | GoToLabel _ -> raise InvalidOperandException let transOprToImm = function @@ -104,136 +104,136 @@ let transThreeOprs insInfo ctxt (o1, o2, o3) = transOprToExpr insInfo ctxt o3 let sideEffects insInfo name = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) startMark insInfo builder - builder 31 - let e2High = extract e2 1 31 - let rHigh = extract r 1 31 + let e1High = AST.extract e1 1 31 + let e2High = AST.extract e2 1 31 + let rHigh = AST.extract r 1 31 (e1High == e2High) .& (e1High <+> rHigh) let notWordValue v = - (extractHigh 32 v) != sExt 32 (extract v 1 31) + (AST.xthi 32 v) != AST.sext 32 (AST.extract v 1 31) let add insInfo ctxt = - let builder = new StmtBuilder (8) - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let lblEnd = lblSymbol "End" + let builder = IRBuilder (8) + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let lblEnd = builder.NewSymbol "End" let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - let result = tmpVar 32 + let result = builder.NewTempVar 32 let cond = checkOverfolwOnAdd rs rt result startMark insInfo builder builder transThreeOprs insInfo ctxt - let result = tmpVar 32 + let result = builder.NewTempVar 32 let cond = notWordValue rs .| notWordValue rt let cond2 = checkOverfolwOnAdd rs rt result startMark insInfo builder - builder rs .+ extractLow 32 rt) - builder result) - builder rs .+ AST.xtlo 32 rt) + builder result) + builder transThreeOprs insInfo ctxt - let result = tmpVar 32 + let result = builder.NewTempVar 32 startMark insInfo builder builder transThreeOprs insInfo ctxt - let result = tmpVar 64 + let result = builder.NewTempVar 64 let cond = notWordValue rs startMark insInfo builder - builder (extractLow 32 result)) - builder (AST.xtlo 32 result)) + builder transThreeOprs insInfo ctxt startMark insInfo builder builder transThreeOprs insInfo ctxt - let result = tmpVar 64 + let result = builder.NewTempVar 64 let cond = notWordValue rs .| notWordValue rt startMark insInfo builder - builder (extractLow 32 result)) - builder (AST.xtlo 32 result)) + builder transThreeOprs insInfo ctxt startMark insInfo builder builder transThreeOprs insInfo ctxt startMark insInfo builder builder transThreeOprs insInfo ctxt let imm = imm << numI32 16 ctxt.WordBitSize startMark insInfo builder @@ -241,157 +241,154 @@ let aui insInfo ctxt = endMark insInfo builder let b insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let offset = getOneOpr insInfo |> transOneOpr insInfo ctxt - let pc = getRegVar ctxt R.PC startMark insInfo builder - builder transOneOpr insInfo ctxt let pc = getRegVar ctxt R.PC startMark insInfo builder builder transThreeOprs insInfo ctxt - let pc = getRegVar ctxt R.PC let cond = rs == rt let fallThrough = bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo startMark insInfo builder - builder transTwoOprs insInfo ctxt - let pc = getRegVar ctxt R.PC - let cond = le rs (num0 ctxt.WordBitSize) + let cond = AST.le rs (AST.num0 ctxt.WordBitSize) let fallThrough = bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo startMark insInfo builder - builder transTwoOprs insInfo ctxt - let pc = getRegVar ctxt R.PC - let cond = lt rs (num0 ctxt.WordBitSize) + let cond = AST.lt rs (AST.num0 ctxt.WordBitSize) let fallThrough = bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo startMark insInfo builder - builder transTwoOprs insInfo ctxt - let pc = getRegVar ctxt R.PC - let cond = ge rs (num0 ctxt.WordBitSize) + let cond = AST.ge rs (AST.num0 ctxt.WordBitSize) let fallThrough = bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo startMark insInfo builder - builder transTwoOprs insInfo ctxt - let pc = getRegVar ctxt R.PC - let cond = gt rs (num0 ctxt.WordBitSize) + let cond = AST.gt rs (AST.num0 ctxt.WordBitSize) let fallThrough = bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo startMark insInfo builder - builder transThreeOprs insInfo ctxt - let pc = getRegVar ctxt R.PC let cond = rs != rt let fallThrough = bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo startMark insInfo builder - builder transTwoOprs insInfo ctxt - let t = tmpVar wordSz + let t = builder.NewTempVar wordSz let tmp = numI32 (32 - 1) wordSz startMark insInfo builder builder > t == num1 wordSz, Name lblEnd, Name lblContinue)) - builder > t == AST.num1 wordSz) + (AST.name lblEnd) (AST.name lblContinue)) + builder transThreeOprs insInfo ctxt - let result = tmpVar 64 + let result = builder.NewTempVar 64 startMark insInfo builder builder transTwoOprs insInfo ctxt - let t = tmpVar wordSz + let t = builder.NewTempVar wordSz let tmp = numI32 (64 - 1) wordSz startMark insInfo builder builder > t == num1 wordSz, Name lblEnd, Name lblContinue)) - builder > t == AST.num1 wordSz) + (AST.name lblEnd) (AST.name lblContinue)) + builder transTwoOprs insInfo ctxt - let q = tmpVar 128 - let r = tmpVar 128 + let q = builder.NewTempVar 128 + let r = builder.NewTempVar 128 let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO - let rs = zExt 128 rs - let rt = zExt 128 rt + let rs = AST.zext 128 rs + let rt = AST.zext 128 rt builder q) - builder r) + builder q) + builder r) endMark insInfo builder let checkDEXTPosSize pos size = @@ -402,7 +399,7 @@ let checkDEXTPosSize pos size = else raise InvalidOperandException let dext insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) startMark insInfo builder let rt, rs, pos, size = getFourOprs insInfo let rt = transOprToExpr insInfo ctxt rt @@ -431,7 +428,7 @@ let checkDEXTUPosSize pos size = else raise InvalidOperandException let dextx insInfo posSizeCheckFn ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) startMark insInfo builder let rt, rs, pos, size = getFourOprs insInfo let rt = transOprToExpr insInfo ctxt rt @@ -455,7 +452,7 @@ let checkINSorExtPosSize pos size = else raise InvalidOperandException let dins insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) startMark insInfo builder let rt, rs, pos, size = getFourOprs insInfo let rt = transOprToExpr insInfo ctxt rt @@ -468,8 +465,9 @@ let dins insInfo ctxt = let posExpr = numI32 pos ctxt.WordBitSize let getMask size = (1L <<< size) - 1L let mask = numI64 (getMask size) ctxt.WordBitSize - let rs', rt' = if pos = 0 then rs .& mask, rt .& (not mask) - else (rs .& mask) << posExpr, rt .& (not (mask << posExpr)) + let rs', rt' = + if pos = 0 then rs .& mask, rt .& (AST.not mask) + else (rs .& mask) << posExpr, rt .& (AST.not (mask << posExpr)) builder transTwoOprs insInfo ctxt - let q = tmpVar 64 - let r = tmpVar 64 + let q = builder.NewTempVar 64 + let r = builder.NewTempVar 64 let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO if ctxt.WordBitSize = 64 then - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let lblEnd = lblSymbol "End" + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let lblEnd = builder.NewSymbol "End" let cond = notWordValue rs .| notWordValue rt let mask = numI64 0xFFFFFFFFL 64 let rs = rs .& mask let rt = rt .& mask - builder (extractLow 32 q)) - builder (extractLow 32 r)) - builder (AST.xtlo 32 q)) + builder (AST.xtlo 32 r)) + builder rs - let rt = zExt 64 rt + let rs = AST.zext 64 rs + let rt = AST.zext 64 rt builder q) - builder r) + builder q) + builder r) endMark insInfo builder let dmult insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) startMark insInfo builder let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let result = tmpVar 128 + let result = builder.NewTempVar 128 let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO - builder rs) .* (sExt 128 rt)) - builder result) - builder result) + builder rs) .* (AST.sext 128 rt)) + builder result) + builder result) endMark insInfo builder let dmultu insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) startMark insInfo builder let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let result = tmpVar 128 + let result = builder.NewTempVar 128 let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO - builder rs) .* (zExt 128 rt)) - builder result) - builder result) + builder rs) .* (AST.zext 128 rt)) + builder result) + builder result) endMark insInfo builder let drotr insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt let size = numI32 64 64 startMark insInfo builder @@ -574,15 +573,15 @@ let drotr insInfo ctxt = endMark insInfo builder let dsll insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt startMark insInfo builder - if sa = num0 ctxt.WordBitSize then builder transThreeOprs insInfo ctxt let sa = sa .+ numI32 32 64 startMark insInfo builder @@ -590,22 +589,22 @@ let dsll32 insInfo ctxt = endMark insInfo builder let dsllv insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rd, rt, rs = getThreeOprs insInfo |> transThreeOprs insInfo ctxt startMark insInfo builder builder )) endMark insInfo builder let dsra insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt startMark insInfo builder - if sa = num0 ctxt.WordBitSize then builder > sa) endMark insInfo builder let dsra32 insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt let sa = sa .+ numI32 32 64 startMark insInfo builder @@ -613,15 +612,15 @@ let dsra32 insInfo ctxt = endMark insInfo builder let dsrl insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt startMark insInfo builder - if sa = num0 ctxt.WordBitSize then builder > sa) endMark insInfo builder let dsrl32 insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt let sa = sa .+ numI32 32 64 startMark insInfo builder @@ -629,14 +628,14 @@ let dsrl32 insInfo ctxt = endMark insInfo builder let dsrlv insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rd, rt, rs = getThreeOprs insInfo |> transThreeOprs insInfo ctxt startMark insInfo builder builder > (rs .& numI32 63 64)) endMark insInfo builder let ins insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) startMark insInfo builder let rt, rs, pos, size = getFourOprs insInfo let rt = transOprToExpr insInfo ctxt rt @@ -649,13 +648,14 @@ let ins insInfo ctxt = let posExpr = numI32 pos ctxt.WordBitSize let getMask size = (1L <<< size) - 1L let mask = numI64 (getMask size) ctxt.WordBitSize - let rs', rt' = if pos = 0 then rs .& mask, rt .& (not mask) - else (rs .& mask) << posExpr, rt .& (not (mask << posExpr)) + let rs', rt' = + if pos = 0 then rs .& mask, rt .& (AST.not mask) + else (rs .& mask) << posExpr, rt .& (AST.not (mask << posExpr)) builder raise InvalidOperandException let jalr insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rd, rs = getJALROprs insInfo ctxt - let pc = getRegVar ctxt R.PC let r = bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo startMark insInfo builder builder transOneOpr insInfo ctxt - let pc = getRegVar ctxt R.PC startMark insInfo builder - builder transTwoOprs insInfo ctxt startMark insInfo builder - builder transTwoOprs insInfo ctxt startMark insInfo builder - builder > numI32 pos ctxt.WordBitSize builder transTwoOprs insInfo ctxt startMark insInfo builder if ctxt.WordBitSize = 64 then builder (concat (extractLow 16 imm) (num0 16))) - else builder imm) (num0 16)) + (rt := AST.sext 64 (AST.concat (AST.xtlo 16 imm) (AST.num0 16))) + else builder imm) (AST.num0 16)) endMark insInfo builder let madd insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) startMark insInfo builder let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let result = tmpVar 64 + let result = builder.NewTempVar 64 let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO if ctxt.WordBitSize = 64 then - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let lblEnd = lblSymbol "End" + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let lblEnd = builder.NewSymbol "End" let cond = notWordValue rs .| notWordValue rt - let hilo = concat (extractLow 32 hi) (extractLow 32 lo) + let hilo = AST.concat (AST.xtlo 32 hi) (AST.xtlo 32 lo) let mask = numU32 0xFFFFu 64 - builder (extractHigh 32 result)) - builder (extractLow 32 result)) - builder (AST.xthi 32 result)) + builder (AST.xtlo 32 result)) + builder rs .* sExt 64 rt)) - builder result) - builder result) + builder rs .* AST.sext 64 rt)) + builder result) + builder result) endMark insInfo builder let mfhi insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rd = getOneOpr insInfo |> transOneOpr insInfo ctxt startMark insInfo builder builder transOneOpr insInfo ctxt startMark insInfo builder builder transThreeOprs insInfo ctxt - let cond = rt == num0 ctxt.WordBitSize + let cond = rt == AST.num0 ctxt.WordBitSize startMark insInfo builder - builder transThreeOprs insInfo ctxt - let cond = rt != num0 ctxt.WordBitSize + let cond = rt != AST.num0 ctxt.WordBitSize startMark insInfo builder - builder transThreeOprs insInfo ctxt - let result = tmpVar 64 + let result = builder.NewTempVar 64 let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO if ctxt.WordBitSize = 64 then - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let lblEnd = lblSymbol "End" + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let lblEnd = builder.NewSymbol "End" let cond = notWordValue rs .| notWordValue rt - builder (extractLow 32 result)) - builder (AST.xtlo 32 result)) + builder rs .* sExt 64 rt)) - builder result) - builder rs .* AST.sext 64 rt)) + builder result) + builder transTwoOprs insInfo ctxt - let result = tmpVar 64 + let result = builder.NewTempVar 64 let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO if ctxt.WordBitSize = 64 then - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let lblEnd = lblSymbol "End" + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let lblEnd = builder.NewSymbol "End" let cond = notWordValue rs .| notWordValue rt let mask = numI64 0xFFFFFFFFL 64 - builder (extractLow 32 result)) - builder (extractHigh 32 result)) - builder (AST.xtlo 32 result)) + builder (AST.xthi 32 result)) + builder rs .* sExt 64 rt)) - builder result) - builder result) + builder rs .* AST.sext 64 rt)) + builder result) + builder result) endMark insInfo builder let multu insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) startMark insInfo builder let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let result = tmpVar 64 + let result = builder.NewTempVar 64 let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO if ctxt.WordBitSize = 64 then - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let lblEnd = lblSymbol "End" + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let lblEnd = builder.NewSymbol "End" let cond = notWordValue rs .| notWordValue rt let mask = numI64 0xFFFFFFFFL 64 - builder (extractLow 32 result)) - builder (extractHigh 32 result)) - builder (AST.xtlo 32 result)) + builder (AST.xthi 32 result)) + builder rs .* zExt 64 rt)) - builder result) - builder result) + builder rs .* AST.zext 64 rt)) + builder result) + builder result) endMark insInfo builder let nop insInfo = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) startMark insInfo builder endMark insInfo builder let nor insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt startMark insInfo builder - builder transThreeOprs insInfo ctxt startMark insInfo builder builder transThreeOprs insInfo ctxt startMark insInfo builder builder let size = numI32 32 32 startMark insInfo builder if ctxt.WordBitSize = 64 then - let t1 = tmpVar 32 - builder rt) - builder ((t1 << (size .- sa)) .| (t1 >> sa))) + let t1 = builder.NewTempVar 32 + builder rt) + builder ((t1 << (size .- sa)) .| (t1 >> sa))) else builder > sa)) endMark insInfo builder let sb insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rt, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt startMark insInfo builder - builder rt) + builder rt) endMark insInfo builder let sd insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rt, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt startMark insInfo builder - builder rt) + builder rt) endMark insInfo builder let sdl insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rt, mem = getTwoOprs insInfo let baseOffset = transOprToBaseOffset ctxt mem let rt, mem = transTwoOprs insInfo ctxt (rt, mem) - let t1 = tmpVar 64 - let t2 = tmpVar 64 + let t1 = builder.NewTempVar 64 + let t2 = builder.NewTempVar 64 let getMask size = (1L <<< size) - 1L let mask3 = numI64 (getMask 3) 64 let vaddr0To2 = baseOffset .& mask3 let num8 = numI32 8 64 startMark insInfo builder builder .- vaddr0To2) .* num8) - builder .+ vaddr0To2) .* num8) + builder .+ vaddr0To2) .* num8) builder > t1) .| ((mem >> t2) << t2)) endMark insInfo builder let sdr insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rt, mem = getTwoOprs insInfo let baseOffset = transOprToBaseOffset ctxt mem let rt, mem = transTwoOprs insInfo ctxt (rt, mem) - let t1 = tmpVar 64 - let t2 = tmpVar 64 + let t1 = builder.NewTempVar 64 + let t2 = builder.NewTempVar 64 let getMask size = (1L <<< size) - 1L let mask3 = numI64 (getMask 3) ctxt.WordBitSize let vaddr0To2 = baseOffset .& mask3 @@ -1002,51 +1000,51 @@ let sdr insInfo ctxt = endMark insInfo builder let sh insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rt, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt startMark insInfo builder - builder rt) + builder rt) endMark insInfo builder let sw insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rt, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt startMark insInfo builder - builder rt) + builder rt) endMark insInfo builder let swl insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rt, mem = getTwoOprs insInfo let baseOffset = transOprToBaseOffset ctxt mem let rt, mem = transTwoOprs insInfo ctxt (rt, mem) - let t1 = tmpVar 32 - let t2 = tmpVar 32 + let t1 = builder.NewTempVar 32 + let t2 = builder.NewTempVar 32 let getMask size = (1L <<< size) - 1L let mask2 = numI64 (getMask 2) 32 let baseOffset = if ctxt.WordBitSize = 32 then baseOffset - else extractLow 32 baseOffset - let rt = if ctxt.WordBitSize = 32 then rt else extractLow 32 rt + else AST.xtlo 32 baseOffset + let rt = if ctxt.WordBitSize = 32 then rt else AST.xtlo 32 rt let vaddr0To2 = baseOffset .& mask2 let num8 = numI32 8 32 startMark insInfo builder builder .- vaddr0To2) .* num8) - builder .+ vaddr0To2) .* num8) + builder .+ vaddr0To2) .* num8) builder > t1) .| ((mem >> t2) << t2)) endMark insInfo builder let swr insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rt, mem = getTwoOprs insInfo let baseOffset = transOprToBaseOffset ctxt mem let rt, mem = transTwoOprs insInfo ctxt (rt, mem) - let t1 = tmpVar 32 - let t2 = tmpVar 32 + let t1 = builder.NewTempVar 32 + let t2 = builder.NewTempVar 32 let getMask size = (1L <<< size) - 1L let mask2 = numI64 (getMask 2) 32 let baseOffset = if ctxt.WordBitSize = 32 then baseOffset - else extractLow 32 baseOffset - let rt = if ctxt.WordBitSize = 32 then rt else extractLow 32 rt + else AST.xtlo 32 baseOffset + let rt = if ctxt.WordBitSize = 32 then rt else AST.xtlo 32 rt let vaddr0To2 = baseOffset .& mask2 let num8 = numI32 8 32 startMark insInfo builder @@ -1056,222 +1054,222 @@ let swr insInfo ctxt = endMark insInfo builder let seb insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rd, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt startMark insInfo builder if ctxt.WordBitSize = 64 then - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let lblEnd = lblSymbol "End" + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let lblEnd = builder.NewSymbol "End" let cond = notWordValue rt - builder (extract rt 8 0)) - builder (AST.extract rt 8 0)) + builder (extract rt 8 0)) + builder (AST.extract rt 8 0)) endMark insInfo builder let seh insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rd, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt startMark insInfo builder if ctxt.WordBitSize = 64 then - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let lblEnd = lblSymbol "End" + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let lblEnd = builder.NewSymbol "End" let cond = notWordValue rt - builder (extract rt 16 0)) - builder (AST.extract rt 16 0)) + builder (extract rt 16 0)) + builder (AST.extract rt 16 0)) endMark insInfo builder let sll insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt startMark insInfo builder if ctxt.WordBitSize = 64 then - let rt = extractLow 32 rt - builder (rt << extractLow 32 sa)) + let rt = AST.xtlo 32 rt + builder (rt << AST.xtlo 32 sa)) else builder transThreeOprs insInfo ctxt let mask = numI32 31 32 startMark insInfo builder if ctxt.WordBitSize = 64 then - let rt = extractLow 32 rt - builder (rt << (extractLow 32 rs .& mask))) + let rt = AST.xtlo 32 rt + builder (rt << (AST.xtlo 32 rs .& mask))) else builder transThreeOprs insInfo ctxt - let cond = lt rs rt - let rtVal = ite cond (num1 ctxt.WordBitSize) (num0 ctxt.WordBitSize) + let cond = AST.lt rs rt + let rtVal = AST.ite cond (AST.num1 ctxt.WordBitSize) (AST.num0 ctxt.WordBitSize) startMark insInfo builder builder transThreeOprs insInfo ctxt - let cond = lt rs imm - let rtVal = ite cond (num1 ctxt.WordBitSize) (num0 ctxt.WordBitSize) + let cond = AST.lt rs imm + let rtVal = AST.ite cond (AST.num1 ctxt.WordBitSize) (AST.num0 ctxt.WordBitSize) startMark insInfo builder builder transThreeOprs insInfo ctxt - let cond = lt (zExt (wordSz * 2) rs) (zExt (wordSz * 2) imm) - let rtVal = ite cond (num1 ctxt.WordBitSize) (num0 ctxt.WordBitSize) + let cond = AST.lt (AST.zext (wordSz * 2) rs) (AST.zext (wordSz * 2) imm) + let rtVal = AST.ite cond (AST.num1 ctxt.WordBitSize) (AST.num0 ctxt.WordBitSize) startMark insInfo builder builder transThreeOprs insInfo ctxt - let cond = lt (zExt (wordSz * 2) rs) (zExt (wordSz * 2) rt) - let rtVal = ite cond (num1 ctxt.WordBitSize) (num0 ctxt.WordBitSize) + let cond = AST.lt (AST.zext (wordSz * 2) rs) (AST.zext (wordSz * 2) rt) + let rtVal = AST.ite cond (AST.num1 ctxt.WordBitSize) (AST.num0 ctxt.WordBitSize) startMark insInfo builder builder startMark insInfo builder if ctxt.WordBitSize = 64 then - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let lblEnd = lblSymbol "End" + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let lblEnd = builder.NewSymbol "End" let cond = notWordValue rt - let t1 = tmpVar 32 - builder rt) - builder (t1 ?>> sa)) - builder + builder rt) + builder (t1 ?>> sa)) + builder > sa) endMark insInfo builder let srl insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rd, rt, sa = getThreeOprs insInfo let rd, rt = transTwoOprs insInfo ctxt (rd, rt) let sa = numI32 (int32 (transOprToImm sa)) 32 startMark insInfo builder if ctxt.WordBitSize = 64 then - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let lblEnd = lblSymbol "End" + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let lblEnd = builder.NewSymbol "End" let cond = notWordValue rt - let t1 = tmpVar 32 - builder rt) - builder (t1 >> sa)) - builder + builder rt) + builder (t1 >> sa)) + builder > sa) endMark insInfo builder let srlv insInfo ctxt = - let builder = new StmtBuilder (16) + let builder = IRBuilder (16) let rd, rt, rs = getThreeOprs insInfo |> transThreeOprs insInfo ctxt let mask = numI32 31 32 startMark insInfo builder if ctxt.WordBitSize = 64 then - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let lblEnd = lblSymbol "End" + let lblL0 = builder.NewSymbol "L0" + let lblL1 = builder.NewSymbol "L1" + let lblEnd = builder.NewSymbol "End" let cond = notWordValue rt - let t1 = tmpVar 32 - builder rt) - builder (t1 >> (extractLow 32 rs .& mask))) - builder + builder rt) + builder (t1 >> (AST.xtlo 32 rs .& mask))) + builder > (rs .& mask)) endMark insInfo builder let subu insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt startMark insInfo builder builder transThreeOprs insInfo ctxt let cond = notWordValue rs .| notWordValue rt startMark insInfo builder - builder transTwoOprs insInfo ctxt startMark insInfo builder - builder transThreeOprs insInfo ctxt startMark insInfo builder builder rt) endMark insInfo builder let xori insInfo ctxt = - let builder = new StmtBuilder (4) + let builder = IRBuilder (4) let rt, rs, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt startMark insInfo builder builder imm) @@ -1340,7 +1338,7 @@ let translate insInfo (ctxt: TranslationContext) = | Op.INS -> ins64 insInfo ctxt | Op.JALR | Op.JALRHB -> jalr insInfo ctxt | Op.JR | Op.JRHB -> jr insInfo ctxt - | Op.PAUSE -> sideEffects insInfo Pause + | Op.PAUSE -> sideEffects insInfo Delay | Op.LB | Op.LH | Op.LW | Op.LD -> load insInfo ctxt | Op.LBU | Op.LHU | Op.LWU -> loadu insInfo ctxt | Op.LDC1 | Op.LWC1 | Op.SDC1 | Op.SWC1 -> sideEffects insInfo UnsupportedFP diff --git a/src/FrontEnd/MIPS/MIPSParser.fs b/src/FrontEnd/BinLifter/MIPS/MIPSParser.fs similarity index 99% rename from src/FrontEnd/MIPS/MIPSParser.fs rename to src/FrontEnd/BinLifter/MIPS/MIPSParser.fs index 038ff58e..0fc1119c 100644 --- a/src/FrontEnd/MIPS/MIPSParser.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSParser.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module B2R2.FrontEnd.MIPS.Parser +module B2R2.FrontEnd.BinLifter.MIPS.Parser open B2R2 -open B2R2.FrontEnd.MIPS.Helper -open B2R2.FrontEnd.MIPS.Utils +open B2R2.FrontEnd.BinLifter.MIPS.Helper +open B2R2.FrontEnd.BinLifter.MIPS.Utils /// Check encoded field value let nd binary target = pickBit binary 17u = target diff --git a/src/FrontEnd/MIPS/MIPSParser.fsi b/src/FrontEnd/BinLifter/MIPS/MIPSParser.fsi similarity index 97% rename from src/FrontEnd/MIPS/MIPSParser.fsi rename to src/FrontEnd/BinLifter/MIPS/MIPSParser.fsi index aa356d79..47dd926d 100644 --- a/src/FrontEnd/MIPS/MIPSParser.fsi +++ b/src/FrontEnd/BinLifter/MIPS/MIPSParser.fsi @@ -23,7 +23,7 @@ *) /// MIPS instruction parser. -module B2R2.FrontEnd.MIPS.Parser +module B2R2.FrontEnd.BinLifter.MIPS.Parser open B2R2 diff --git a/src/FrontEnd/MIPS/MIPSRegExprs.fs b/src/FrontEnd/BinLifter/MIPS/MIPSRegExprs.fs similarity index 98% rename from src/FrontEnd/MIPS/MIPSRegExprs.fs rename to src/FrontEnd/BinLifter/MIPS/MIPSRegExprs.fs index 790c3691..44246e18 100644 --- a/src/FrontEnd/MIPS/MIPSRegExprs.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSRegExprs.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.MIPS +namespace B2R2.FrontEnd.BinLifter.MIPS open B2R2 open B2R2.BinIR.LowUIR @@ -101,7 +101,7 @@ type internal RegExprs (wordSize) = member val HI = var regType (Register.toRegID Register.HI) "HI" with get member val LO = var regType (Register.toRegID Register.LO) "LO" with get - member val PC = var regType (Register.toRegID Register.PC) "PC" with get + member val PC = AST.pcvar regType "PC" with get member __.GetRegVar (name) = match name with @@ -172,6 +172,6 @@ type internal RegExprs (wordSize) = | R.F29 -> __.F29 | R.F30 -> __.F30 | R.F31 -> __.F31 - | _ -> raise B2R2.FrontEnd.UnhandledRegExprException + | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/MIPS/MIPSRegister.fs b/src/FrontEnd/BinLifter/MIPS/MIPSRegister.fs similarity index 99% rename from src/FrontEnd/MIPS/MIPSRegister.fs rename to src/FrontEnd/BinLifter/MIPS/MIPSRegister.fs index 150cba04..c05d55dc 100644 --- a/src/FrontEnd/MIPS/MIPSRegister.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSRegister.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.MIPS +namespace B2R2.FrontEnd.BinLifter.MIPS open B2R2 diff --git a/src/FrontEnd/MIPS/MIPSRegisterBay.fs b/src/FrontEnd/BinLifter/MIPS/MIPSRegisterBay.fs similarity index 95% rename from src/FrontEnd/MIPS/MIPSRegisterBay.fs rename to src/FrontEnd/BinLifter/MIPS/MIPSRegisterBay.fs index 580dde27..aceefc77 100644 --- a/src/FrontEnd/MIPS/MIPSRegisterBay.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSRegisterBay.fs @@ -22,17 +22,15 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.MIPS +namespace B2R2.FrontEnd.BinLifter.MIPS open B2R2 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type MIPSRegisterBay (wordSize) = +type MIPSRegisterBay internal (wordSize, R: RegExprs) = inherit RegisterBay () - let R = RegExprs (wordSize) - override __.GetAllRegExprs () = [ R.HI; R.LO; R.PC; R.R0; R.R1; R.R2; R.R3; R.R4; R.R5; R.R6; R.R7; R.R8; R.R9; R.R10; R.R11; R.R12; R.R13; R.R14; R.R15; R.R16; R.R17; R.R18; @@ -53,11 +51,14 @@ type MIPSRegisterBay (wordSize) = R.R29; R.R30; R.R31 ] override __.RegIDFromRegExpr (e) = - match e with + match e.E with | Var (_,id, _,_) -> id | PCVar (_, _) -> Register.toRegID Register.PC | _ -> failwith "not a register expression" + override __.RegIDToRegExpr (id) = + Register.ofRegID id |> R.GetRegVar + override __.StrToRegExpr s = match s with | "HI" -> R.HI diff --git a/src/FrontEnd/MIPS/MIPSRegisterSet.fs b/src/FrontEnd/BinLifter/MIPS/MIPSRegisterSet.fs similarity index 60% rename from src/FrontEnd/MIPS/MIPSRegisterSet.fs rename to src/FrontEnd/BinLifter/MIPS/MIPSRegisterSet.fs index ac1da368..0fd21e83 100644 --- a/src/FrontEnd/MIPS/MIPSRegisterSet.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSRegisterSet.fs @@ -22,25 +22,28 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.MIPS +namespace B2R2.FrontEnd.BinLifter.MIPS open B2R2 +module private RegisterSetLiteral = + let [] arrLen = 2 + +open RegisterSetLiteral + type MIPSRegisterSet (bitArray: uint64 [], s: Set) = inherit NonEmptyRegisterSet (bitArray, s) - static let defaultSize = 2 - static let emptyArr = Array.init defaultSize (fun _ -> 0UL) - static member EmptySet = - new MIPSRegisterSet (emptyArr, Set.empty) :> RegisterSet + new () = MIPSRegisterSet (RegisterSet.MakeInternalBitArray arrLen, Set.empty) override __.Tag = RegisterSetTag.MIPS - override __.ArrSize = defaultSize - override __.New x s = new MIPSRegisterSet (x, s) :> RegisterSet - override __.Empty = MIPSRegisterSet.EmptySet - override __.EmptyArr = emptyArr - override __.Project x = - match Register.ofRegID x with + + override __.ArrSize = arrLen + + override __.New arr s = new MIPSRegisterSet (arr, s) :> RegisterSet + + override __.RegIDToIndex rid = + match Register.ofRegID rid with | R.R0 -> 0 | R.R1 -> 1 | R.R2 -> 2 @@ -110,10 +113,82 @@ type MIPSRegisterSet (bitArray: uint64 [], s: Set) = | R.PC -> 66 | _ -> -1 + override __.IndexToRegID index = + match index with + | 0 -> R.R0 + | 1 -> R.R1 + | 2 -> R.R2 + | 3 -> R.R3 + | 4 -> R.R4 + | 5 -> R.R5 + | 6 -> R.R6 + | 7 -> R.R7 + | 8 -> R.R8 + | 9 -> R.R9 + | 10 -> R.R10 + | 11 -> R.R11 + | 12 -> R.R12 + | 13 -> R.R13 + | 14 -> R.R14 + | 15 -> R.R15 + | 16 -> R.R16 + | 17 -> R.R17 + | 18 -> R.R18 + | 19 -> R.R19 + | 20 -> R.R20 + | 21 -> R.R21 + | 22 -> R.R22 + | 23 -> R.R23 + | 24 -> R.R24 + | 25 -> R.R25 + | 26 -> R.R26 + | 27 -> R.R27 + | 28 -> R.R28 + | 29 -> R.R29 + | 30 -> R.R30 + | 31 -> R.R31 + | 32 -> R.F0 + | 33 -> R.F1 + | 34 -> R.F2 + | 35 -> R.F3 + | 36 -> R.F4 + | 37 -> R.F5 + | 38 -> R.F6 + | 39 -> R.F7 + | 40 -> R.F8 + | 41 -> R.F9 + | 42 -> R.F10 + | 43 -> R.F11 + | 44 -> R.F12 + | 45 -> R.F13 + | 46 -> R.F14 + | 47 -> R.F15 + | 48 -> R.F16 + | 49 -> R.F17 + | 50 -> R.F18 + | 51 -> R.F19 + | 52 -> R.F20 + | 53 -> R.F21 + | 54 -> R.F22 + | 55 -> R.F23 + | 56 -> R.F24 + | 57 -> R.F25 + | 58 -> R.F26 + | 59 -> R.F27 + | 60 -> R.F28 + | 61 -> R.F29 + | 62 -> R.F30 + | 63 -> R.F31 + | 64 -> R.HI + | 65 -> R.LO + | 66 -> R.PC + | _ -> Utils.impossible () + |> Register.toRegID + override __.ToString () = sprintf "MIPSRegisterSet<%x, %x>" __.BitArray.[0] __.BitArray.[1] [] module MIPSRegisterSet = - let singleton = RegisterSetBuilder.singletonBuilder MIPSRegisterSet.EmptySet - let empty = MIPSRegisterSet.EmptySet + let singleton rid = MIPSRegisterSet().Add(rid) + let empty = MIPSRegisterSet () :> RegisterSet diff --git a/src/FrontEnd/MIPS/MIPSSupportedOpcode.txt b/src/FrontEnd/BinLifter/MIPS/MIPSSupportedOpcode.txt similarity index 100% rename from src/FrontEnd/MIPS/MIPSSupportedOpcode.txt rename to src/FrontEnd/BinLifter/MIPS/MIPSSupportedOpcode.txt diff --git a/src/FrontEnd/MIPS/MIPSTypes.fs b/src/FrontEnd/BinLifter/MIPS/MIPSTypes.fs similarity index 98% rename from src/FrontEnd/MIPS/MIPSTypes.fs rename to src/FrontEnd/BinLifter/MIPS/MIPSTypes.fs index af02f592..ee8e0cd4 100644 --- a/src/FrontEnd/MIPS/MIPSTypes.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSTypes.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.MIPS +namespace B2R2.FrontEnd.BinLifter.MIPS open B2R2 open System.Runtime.CompilerServices -[] +[] do () exception internal InvalidConditionException diff --git a/src/FrontEnd/MIPS/MIPSUtils.fs b/src/FrontEnd/BinLifter/MIPS/MIPSUtils.fs similarity index 97% rename from src/FrontEnd/MIPS/MIPSUtils.fs rename to src/FrontEnd/BinLifter/MIPS/MIPSUtils.fs index 3f823bb8..274abbeb 100644 --- a/src/FrontEnd/MIPS/MIPSUtils.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSUtils.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.MIPS.Utils +module internal B2R2.FrontEnd.BinLifter.MIPS.Utils open B2R2 diff --git a/src/FrontEnd/BinLifter/MIPS/README.md b/src/FrontEnd/BinLifter/MIPS/README.md new file mode 100644 index 00000000..bb44aed2 --- /dev/null +++ b/src/FrontEnd/BinLifter/MIPS/README.md @@ -0,0 +1,11 @@ +# B2R2.FrontEnd.BinLifter.MIPS + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.BinLifter.MIPS Package? + +`B2R2.FrontEnd.BinLifter.MIPS` includes MIPS parsers and lifters. diff --git a/src/FrontEnd/BinLifter/Optimizer/B2R2.FrontEnd.BinLifter.Optimizer.fsproj b/src/FrontEnd/BinLifter/Optimizer/B2R2.FrontEnd.BinLifter.Optimizer.fsproj new file mode 100644 index 00000000..663167ae --- /dev/null +++ b/src/FrontEnd/BinLifter/Optimizer/B2R2.FrontEnd.BinLifter.Optimizer.fsproj @@ -0,0 +1,25 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 local optimizer. + + + + + + + + + + + + + + + + + diff --git a/src/FrontEnd/BinLifter/Optimizer/ConstantFolding.fs b/src/FrontEnd/BinLifter/Optimizer/ConstantFolding.fs new file mode 100644 index 00000000..18f243ab --- /dev/null +++ b/src/FrontEnd/BinLifter/Optimizer/ConstantFolding.fs @@ -0,0 +1,240 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +[] +module B2R2.FrontEnd.BinLifter.ConstantFolding + +open System.Collections.Generic +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR + +type Context = { + VarMap: Dictionary + TempVarMap: Dictionary +} + +let private concretizeUnOp unopType bv = + match unopType with + | UnOpType.NEG -> BitVector.neg bv + | UnOpType.NOT -> BitVector.bnot bv + | UnOpType.FSQRT -> BitVector.fsqrt bv + | UnOpType.FCOS -> BitVector.fcos bv + | UnOpType.FSIN -> BitVector.fsin bv + | UnOpType.FTAN -> BitVector.ftan bv + | UnOpType.FATAN -> BitVector.fatan bv + | _ -> Utils.impossible () + +let private concretizeBinOp binopType bv1 bv2 = + match binopType with + | BinOpType.ADD -> BitVector.add bv1 bv2 + | BinOpType.SUB -> BitVector.sub bv1 bv2 + | BinOpType.MUL -> BitVector.mul bv1 bv2 + | BinOpType.DIV -> BitVector.div bv1 bv2 + | BinOpType.SDIV -> BitVector.sdiv bv1 bv2 + | BinOpType.MOD -> BitVector.modulo bv1 bv2 + | BinOpType.SMOD -> BitVector.smodulo bv1 bv2 + | BinOpType.SHL -> BitVector.shl bv1 bv2 + | BinOpType.SHR -> BitVector.shr bv1 bv2 + | BinOpType.SAR -> BitVector.sar bv1 bv2 + | BinOpType.AND -> BitVector.band bv1 bv2 + | BinOpType.OR -> BitVector.bor bv1 bv2 + | BinOpType.XOR -> BitVector.bxor bv1 bv2 + | BinOpType.CONCAT -> BitVector.concat bv1 bv2 + | BinOpType.FADD -> BitVector.fadd bv1 bv2 + | BinOpType.FSUB -> BitVector.fsub bv1 bv2 + | BinOpType.FMUL -> BitVector.fmul bv1 bv2 + | BinOpType.FDIV -> BitVector.fdiv bv1 bv2 + | BinOpType.FPOW -> BitVector.fpow bv1 bv2 + | BinOpType.FLOG -> BitVector.flog bv1 bv2 + | _ -> Utils.impossible () + +let private concretizeRelOp relopType bv1 bv2 = + match relopType with + | RelOpType.EQ -> BitVector.eq bv1 bv2 + | RelOpType.NEQ -> BitVector.neq bv1 bv2 + | RelOpType.GT -> BitVector.gt bv1 bv2 + | RelOpType.GE -> BitVector.ge bv1 bv2 + | RelOpType.SGT -> BitVector.sgt bv1 bv2 + | RelOpType.SGE -> BitVector.sge bv1 bv2 + | RelOpType.LT -> BitVector.lt bv1 bv2 + | RelOpType.LE -> BitVector.le bv1 bv2 + | RelOpType.SLT -> BitVector.slt bv1 bv2 + | RelOpType.SLE -> BitVector.sle bv1 bv2 + | RelOpType.FGT -> BitVector.fgt bv1 bv2 + | RelOpType.FGE -> BitVector.fge bv1 bv2 + | RelOpType.FLT -> BitVector.flt bv1 bv2 + | RelOpType.FLE -> BitVector.fle bv1 bv2 + | _ -> Utils.impossible () + +let private concretizeCast castType rt bv = + match castType with + | CastKind.SignExt -> BitVector.sext bv rt + | CastKind.ZeroExt -> BitVector.zext bv rt + | CastKind.IntToFloat -> BitVector.itof bv rt + | CastKind.FtoIRound -> BitVector.ftoiround bv rt + | CastKind.FtoICeil -> BitVector.ftoiceil bv rt + | CastKind.FtoIFloor -> BitVector.ftoifloor bv rt + | CastKind.FtoITrunc -> BitVector.ftoitrunc bv rt + | CastKind.FloatCast -> BitVector.fcast bv rt + | _ -> Utils.impossible () + +let rec replace ctxt expr = + match expr.E with + | Var (_, name, _, _) -> + match ctxt.VarMap.TryGetValue name with + | true, e -> struct (true, e) + | _ -> struct (false, expr) + | TempVar (_, name) -> + match ctxt.TempVarMap.TryGetValue name with + | (true, e) -> struct (true, e) + | _ -> struct (false, expr) + | UnOp (t, e, _) -> + let struct (changed, e) = replace ctxt e + if changed then + match e.E with + | Num bv -> struct (true, AST.num <| concretizeUnOp t bv) + | _ -> struct (true, AST.unop t e) + else struct (false, expr) + | BinOp (BinOpType.ADD, _, e, { E = Num bv }, _) + | BinOp (BinOpType.ADD, _, { E = Num bv }, e, _) + when BitVector.isZero bv -> + let struct (changed, e') = replace ctxt e + if changed then struct (true, e') else struct (true, e) + | BinOp (BinOpType.MUL, _, e, { E = Num bv }, _) + | BinOp (BinOpType.MUL, _, { E = Num bv }, e, _) + when BitVector.isOne bv -> + let struct (changed, e') = replace ctxt e + if changed then struct (true, e') else struct (true, e) + | BinOp (t, _, e1, e2, _) -> + let struct (changed1, e1) = replace ctxt e1 + let struct (changed2, e2) = replace ctxt e2 + match e1.E, e2.E with + | Num bv1, Num bv2 -> struct (true, AST.num <| concretizeBinOp t bv1 bv2) + | _ -> + if changed1 || changed2 then struct (true, AST.binop t e1 e2) + else struct (false, expr) + | RelOp (t, e1, e2, _) -> + let struct (changed1, e1) = replace ctxt e1 + let struct (changed2, e2) = replace ctxt e2 + match e1.E, e2.E with + | Num bv1, Num bv2 -> struct (true, AST.num <| concretizeRelOp t bv1 bv2) + | _ -> + if changed1 || changed2 then struct (true, AST.relop t e1 e2) + else struct (false, expr) + | Load (endian, rt, e, _) -> + let struct (changed, e') = replace ctxt e + if changed then struct (true, AST.load endian rt e') + else struct (false, expr) + | Ite (cond, e1, e2, _) -> + let struct (changed0, cond) = replace ctxt cond + let struct (changed1, e1) = replace ctxt e1 + let struct (changed2, e2) = replace ctxt e2 + if changed0 || changed1 || changed2 then + match cond.E with + | Num bv -> + if BitVector.isTrue bv then struct (true, e1) + else struct (false, e2) + | _ -> struct (true, AST.ite cond e1 e2) + else struct (false, expr) + | Cast (kind, rt, e, _) -> + let struct (changed, e) = replace ctxt e + if changed then + match e.E with + | Num bv -> struct (true, AST.num <| concretizeCast kind rt bv) + | _ -> struct (true, AST.cast kind rt e) + else struct (false, expr) + | Extract (e, rt, pos, _) -> + let struct (changed, e) = replace ctxt e + if changed then + match e.E with + | Num bv -> struct (true, AST.num <| BitVector.extract bv rt pos) + | _ -> struct (true, AST.extract e rt pos) + else struct (false, expr) + | _ -> struct (false, expr) + +let updateContextAtDef ctxt dst src = + match dst.E, src.E with + | Var (_, r, _, _), Num _ -> ctxt.VarMap.TryAdd (r, src) |> ignore + | Var (_, r, _, _), _ -> ctxt.VarMap.Remove (r) |> ignore + | TempVar (_, n), Num _ -> ctxt.TempVarMap.TryAdd (n, src) |> ignore + | TempVar (_, n), _ -> ctxt.TempVarMap.Remove (n) |> ignore + | _ -> () + +let rec optimizeLoop (stmts: Stmt []) idx ctxt = + if Array.length stmts > idx then + match stmts.[idx].S with + | Store (endian, e1, e2) -> + let struct (c1, e1) = replace ctxt e1 + let struct (c2, e2) = replace ctxt e2 + if c1 || c2 then stmts.[idx] <- AST.store endian e1 e2 else () + optimizeLoop stmts (idx + 1) ctxt + | InterJmp (e, t) -> + let struct (changed, e) = replace ctxt e + if changed then stmts.[idx] <- AST.interjmp e t else () + optimizeLoop stmts (idx + 1) ctxt + | InterCJmp (cond, e1, e2) -> + let struct (c0, cond) = replace ctxt cond + let struct (c1, e1) = replace ctxt e1 + let struct (c2, e2) = replace ctxt e2 + if c0 || c1 || c2 then + stmts.[idx] <- + match cond.E with + | Num n when BitVector.isOne n -> AST.interjmp e1 InterJmpKind.Base + | Num _ -> AST.interjmp e2 InterJmpKind.Base + | _ -> AST.intercjmp cond e1 e2 + else () + optimizeLoop stmts (idx + 1) ctxt + | Jmp (e) -> + let struct (changed, e) = replace ctxt e + if changed then stmts.[idx] <- AST.jmp e else () + optimizeLoop stmts (idx + 1) ctxt + | CJmp (cond, e1, e2) -> + let struct (c0, cond) = replace ctxt cond + let struct (c1, e1) = replace ctxt e1 + let struct (c2, e2) = replace ctxt e2 + if c0 || c1 || c2 then + stmts.[idx] <- + match cond.E with + | Num (n) when BitVector.isOne n -> AST.jmp e1 + | Num (_) -> AST.jmp e2 + | _ -> AST.cjmp cond e1 e2 + else () + optimizeLoop stmts (idx + 1) ctxt + | LMark _ -> optimizeLoop stmts (idx + 1) ctxt + | Put (lhs, rhs) -> + let rhs = match replace ctxt rhs with + | true, rhs -> stmts.[idx] <- AST.put lhs rhs; rhs + | _ -> rhs + updateContextAtDef ctxt lhs rhs + optimizeLoop stmts (idx + 1) ctxt + | ISMark _ | IEMark _ | SideEffect _ -> + optimizeLoop stmts (idx + 1) ctxt + else stmts + +/// Assuming that the stmts are localized, i.e., those stmts represent a basic +/// block, perform local constant folding. +let optimize (stmts: Stmt []) = + let stmts = Array.copy stmts + optimizeLoop stmts 0 { VarMap = Dictionary (); TempVarMap = Dictionary () } diff --git a/src/FrontEnd/BinLifter/Optimizer/DeadCodeElimination.fs b/src/FrontEnd/BinLifter/Optimizer/DeadCodeElimination.fs new file mode 100644 index 00000000..6047ff1f --- /dev/null +++ b/src/FrontEnd/BinLifter/Optimizer/DeadCodeElimination.fs @@ -0,0 +1,149 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +[] +module B2R2.FrontEnd.BinLifter.DeadCodeElimination + +open B2R2 +open B2R2.BinIR.LowUIR + +type DeadCodeRemovalContext = { + UseRegisters: RegisterSet + OutRegisters: RegisterSet + UseTempVar: Set + OutTempVar: Set + IsLastBlock: bool +} + +let emptyCtxt = + { UseRegisters = RegisterSet.empty + OutRegisters = RegisterSet.empty + UseTempVar = Set.empty + OutTempVar= Set.empty + IsLastBlock = false } + +let removeUse n ctxt = + { ctxt with UseRegisters = RegisterSet.remove n ctxt.UseRegisters } + +let removeTempUse n ctxt = + { ctxt with UseTempVar = Set.remove n ctxt.UseTempVar } + +let updateUse ei ctxt = + { ctxt with UseTempVar = Set.union ei.TempVarsUsed ctxt.UseTempVar + UseRegisters = RegisterSet.union ei.VarsUsed ctxt.UseRegisters } + +let updateUse2 ei1 ei2 ctxt = + { ctxt with + UseTempVar = Set.union ei1.TempVarsUsed ctxt.UseTempVar + |> Set.union ei2.TempVarsUsed + UseRegisters = RegisterSet.union ei1.VarsUsed ctxt.UseRegisters + |> RegisterSet.union ei2.VarsUsed } + +let updateUse3 ei1 ei2 ei3 ctxt = + { ctxt with + UseTempVar = Set.union ei1.TempVarsUsed ctxt.UseTempVar + |> Set.union ei2.TempVarsUsed + |> Set.union ei3.TempVarsUsed + UseRegisters = RegisterSet.union ei1.VarsUsed ctxt.UseRegisters + |> RegisterSet.union ei2.VarsUsed + |> RegisterSet.union ei3.VarsUsed } + +let updateOut rs ctxt = + { ctxt with OutRegisters = RegisterSet.union rs ctxt.OutRegisters } + +let updateTempOut n ctxt = + { ctxt with OutTempVar = Set.add n ctxt.OutTempVar } + +let rec createLoop (outs: Stmt []) (ins: Stmt []) (used: bool []) iIdx oIdx = + if oIdx < outs.Length then + if used.[iIdx] then + outs.[oIdx] <- ins.[iIdx] + createLoop outs ins used (iIdx + 1) (oIdx + 1) + else createLoop outs ins used (iIdx + 1) oIdx + else outs + +let createReducedStmts (stmts: Stmt []) reducedLen (used: bool []) = + createLoop (Array.zeroCreate reducedLen) stmts used 0 0 + +let rec optimizeLoop (stmts: Stmt []) (used: bool []) idx len ctxt = + if idx >= 0 then + match stmts.[idx].S with + | Store (_, e1, e2) -> + let ei1 = AST.getExprInfo e1 + let ei2 = AST.getExprInfo e2 + optimizeLoop stmts used (idx - 1) len (updateUse2 ei1 ei2 ctxt) + | InterJmp (e, _) -> + let ei = AST.getExprInfo e + optimizeLoop stmts used (idx - 1) len (updateUse ei ctxt) + | InterCJmp (e, e1, e2) -> + let ei = AST.getExprInfo e + let ei1 = AST.getExprInfo e1 + let ei2 = AST.getExprInfo e2 + optimizeLoop stmts used (idx - 1) len (updateUse3 ei ei1 ei2 ctxt) + | Jmp e -> + let ei = AST.getExprInfo e + optimizeLoop stmts used (idx - 1) len (updateUse ei ctxt) + | CJmp (e, e1, e2) -> + let ei = AST.getExprInfo e + let ei1 = AST.getExprInfo e1 + let ei2 = AST.getExprInfo e2 + optimizeLoop stmts used (idx - 1) len (updateUse3 ei ei1 ei2 ctxt) + | Put (v, e) when v = e -> + used.[idx] <- false + optimizeLoop stmts used (idx - 1) (len - 1) ctxt + | Put ({ E = Var (_, rid, _, rs) }, rhs) -> + let isUsed = RegisterSet.exist rid ctxt.UseRegisters + let ctxt = if isUsed then removeUse rid ctxt else ctxt + if not isUsed && RegisterSet.exist rid ctxt.OutRegisters then + used.[idx] <- false + optimizeLoop stmts used (idx - 1) (len - 1) ctxt + else + let ctxt = updateOut rs ctxt + let ctxt = updateUse (AST.getExprInfo rhs) ctxt + optimizeLoop stmts used (idx - 1) len ctxt + | Put ({ E = TempVar (_, n) }, rhs) -> + let isUsed = Set.contains n ctxt.UseTempVar + let ctxt = if isUsed then removeTempUse n ctxt else ctxt + if not isUsed && (ctxt.IsLastBlock || Set.contains n ctxt.OutTempVar) then + used.[idx] <- false + optimizeLoop stmts used (idx - 1) (len - 1) ctxt + else + let ctxt = updateTempOut n ctxt + let ctxt = updateUse (AST.getExprInfo rhs) ctxt + optimizeLoop stmts used (idx - 1) len ctxt + | LMark _ -> + optimizeLoop stmts used (idx - 1) len { ctxt with IsLastBlock = false } + | ISMark _ -> + optimizeLoop stmts used (idx - 1) len { ctxt with IsLastBlock = false } + | IEMark _ -> + optimizeLoop stmts used (idx - 1) len { ctxt with IsLastBlock = true } + | _ -> optimizeLoop stmts used (idx - 1) len ctxt + else createReducedStmts stmts len used + +/// Assuming that the stmts are localized, i.e., those stmts represent a basic +/// block, perform dead code elimination. +let optimize (stmts: Stmt []) = + let used = Array.init stmts.Length (fun _ -> true) + let len = stmts.Length + optimizeLoop stmts used (len - 1) len emptyCtxt diff --git a/src/FrontEnd/BinLifter/Optimizer/LocalOptimizer.fs b/src/FrontEnd/BinLifter/Optimizer/LocalOptimizer.fs new file mode 100644 index 00000000..24d7cbce --- /dev/null +++ b/src/FrontEnd/BinLifter/Optimizer/LocalOptimizer.fs @@ -0,0 +1,65 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter + +open B2R2.BinIR.LowUIR + +[] +module private Localizer = + let rec breakByMark acc (stmts: Stmt []) idx = + if idx < stmts.Length then + match stmts.[idx].S with + | ISMark (_) + | LMark (_) -> + let left, right = Array.splitAt idx stmts + breakByMark (left :: acc) right 1 + | _ -> + breakByMark acc stmts (idx + 1) + else List.rev (stmts :: acc) |> List.toArray + + let breakIntoBlocks (stmts: Stmt []) = + if Array.length stmts = 0 then [| stmts |] + else breakByMark [] stmts 1 + +/// Intra-block local IR optimizer. +type LocalOptimizer = + /// Remove unnecessary IEMark to ease the analysis. + static member private TrimIEMark (stmts: Stmt []) = + let last = stmts.[stmts.Length - 1].S + let secondLast = stmts.[stmts.Length - 2].S + match secondLast, last with + | InterJmp _, IEMark _ + | InterCJmp _, IEMark _ -> + Array.sub stmts 0 (stmts.Length - 1) + | _ -> stmts + + /// Run optimization on a flattened IR statements (an array of IR statements). + static member Optimize stmts = + LocalOptimizer.TrimIEMark stmts + |> breakIntoBlocks + |> Array.map (fun stmts -> + ConstantFolding.optimize stmts + |> DeadCodeElimination.optimize) + |> Array.concat diff --git a/src/FrontEnd/BinLifter/Optimizer/README.md b/src/FrontEnd/BinLifter/Optimizer/README.md new file mode 100644 index 00000000..82d28684 --- /dev/null +++ b/src/FrontEnd/BinLifter/Optimizer/README.md @@ -0,0 +1,12 @@ +# B2R2.FrontEnd.BinLifter.Optimizer + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.BinLifter.Optimizer Package? + +`B2R2.FrontEnd.BinLifter.Optimizer` declares local IR optimizers that can be +used to optimize LowUIR statements while lifting them. diff --git a/src/FrontEnd/BinLifter/TMS320C6000/B2R2.FrontEnd.BinLifter.TMS320C6000.fsproj b/src/FrontEnd/BinLifter/TMS320C6000/B2R2.FrontEnd.BinLifter.TMS320C6000.fsproj new file mode 100644 index 00000000..3d21b944 --- /dev/null +++ b/src/FrontEnd/BinLifter/TMS320C6000/B2R2.FrontEnd.BinLifter.TMS320C6000.fsproj @@ -0,0 +1,33 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 TMS frontend. + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FrontEnd/BinLifter/TMS320C6000/README.md b/src/FrontEnd/BinLifter/TMS320C6000/README.md new file mode 100644 index 00000000..f2132dda --- /dev/null +++ b/src/FrontEnd/BinLifter/TMS320C6000/README.md @@ -0,0 +1,11 @@ +# B2R2.FrontEnd.BinLifter.TMS320C6000 + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.BinLifter.TMS320C6000 Package? + +`B2R2.FrontEnd.BinLifter.TMS320C6000` includes TMS320C6000 parsers and lifters. diff --git a/src/FrontEnd/TMS320C6000/TMS320C6000.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000.fs similarity index 71% rename from src/FrontEnd/TMS320C6000/TMS320C6000.fs rename to src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000.fs index 7e16847b..49cb7ac7 100644 --- a/src/FrontEnd/TMS320C6000/TMS320C6000.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000.fs @@ -22,15 +22,16 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.TMS320C6000 +namespace B2R2.FrontEnd.BinLifter.TMS320C6000 -open B2R2.FrontEnd +open B2R2 +open B2R2.FrontEnd.BinLifter /// Translation context for TMS320C6000 instructions. -type TMS320C6000TranslationContext (isa) = +type TMS320C6000TranslationContext internal (isa, regexprs) = inherit TranslationContext (isa) /// Register expressions. - member val private RegExprs: RegExprs = RegExprs (isa.WordSize) + member val private RegExprs: RegExprs = regexprs override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar override __.GetPseudoRegVar _id _pos = failwith "Implement" @@ -38,7 +39,18 @@ type TMS320C6000TranslationContext (isa) = /// instruction type (Instruction). type TMS320C6000Parser () = inherit Parser () - override __.Parse binReader ctxt addr pos = - Parser.parse binReader ctxt addr pos :> Instruction + let mutable inParallel = false + override __.Parse binReader addr pos = + Parser.parse binReader &inParallel addr pos :> Instruction + + override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () + +module Basis = + let init (isa: ISA) = + let regexprs = RegExprs (isa.WordSize) + struct ( + TMS320C6000TranslationContext (isa, regexprs) :> TranslationContext, + TMS320C6000RegisterBay () :> RegisterBay + ) // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/TMS320C6000/TMS320C6000Disasm.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Disasm.fs similarity index 72% rename from src/FrontEnd/TMS320C6000/TMS320C6000Disasm.fs rename to src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Disasm.fs index c1b45932..e2c3ead7 100644 --- a/src/FrontEnd/TMS320C6000/TMS320C6000Disasm.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Disasm.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module B2R2.FrontEnd.TMS320C6000.Disasm +module B2R2.FrontEnd.BinLifter.TMS320C6000.Disasm open B2R2 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter let opCodeToString = function | Op.ABS -> "ABS" @@ -277,91 +277,89 @@ let inline appendUnit insInfo opcode = | D2XUnit -> opcode + ".D2X" | NoUnit -> opcode -let buildParallelPipe ins builder acc = - if ins.IsParallel then builder AsmWordKind.String "|| " acc - else acc +let buildParallelPipe ins (builder: DisasmBuilder<_>) = + if ins.IsParallel then builder.Accumulate AsmWordKind.String "|| " else () -let inline buildOpcode ins builder acc = +let inline buildOpcode ins (builder: DisasmBuilder<_>) = let str = opCodeToString ins.Opcode |> appendUnit ins - builder AsmWordKind.Mnemonic str acc + builder.Accumulate AsmWordKind.Mnemonic str -let buildMemBase builder baseR acc = function +let buildMemBase (builder: DisasmBuilder<_>) baseR = function | NegativeOffset -> - builder AsmWordKind.String "-" acc - |> builder AsmWordKind.Variable (Register.toString baseR) + builder.Accumulate AsmWordKind.String "-" + builder.Accumulate AsmWordKind.Variable (Register.toString baseR) | PositiveOffset -> - builder AsmWordKind.String "+" acc - |> builder AsmWordKind.Variable (Register.toString baseR) + builder.Accumulate AsmWordKind.String "+" + builder.Accumulate AsmWordKind.Variable (Register.toString baseR) | PreDecrement -> - builder AsmWordKind.String "--" acc - |> builder AsmWordKind.Variable (Register.toString baseR) + builder.Accumulate AsmWordKind.String "--" + builder.Accumulate AsmWordKind.Variable (Register.toString baseR) | PreIncrement -> - builder AsmWordKind.String "++" acc - |> builder AsmWordKind.Variable (Register.toString baseR) + builder.Accumulate AsmWordKind.String "++" + builder.Accumulate AsmWordKind.Variable (Register.toString baseR) | PostDecrement -> - builder AsmWordKind.Variable (Register.toString baseR) acc - |> builder AsmWordKind.String "--" + builder.Accumulate AsmWordKind.Variable (Register.toString baseR) + builder.Accumulate AsmWordKind.String "--" | PostIncrement -> - builder AsmWordKind.Variable (Register.toString baseR) acc - |> builder AsmWordKind.String "++" + builder.Accumulate AsmWordKind.Variable (Register.toString baseR) + builder.Accumulate AsmWordKind.String "++" -let private offsetToString builder offset acc = +let private offsetToString (builder: DisasmBuilder<_>) offset = match offset with - | UCst5 i -> builder AsmWordKind.Value (i.ToString()) acc - | UCst15 i -> builder AsmWordKind.Value (i.ToString()) acc - | OffsetR reg -> builder AsmWordKind.Variable (Register.toString reg) acc + | UCst5 i -> builder.Accumulate AsmWordKind.Value (i.ToString()) + | UCst15 i -> builder.Accumulate AsmWordKind.Value (i.ToString()) + | OffsetR r -> builder.Accumulate AsmWordKind.Variable (Register.toString r) -let private buildMemOffset builder offset acc = +let private buildMemOffset (builder: DisasmBuilder<_>) offset = match offset with - | UCst5 0UL -> acc + | UCst5 0UL -> () | offset -> - builder AsmWordKind.String "[" acc - |> offsetToString builder offset - |> builder AsmWordKind.String "]" + builder.Accumulate AsmWordKind.String "[" + offsetToString builder offset + builder.Accumulate AsmWordKind.String "]" -let memToString builder baseR modification offset acc = - buildMemBase builder baseR acc modification - |> buildMemOffset builder offset +let memToString builder baseR modification offset = + buildMemBase builder baseR modification + buildMemOffset builder offset -let oprToString insInfo opr delim builder acc = +let oprToString opr delim (builder: DisasmBuilder<_>) = match opr with | OpReg reg -> - builder AsmWordKind.String delim acc - |> builder AsmWordKind.Variable (Register.toString reg) + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.Variable (Register.toString reg) | RegisterPair (r1, r2) -> - builder AsmWordKind.String delim acc - |> builder AsmWordKind.Variable (Register.toString r1) - |> builder AsmWordKind.String ":" - |> builder AsmWordKind.Variable (Register.toString r2) + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.Variable (Register.toString r1) + builder.Accumulate AsmWordKind.String ":" + builder.Accumulate AsmWordKind.Variable (Register.toString r2) | OprMem (baseR, modification, offset) -> - builder AsmWordKind.String delim acc - |> builder AsmWordKind.String " *" - |> memToString builder baseR modification offset + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.String " *" + memToString builder baseR modification offset | Immediate imm -> - builder AsmWordKind.String delim acc - |> builder AsmWordKind.Value ("0x" + imm.ToString ("X")) + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.Value (String.u64ToHex imm) -let buildOprs insInfo builder acc = +let buildOprs insInfo builder = match insInfo.Operands with - | NoOperand -> acc + | NoOperand -> () | OneOperand opr -> - oprToString insInfo opr " " builder acc + oprToString opr " " builder | TwoOperands (opr1, opr2) -> - oprToString insInfo opr1 " " builder acc - |> oprToString insInfo opr2 ", " builder + oprToString opr1 " " builder + oprToString opr2 ", " builder | ThreeOperands (opr1, opr2, opr3) -> - oprToString insInfo opr1 " " builder acc - |> oprToString insInfo opr2 ", " builder - |> oprToString insInfo opr3 ", " builder + oprToString opr1 " " builder + oprToString opr2 ", " builder + oprToString opr3 ", " builder | FourOperands (opr1, opr2, opr3, opr4) -> - oprToString insInfo opr1 " " builder acc - |> oprToString insInfo opr2 ", " builder - |> oprToString insInfo opr3 ", " builder - |> oprToString insInfo opr4 ", " builder + oprToString opr1 " " builder + oprToString opr2 ", " builder + oprToString opr3 ", " builder + oprToString opr4 ", " builder -let disasm showAddr insInfo builder acc = - let pc = insInfo.Address - DisasmBuilder.addr pc WordSize.Bit32 showAddr builder acc - |> buildParallelPipe insInfo builder - |> buildOpcode insInfo builder - |> buildOprs insInfo builder +let disasm insInfo (builder: DisasmBuilder<_>) = + if builder.ShowAddr then builder.AccumulateAddr () else () + buildParallelPipe insInfo builder + buildOpcode insInfo builder + buildOprs insInfo builder diff --git a/src/FrontEnd/TMS320C6000/TMS320C6000Instruction.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Instruction.fs similarity index 66% rename from src/FrontEnd/TMS320C6000/TMS320C6000Instruction.fs rename to src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Instruction.fs index 25e432c7..1a2b4961 100644 --- a/src/FrontEnd/TMS320C6000/TMS320C6000Instruction.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Instruction.fs @@ -22,28 +22,25 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.TMS320C6000 +namespace B2R2.FrontEnd.BinLifter.TMS320C6000 open B2R2 -open B2R2.FrontEnd -open System.Text +open B2R2.FrontEnd.BinLifter /// The internal representation for a TMS320C6000 instruction used by our /// disassembler and lifter. -type TMS320C6000Instruction (addr, numBytes, insInfo, ctxt) = +type TMS320C6000Instruction (addr, numBytes, insInfo) = inherit Instruction (addr, numBytes, WordSize.Bit32) /// Basic instruction information. member val Info: InsInfo = insInfo - override __.NextParsingContext = ctxt - - override __.AuxParsingContext with get() = None - override __.IsBranch () = match __.Info.Opcode with | _ -> false + override __.IsModeChanging () = false + member __.HasConcJmpTarget () = Utils.futureFeature () override __.IsDirectBranch () = @@ -62,42 +59,48 @@ type TMS320C6000Instruction (addr, numBytes, insInfo, ctxt) = override __.IsInterrupt () = Utils.futureFeature () - override __.IsExit () = + override __.IsExit () = Utils.futureFeature () + + override __.IsBBLEnd () = __.IsDirectBranch () || __.IsIndirectBranch () - override __.DirectBranchTarget (addr: byref) = Utils.futureFeature () + override __.DirectBranchTarget (_addr: byref) = Utils.futureFeature () - override __.IndirectTrampolineAddr (addr: byref) = + override __.IndirectTrampolineAddr (_addr: byref) = Utils.futureFeature () + override __.Immediate (_v: byref) = Utils.futureFeature () + override __.GetNextInstrAddrs () = Utils.futureFeature () - override __.InterruptNum (num: byref) = Utils.futureFeature () + override __.InterruptNum (_num: byref) = Utils.futureFeature () override __.IsNop () = Utils.futureFeature () override __.Translate ctxt = Utils.futureFeature () - member private __.StrBuilder _ (str: string) (acc: StringBuilder) = - acc.Append (str) - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = - let acc = StringBuilder () - let acc = Disasm.disasm showAddr __.Info __.StrBuilder acc - acc.ToString () + let builder = + DisasmStringBuilder (showAddr, false, WordSize.Bit32, addr, numBytes) + Disasm.disasm __.Info builder + builder.Finalize () override __.Disasm () = - let acc = StringBuilder () - let acc = Disasm.disasm false __.Info __.StrBuilder acc - acc.ToString () + let builder = + DisasmStringBuilder (false, false, WordSize.Bit32, addr, numBytes) + Disasm.disasm __.Info builder + builder.Finalize () + + override __.Decompose (showAddr) = + let builder = + DisasmWordBuilder (showAddr, false, WordSize.Bit32, addr, numBytes, 8) + Disasm.disasm __.Info builder + builder.Finalize () - member private __.WordBuilder kind str (acc: AsmWordBuilder) = - acc.Append ({ AsmWordKind = kind; AsmWordValue = str }) + override __.IsInlinedAssembly () = false - override __.Decompose () = - AsmWordBuilder (8) - |> Disasm.disasm true __.Info __.WordBuilder - |> fun b -> b.Finish () + override __.Equals (_) = Utils.futureFeature () + override __.GetHashCode () = Utils.futureFeature () // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/TMS320C6000/TMS320C6000Parser.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Parser.fs similarity index 99% rename from src/FrontEnd/TMS320C6000/TMS320C6000Parser.fs rename to src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Parser.fs index 921f2502..c98b6292 100644 --- a/src/FrontEnd/TMS320C6000/TMS320C6000Parser.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Parser.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module B2R2.FrontEnd.TMS320C6000.Parser +module B2R2.FrontEnd.BinLifter.TMS320C6000.Parser open B2R2 -open B2R2.FrontEnd -open B2R2.FrontEnd.BitData +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.BitData /// Table 3-1. Instruction Operation and Execution Notations. type OperandType = @@ -1969,7 +1969,7 @@ let private parseInstruction bin = | 0b01u -> parseDUnitLoadStore bin | _ (* 0b11u *) -> parseDUnitLongImm bin -let parse (reader: BinReader) (ctxt: ParsingContext) addr pos = +let parse (reader: BinReader) (inParallel: byref) addr pos = let struct (bin, nextPos) = reader.ReadUInt32 pos let instrLen = nextPos - pos |> uint32 let struct (opcode, unit, operands) = parseInstruction bin @@ -1980,9 +1980,9 @@ let parse (reader: BinReader) (ctxt: ParsingContext) addr pos = Operands = operands FunctionalUnit = unit OperationSize = 32 // FIXME - IsParallel = ctxt.InParallel + IsParallel = inParallel EffectiveAddress = 0UL } - let ctxt' = ParsingContext.InitDSP (ctxt, pBit bin <> 0u) - TMS320C6000Instruction (addr, instrLen, insInfo, ctxt') + inParallel <- pBit bin <> 0u + TMS320C6000Instruction (addr, instrLen, insInfo) // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/TMS320C6000/TMS320C6000RegExprs.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegExprs.fs similarity index 92% rename from src/FrontEnd/TMS320C6000/TMS320C6000RegExprs.fs rename to src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegExprs.fs index 0cbe18f3..cdbe4931 100644 --- a/src/FrontEnd/TMS320C6000/TMS320C6000RegExprs.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegExprs.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.TMS320C6000 +namespace B2R2.FrontEnd.BinLifter.TMS320C6000 open B2R2 open B2R2.BinIR.LowUIR @@ -35,6 +35,6 @@ type internal RegExprs (wordSize) = member __.GetRegVar (name) = match name with - | _ -> raise B2R2.FrontEnd.UnhandledRegExprException + | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/TMS320C6000/TMS320C6000Register.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Register.fs similarity index 99% rename from src/FrontEnd/TMS320C6000/TMS320C6000Register.fs rename to src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Register.fs index 5c4871b3..c0ee6d45 100644 --- a/src/FrontEnd/TMS320C6000/TMS320C6000Register.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Register.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.TMS320C6000 +namespace B2R2.FrontEnd.BinLifter.TMS320C6000 open B2R2 diff --git a/src/FrontEnd/TMS320C6000/TMS320C6000RegisterBay.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterBay.fs similarity index 93% rename from src/FrontEnd/TMS320C6000/TMS320C6000RegisterBay.fs rename to src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterBay.fs index 259a998d..77ac8995 100644 --- a/src/FrontEnd/TMS320C6000/TMS320C6000RegisterBay.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterBay.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.TMS320C6000 +namespace B2R2.FrontEnd.BinLifter.TMS320C6000 open B2R2 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR type TMS320C6000RegisterBay () = @@ -39,11 +39,12 @@ type TMS320C6000RegisterBay () = override __.GetGeneralRegExprs () = Utils.futureFeature () override __.RegIDFromRegExpr (e) = - match e with + match e.E with | Var (_, id, _ ,_) -> id | PCVar (_, _) -> Register.toRegID Register.PCE1 | _ -> failwith "not a register expression" + override __.RegIDToRegExpr (id) = Utils.futureFeature () override __.StrToRegExpr _s = Utils.futureFeature () override __.RegIDFromString _s = Utils.futureFeature () override __.RegIDToString _ = Utils.futureFeature () diff --git a/src/FrontEnd/TMS320C6000/TMS320C6000RegisterSet.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterSet.fs similarity index 70% rename from src/FrontEnd/TMS320C6000/TMS320C6000RegisterSet.fs rename to src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterSet.fs index cbb5993d..5c51d00c 100644 --- a/src/FrontEnd/TMS320C6000/TMS320C6000RegisterSet.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterSet.fs @@ -22,31 +22,38 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.TMS320C6000 +namespace B2R2.FrontEnd.BinLifter.TMS320C6000 open B2R2 +module private RegisterSetLiteral = + let [] arrLen = 2 + +open RegisterSetLiteral + type TMS320C6000RegisterSet (bitArray: uint64 [], s: Set) = inherit NonEmptyRegisterSet (bitArray, s) - static let defaultSize = 2 - static let emptyArr = Array.init defaultSize (fun _ -> 0UL) - static member EmptySet = - new TMS320C6000RegisterSet (emptyArr, Set.empty) :> RegisterSet + new () = + TMS320C6000RegisterSet (RegisterSet.MakeInternalBitArray arrLen, Set.empty) override __.Tag = RegisterSetTag.TMS320C6000 - override __.ArrSize = defaultSize - override __.New x s = new TMS320C6000RegisterSet (x, s) :> RegisterSet - override __.Empty = TMS320C6000RegisterSet.EmptySet - override __.EmptyArr = emptyArr - override __.Project x = - match Register.ofRegID x with - | _ -> -1 + + override __.ArrSize = arrLen + + override __.New arr s = new TMS320C6000RegisterSet (arr, s) :> RegisterSet + + override __.RegIDToIndex rid = + match Register.ofRegID rid with + | _ -> Utils.futureFeature () + + override __.IndexToRegID _index: RegisterID = + Utils.futureFeature () override __.ToString () = sprintf "TMS320C6000RegisterSet<%x, %x>" __.BitArray.[0] __.BitArray.[1] [] module TMS320C6000RegisterSet = - let singleton = RegisterSetBuilder.singletonBuilder TMS320C6000RegisterSet.EmptySet - let empty = TMS320C6000RegisterSet.EmptySet + let singleton rid = TMS320C6000RegisterSet().Add(rid) + let empty = TMS320C6000RegisterSet () :> RegisterSet diff --git a/src/FrontEnd/TMS320C6000/TMS320C6000Types.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Types.fs similarity index 98% rename from src/FrontEnd/TMS320C6000/TMS320C6000Types.fs rename to src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Types.fs index 380e6b57..9d9c5d15 100644 --- a/src/FrontEnd/TMS320C6000/TMS320C6000Types.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Types.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.TMS320C6000 +namespace B2R2.FrontEnd.BinLifter.TMS320C6000 open B2R2 open System.Runtime.CompilerServices -[] +[] do () /// diff --git a/src/FrontEnd/TMS320C6000/TMS320C6000Utils.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Utils.fs similarity index 95% rename from src/FrontEnd/TMS320C6000/TMS320C6000Utils.fs rename to src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Utils.fs index 6f9807c8..b7ff37bc 100644 --- a/src/FrontEnd/TMS320C6000/TMS320C6000Utils.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Utils.fs @@ -22,6 +22,6 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.TMS320C6000.Utils +module internal B2R2.FrontEnd.BinLifter.TMS320C6000.Utils // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/Core/B2R2.FrontEnd.Core.fsproj b/src/FrontEnd/Core/B2R2.FrontEnd.Core.fsproj deleted file mode 100644 index 4007ed81..00000000 --- a/src/FrontEnd/Core/B2R2.FrontEnd.Core.fsproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - netstandard2.1 - false - false - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/FrontEnd/Core/DisasmUtils.fs b/src/FrontEnd/Core/DisasmUtils.fs deleted file mode 100644 index b633fd8a..00000000 --- a/src/FrontEnd/Core/DisasmUtils.fs +++ /dev/null @@ -1,34 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd - -open B2R2 - -module DisasmBuilder = - let inline addr (addr: Addr) wordSize showAddress builder acc = - if not showAddress then acc - else - builder AsmWordKind.Address (Addr.toString wordSize addr) acc - |> builder AsmWordKind.String (": ") diff --git a/src/FrontEnd/EVM/B2R2.FrontEnd.EVM.fsproj b/src/FrontEnd/EVM/B2R2.FrontEnd.EVM.fsproj deleted file mode 100644 index 632d8d39..00000000 --- a/src/FrontEnd/EVM/B2R2.FrontEnd.EVM.fsproj +++ /dev/null @@ -1,29 +0,0 @@ - - - - netstandard2.1 - false - false - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/FrontEnd/EVM/EVMDisasm.fs b/src/FrontEnd/EVM/EVMDisasm.fs deleted file mode 100644 index 3f9877f1..00000000 --- a/src/FrontEnd/EVM/EVMDisasm.fs +++ /dev/null @@ -1,198 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.EVM.Disasm - -open B2R2 -open B2R2.FrontEnd - -let opcodeToStrings = function - | Op.STOP -> struct ("stop", None) - | Op.ADD -> struct("add", None) - | Op.MUL -> struct("mul", None) - | Op.SUB -> struct("sub", None) - | Op.DIV -> struct("div", None) - | Op.SDIV -> struct("sdiv", None) - | Op.MOD -> struct("mod", None) - | Op.SMOD -> struct("smod", None) - | Op.ADDMOD -> struct("addmod", None) - | Op.MULMOD -> struct("mulmod", None) - | Op.EXP -> struct("exp", None) - | Op.SIGNEXTEND -> struct("signextend", None) - | Op.LT -> struct("lt", None) - | Op.GT -> struct("gt", None) - | Op.SLT -> struct("slt", None) - | Op.SGT -> struct("sgt", None) - | Op.EQ -> struct("eq", None) - | Op.ISZERO -> struct("iszero", None) - | Op.AND -> struct("and", None) - | Op.OR -> struct("or", None) - | Op.XOR -> struct("xor", None) - | Op.NOT -> struct("not", None) - | Op.BYTE -> struct("byte", None) - | Op.SHL -> struct("shl", None) - | Op.SHR -> struct("shr", None) - | Op.SAR -> struct("sar", None) - | Op.SHA3 -> struct("sha3", None) - | Op.ADDRESS -> struct("address", None) - | Op.BALANCE -> struct("balance", None) - | Op.ORIGIN -> struct("origin", None) - | Op.CALLER -> struct("caller", None) - | Op.CALLVALUE -> struct("callvalue", None) - | Op.CALLDATALOAD -> struct("calldataload", None) - | Op.CALLDATASIZE -> struct("calldatasize", None) - | Op.CALLDATACOPY -> struct("calldatacopy", None) - | Op.CODESIZE -> struct("codesize", None) - | Op.CODECOPY -> struct("codecopy", None) - | Op.GASPRICE -> struct("gasprice", None) - | Op.EXTCODESIZE -> struct("extcodesize", None) - | Op.EXTCODECOPY -> struct("extcodecopy", None) - | Op.RETURNDATASIZE -> struct("returndatasize", None) - | Op.RETURNDATACOPY -> struct("returndatacopy", None) - | Op.BLOCKHASH -> struct("blockhash", None) - | Op.COINBASE -> struct("coinbase", None) - | Op.TIMESTAMP -> struct("timestamp", None) - | Op.NUMBER -> struct("number", None) - | Op.DIFFICULTY -> struct("difficulty", None) - | Op.GASLIMIT -> struct("gaslimit", None) - | Op.POP -> struct("pop", None) - | Op.MLOAD -> struct("mload", None) - | Op.MSTORE -> struct("mstore", None) - | Op.MSTORE8 -> struct("mstore8", None) - | Op.SLOAD -> struct("sload", None) - | Op.SSTORE -> struct("sstore", None) - | Op.JUMP -> struct("jump", None) - | Op.JUMPI -> struct("jumpi", None) - | Op.GETPC -> struct("getpc", None) - | Op.MSIZE -> struct("msize", None) - | Op.GAS -> struct("gas", None) - | Op.JUMPDEST -> struct("jumpdest", None) - | Op.PUSH1 imm -> struct("push1", BitVector.valToString imm |> Some) - | Op.PUSH2 imm -> struct("push2", BitVector.valToString imm |> Some) - | Op.PUSH3 imm -> struct("push3", BitVector.valToString imm |> Some) - | Op.PUSH4 imm -> struct("push4", BitVector.valToString imm |> Some) - | Op.PUSH5 imm -> struct("push5", BitVector.valToString imm |> Some) - | Op.PUSH6 imm -> struct("push6", BitVector.valToString imm |> Some) - | Op.PUSH7 imm -> struct("push7", BitVector.valToString imm |> Some) - | Op.PUSH8 imm -> struct("push8", BitVector.valToString imm |> Some) - | Op.PUSH9 imm -> struct("push9", BitVector.valToString imm |> Some) - | Op.PUSH10 imm -> struct("push10", BitVector.valToString imm |> Some) - | Op.PUSH11 imm -> struct("push11", BitVector.valToString imm |> Some) - | Op.PUSH12 imm -> struct("push12", BitVector.valToString imm |> Some) - | Op.PUSH13 imm -> struct("push13", BitVector.valToString imm |> Some) - | Op.PUSH14 imm -> struct("push14", BitVector.valToString imm |> Some) - | Op.PUSH15 imm -> struct("push15", BitVector.valToString imm |> Some) - | Op.PUSH16 imm -> struct("push16", BitVector.valToString imm |> Some) - | Op.PUSH17 imm -> struct("push17", BitVector.valToString imm |> Some) - | Op.PUSH18 imm -> struct("push18", BitVector.valToString imm |> Some) - | Op.PUSH19 imm -> struct("push19", BitVector.valToString imm |> Some) - | Op.PUSH20 imm -> struct("push20", BitVector.valToString imm |> Some) - | Op.PUSH21 imm -> struct("push21", BitVector.valToString imm |> Some) - | Op.PUSH22 imm -> struct("push22", BitVector.valToString imm |> Some) - | Op.PUSH23 imm -> struct("push23", BitVector.valToString imm |> Some) - | Op.PUSH24 imm -> struct("push24", BitVector.valToString imm |> Some) - | Op.PUSH25 imm -> struct("push25", BitVector.valToString imm |> Some) - | Op.PUSH26 imm -> struct("push26", BitVector.valToString imm |> Some) - | Op.PUSH27 imm -> struct("push27", BitVector.valToString imm |> Some) - | Op.PUSH28 imm -> struct("push28", BitVector.valToString imm |> Some) - | Op.PUSH29 imm -> struct("push29", BitVector.valToString imm |> Some) - | Op.PUSH30 imm -> struct("push30", BitVector.valToString imm |> Some) - | Op.PUSH31 imm -> struct("push31", BitVector.valToString imm |> Some) - | Op.PUSH32 imm -> struct("push32", BitVector.valToString imm |> Some) - | Op.DUP1 -> struct("dup1", None) - | Op.DUP2 -> struct("dup2", None) - | Op.DUP3 -> struct("dup3", None) - | Op.DUP4 -> struct("dup4", None) - | Op.DUP5 -> struct("dup5", None) - | Op.DUP6 -> struct("dup6", None) - | Op.DUP7 -> struct("dup7", None) - | Op.DUP8 -> struct("dup8", None) - | Op.DUP9 -> struct("dup9", None) - | Op.DUP10 -> struct("dup10", None) - | Op.DUP11 -> struct("dup11", None) - | Op.DUP12 -> struct("dup12", None) - | Op.DUP13 -> struct("dup13", None) - | Op.DUP14 -> struct("dup14", None) - | Op.DUP15 -> struct("dup15", None) - | Op.DUP16 -> struct("dup16", None) - | Op.SWAP1 -> struct("swap1", None) - | Op.SWAP2 -> struct("swap2", None) - | Op.SWAP3 -> struct("swap3", None) - | Op.SWAP4 -> struct("swap4", None) - | Op.SWAP5 -> struct("swap5", None) - | Op.SWAP6 -> struct("swap6", None) - | Op.SWAP7 -> struct("swap7", None) - | Op.SWAP8 -> struct("swap8", None) - | Op.SWAP9 -> struct("swap9", None) - | Op.SWAP10 -> struct("swap10", None) - | Op.SWAP11 -> struct("swap11", None) - | Op.SWAP12 -> struct("swap12", None) - | Op.SWAP13 -> struct("swap13", None) - | Op.SWAP14 -> struct("swap14", None) - | Op.SWAP15 -> struct("swap15", None) - | Op.SWAP16 -> struct("swap16", None) - | Op.LOG0 -> struct("log0", None) - | Op.LOG1 -> struct("log1", None) - | Op.LOG2 -> struct("log2", None) - | Op.LOG3 -> struct("log3", None) - | Op.LOG4 -> struct("log4", None) - | Op.JUMPTO -> struct("jumpto", None) - | Op.JUMPIF -> struct("jumpif", None) - | Op.JUMPSUB -> struct("jumpsub", None) - | Op.JUMPSUBV -> struct("jumpsubv", None) - | Op.BEGINSUB -> struct("beginsub", None) - | Op.BEGINDATA -> struct("begindata", None) - | Op.RETURNSUB -> struct("returnsub", None) - | Op.PUTLOCAL -> struct("putlocal", None) - | Op.GETLOCAL -> struct("getlocal", None) - | Op.SLOADBYTES -> struct("sloadbytes", None) - | Op.SSTOREBYTES -> struct("sstorebytes", None) - | Op.SSIZE -> struct("ssize", None) - | Op.CREATE -> struct("create", None) - | Op.CALL -> struct("call", None) - | Op.CALLCODE -> struct("callcode", None) - | Op.RETURN -> struct("return", None) - | Op.DELEGATECALL -> struct("delegatecall", None) - | Op.CREATE2 -> struct("create2", None) - | Op.STATICCALL -> struct("staticcall", None) - | Op.TXEXECGAS -> struct("txexecgas", None) - | Op.REVERT -> struct("revert", None) - | Op.INVALID -> struct("invalid", None) - | Op.SELFDESTRUCT -> struct("selfdestruct", None) - -let inline buildOpcode insInfo builder acc = - let struct (opcode, extra) = opcodeToStrings insInfo.Opcode - match extra with - | None -> builder AsmWordKind.Mnemonic opcode acc - | Some extra -> - builder AsmWordKind.Mnemonic opcode acc - |> builder AsmWordKind.String " " - |> builder AsmWordKind.Value extra - -let disasm showAddr insInfo builder acc = - let pc = insInfo.Address - DisasmBuilder.addr pc WordSize.Bit32 showAddr builder acc - |> buildOpcode insInfo builder - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/EVM/EVMParser.fsi b/src/FrontEnd/EVM/EVMParser.fsi deleted file mode 100644 index a9fd6e48..00000000 --- a/src/FrontEnd/EVM/EVMParser.fsi +++ /dev/null @@ -1,40 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -/// EVM instruction parser. -module B2R2.FrontEnd.EVM.Parser - -open B2R2 -open B2R2.FrontEnd - -/// Read in bytes and return a parsed instruction for EVM. This function -/// returns EVMInstruction, which is a specialized type for EVM. If you want -/// to handle instructions in a platform-agnostic manner, you'd better use the -/// EVM class. -val parse: BinReader - -> ParsingContext - -> WordSize - -> Addr - -> int - -> EVMInstruction diff --git a/src/FrontEnd/Intel/B2R2.FrontEnd.Intel.fsproj b/src/FrontEnd/Intel/B2R2.FrontEnd.Intel.fsproj deleted file mode 100644 index 80a6c414..00000000 --- a/src/FrontEnd/Intel/B2R2.FrontEnd.Intel.fsproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - netstandard2.1 - false - false - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/FrontEnd/Intel/IntelConstants.fs b/src/FrontEnd/Intel/IntelConstants.fs deleted file mode 100644 index cfbc2527..00000000 --- a/src/FrontEnd/Intel/IntelConstants.fs +++ /dev/null @@ -1,1095 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.Intel.Constants - -type R = Register - -let _Ap = ODModeSize (struct (OprMode.A, OprSize.P)) -let _BNDRbnd = ODModeSize (struct (OprMode.BndR, OprSize.Bnd)) -let _BNDRMbnd = ODModeSize (struct (OprMode.BndM, OprSize.Bnd)) -let _By = ODModeSize (struct (OprMode.B, OprSize.Y)) -let _Cd = ODModeSize (struct (OprMode.C, OprSize.D)) -let _Dd = ODModeSize (struct (OprMode.D, OprSize.D)) -let _E0v = ODModeSize (struct (OprMode.E0, OprSize.V)) (* \x0f\x1f *) -let _Eb = ODModeSize (struct (OprMode.E, OprSize.B)) -let _Ed = ODModeSize (struct (OprMode.E, OprSize.D)) -let _Edb = ODModeSize (struct (OprMode.E, OprSize.DB)) -let _Edw = ODModeSize (struct (OprMode.E, OprSize.DW)) -let _Ep = ODModeSize (struct (OprMode.E, OprSize.P)) -let _Ev = ODModeSize (struct (OprMode.E, OprSize.V)) -let _Ew = ODModeSize (struct (OprMode.E, OprSize.W)) -let _Ey = ODModeSize (struct (OprMode.E, OprSize.Y)) -let _Gb = ODModeSize (struct (OprMode.G, OprSize.B)) -let _Gd = ODModeSize (struct (OprMode.G, OprSize.D)) -let _Gv = ODModeSize (struct (OprMode.G, OprSize.V)) -let _Gw = ODModeSize (struct (OprMode.G, OprSize.W)) -let _Gy = ODModeSize (struct (OprMode.G, OprSize.Y)) -let _Gz = ODModeSize (struct (OprMode.G, OprSize.Z)) -let _Hdq = ODModeSize (struct (OprMode.H, OprSize.DQ)) -let _Hpd = ODModeSize (struct (OprMode.H, OprSize.PD)) -let _Hps = ODModeSize (struct (OprMode.H, OprSize.PS)) -let _Hqq = ODModeSize (struct (OprMode.H, OprSize.QQ)) -let _Hsd = ODModeSize (struct (OprMode.H, OprSize.SD)) -let _Hss = ODModeSize (struct (OprMode.H, OprSize.SS)) -let _Hx = ODModeSize (struct (OprMode.H, OprSize.X)) -let _Ib = ODModeSize (struct (OprMode.I, OprSize.B)) -let _Iv = ODModeSize (struct (OprMode.I, OprSize.V)) -let _Iw = ODModeSize (struct (OprMode.I, OprSize.W)) -let _Iz = ODModeSize (struct (OprMode.I, OprSize.Z)) -let _Jb = ODModeSize (struct (OprMode.J, OprSize.B)) -let _Jz = ODModeSize (struct (OprMode.J, OprSize.Z)) -let _Ma = ODModeSize (struct (OprMode.M, OprSize.A)) -let _Md = ODModeSize (struct (OprMode.M, OprSize.D)) -let _Mdq = ODModeSize (struct (OprMode.M, OprSize.DQ)) -let _Mdqd = ODModeSize (struct (OprMode.M, OprSize.DQD)) -let _Mp = ODModeSize (struct (OprMode.M, OprSize.P)) -let _Mpd = ODModeSize (struct (OprMode.M, OprSize.PD)) -let _Mps = ODModeSize (struct (OprMode.M, OprSize.PS)) -let _Mq = ODModeSize (struct (OprMode.M, OprSize.Q)) -let _Ms = ODModeSize (struct (OprMode.M, OprSize.S)) -let _Mv = ODModeSize (struct (OprMode.M, OprSize.V)) -let _Mw = ODModeSize (struct (OprMode.M, OprSize.W)) -let _Mx = ODModeSize (struct (OprMode.M, OprSize.X)) -let _My = ODModeSize (struct (OprMode.M, OprSize.Y)) -let _Mz = ODModeSize (struct (OprMode.M, OprSize.Z)) -let _MZxz = ODModeSize (struct (OprMode.MZ, OprSize.XZ)) -let _Nq = ODModeSize (struct (OprMode.N, OprSize.Q)) -let _Ob = ODModeSize (struct (OprMode.O, OprSize.B)) -let _Ov = ODModeSize (struct (OprMode.O, OprSize.V)) -let _Pd = ODModeSize (struct (OprMode.P, OprSize.D)) -let _Ppi = ODModeSize (struct (OprMode.P, OprSize.PI)) -let _Pq = ODModeSize (struct (OprMode.P, OprSize.Q)) -let _Qd = ODModeSize (struct (OprMode.Q, OprSize.D)) -let _Qpi = ODModeSize (struct (OprMode.Q, OprSize.PI)) -let _Qq = ODModeSize (struct (OprMode.Q, OprSize.Q)) -let _Rd = ODModeSize (struct (OprMode.R, OprSize.D)) -let _Rv = ODModeSize (struct (OprMode.R, OprSize.V)) -let _Ry = ODModeSize (struct (OprMode.R, OprSize.Y)) -let _SIb = ODModeSize (struct (OprMode.SI, OprSize.B)) -let _SIv = ODModeSize (struct (OprMode.SI, OprSize.V)) -let _SIw = ODModeSize (struct (OprMode.SI, OprSize.W)) -let _SIz = ODModeSize (struct (OprMode.SI, OprSize.Z)) -let _Sw = ODModeSize (struct (OprMode.S, OprSize.W)) -let _Udq = ODModeSize (struct (OprMode.U, OprSize.DQ)) -let _Upd = ODModeSize (struct (OprMode.U, OprSize.PD)) -let _Ups = ODModeSize (struct (OprMode.U, OprSize.PS)) -let _Uq = ODModeSize (struct (OprMode.U, OprSize.Q)) -let _Ux = ODModeSize (struct (OprMode.U, OprSize.X)) -let _Vdq = ODModeSize (struct (OprMode.V, OprSize.DQ)) -let _Vpd = ODModeSize (struct (OprMode.V, OprSize.PD)) -let _Vps = ODModeSize (struct (OprMode.V, OprSize.PS)) -let _Vq = ODModeSize (struct (OprMode.V, OprSize.Q)) -let _Vqq = ODModeSize (struct (OprMode.V, OprSize.QQ)) -let _Vsd = ODModeSize (struct (OprMode.V, OprSize.SD)) -let _Vss = ODModeSize (struct (OprMode.V, OprSize.SS)) -let _Vx = ODModeSize (struct (OprMode.V, OprSize.X)) -let _Vy = ODModeSize (struct (OprMode.V, OprSize.Y)) -let _VZxz = ODModeSize (struct (OprMode.VZ, OprSize.XZ)) -let _Wd = ODModeSize (struct (OprMode.W, OprSize.D)) -let _Wdq = ODModeSize (struct (OprMode.W, OprSize.DQ)) -let _Wdqd = ODModeSize (struct (OprMode.W, OprSize.DQD)) -let _Wdqdq = ODModeSize (struct (OprMode.W, OprSize.DQDQ)) -let _Wdqq = ODModeSize (struct (OprMode.W, OprSize.DQQ)) -let _Wdqqdq = ODModeSize (struct (OprMode.W, OprSize.DQQDQ)) -let _Wdqw = ODModeSize (struct (OprMode.W, OprSize.DQW)) -let _Wdqwd = ODModeSize (struct (OprMode.W, OprSize.DQWD)) -let _Wpd = ODModeSize (struct (OprMode.W, OprSize.PD)) -let _Wps = ODModeSize (struct (OprMode.W, OprSize.PS)) -let _Wpsq = ODModeSize (struct (OprMode.W, OprSize.PSQ)) -let _Wsd = ODModeSize (struct (OprMode.W, OprSize.SD)) -let _Wsdq = ODModeSize (struct (OprMode.W, OprSize.SDQ)) -let _Wss = ODModeSize (struct (OprMode.W, OprSize.SS)) -let _Wssd = ODModeSize (struct (OprMode.W, OprSize.SSD)) -let _Wssq = ODModeSize (struct (OprMode.W, OprSize.SSQ)) -let _Wx = ODModeSize (struct (OprMode.W, OprSize.X)) -let _WZxz = ODModeSize (struct (OprMode.WZ, OprSize.XZ)) -let _Xb = ODModeSize (struct (OprMode.X, OprSize.B)) -let _Xv = ODModeSize (struct (OprMode.X, OprSize.V)) -let _Yb = ODModeSize (struct (OprMode.Y, OprSize.B)) -let _Yv = ODModeSize (struct (OprMode.Y, OprSize.V)) - -let Ap = [| _Ap |] -let Dd = [| _Dd |] -let E0v = [| _E0v |] -let Eb = [| _Eb |] -let Ep = [| _Ep |] -let Ev = [| _Ev |] -let Ew = [| _Ew |] -let Ey = [| _Ey |] -let Gb = [| _Gb |] -let Gd = [| _Gd |] -let Gv = [| _Gv |] -let Gw = [| _Gw |] -let Gy = [| _Gy |] -let Gz = [| _Gz |] -let Ib = [| _Ib |] -let Iv = [| _Iv |] -let Iw = [| _Iw |] -let Iz = [| _Iz |] -let Jb = [| _Jb |] -let Jz = [| _Jz |] -let Ma = [| _Ma |] -let Mdq = [| _Mdq |] -let Mp = [| _Mp |] -let Mq = [| _Mq |] -let Ms = [| _Ms |] -let Mv = [| _Mv |] -let Mw = [| _Mw |] -let My = [| _My |] -let Mz = [| _Mz |] -let Pd = [| _Pd |] -let Pq = [| _Pq |] -let Qq = [| _Qq |] -let Rd = [| _Rd |] -let Rv = [| _Rv |] -let Ry = [| _Ry |] -let SIb = [| _SIb |] -let SIv = [| _SIv |] -let SIw = [| _SIw |] -let SIz = [| _SIz |] -let Sw = [| _Sw |] -let Vdq = [| _Vdq |] -let Vx = [| _Vx |] -let Wdq = [| _Wdq |] -let Wdqd = [| _Wdqd |] -let Wdqq = [| _Wdqq |] -let Wx = [| _Wx |] - -let ORSR sg = [| ODReg sg |] - -let ALDX = [| ODReg R.AL; ODReg R.DX |] -let ALIb = [| ODReg R.AL; _Ib |] -let ALOb = [| ODReg R.AL; _Ob |] -let BNDRbndBNDRMbnd = [| _BNDRbnd; _BNDRMbnd |] -let BNDRMbndBNDRbnd = [| _BNDRMbnd; _BNDRbnd |] -let CdRd = [| _Cd; _Rd |] -let DdRd = [| _Dd; _Rd |] -let DXAL = [| ODReg R.DX; ODReg R.AL |] -let Eb1L = [| _Eb; ODImmOne |] -let EbCL = [| _Eb; ODReg R.CL |] -let EbGb = [| _Eb; _Gb |] -let EbIb = [| _Eb; _Ib |] -let Ev1L = [| _Ev; ODImmOne |] -let EvCL = [| _Ev; ODReg R.CL |] -let EvGv = [| _Ev; _Gv |] -let EvIb = [| _Ev; _Ib |] -let EvIz = [| _Ev; _Iz |] -let EvSIb = [| _Ev; _SIb |] -let EvSIz = [| _Ev; _SIz |] -let EvSw = [| _Ev; _Sw |] -let EwGw = [| _Ew; _Gw |] -let EyPd = [| _Ey; _Pd |] -let EyPq = [| _Ey; _Pq |] -let EyVdq = [| _Ey; _Vdq |] -let GbEb = [| _Gb; _Eb |] -let GdEb = [| _Gd; _Eb |] -let GdEw = [| _Gd; _Ew |] -let GdEy = [| _Gd; _Ey |] -let GdNq = [| _Gd; _Nq |] -let GdUdq = [| _Gd; _Udq |] -let GdUx = [| _Gd; _Ux |] -let GvEb = [| _Gv; _Eb |] -let GvEd = [| _Gv; _Ed |] -let GvEv = [| _Gv; _Ev |] -let GvEw = [| _Gv; _Ew |] -let GvEy = [| _Gv; _Ey |] -let GvMa = [| _Gv; _Ma |] -let GvMp = [| _Gv; _Mp |] -let GvMv = [| _Gv; _Mv |] -let GwMw = [| _Gw; _Mw |] -let GyMy = [| _Gy; _My |] -let GyUdq = [| _Gy; _Udq |] -let GyUpd = [| _Gy; _Upd |] -let GyUps = [| _Gy; _Ups |] -let GyUx = [| _Gy; _Ux |] -let GyWdq = [| _Gy; _Wdq |] -let GyWsd = [| _Gy; _Wsd |] -let GyWsdq = [| _Gy; _Wsdq |] -let GyWss = [| _Gy; _Wss |] -let GyWssd = [| _Gy; _Wssd |] -let GzMp = [| _Gz; _Mp |] -let IbAL = [| _Ib; ODReg R.AL |] -let IwIb = [| _Iw; _Ib |] -let MdqVdq = [| _Mdq; _Vdq |] -let MpdVpd = [| _Mpd; _Vpd |] -let MpsVps = [| _Mps; _Vps |] -let MqPq = [| _Mq; _Pq |] -let MqVdq = [| _Mq; _Vdq |] -let MwGw = [| _Gw; _Mw |] -let MxVx = [| _Mx; _Vx |] -let MyGy = [| _My; _Gy |] -let MZxzVZxz = [| _MZxz; _VZxz |] -let NqIb = [| _Nq; _Ib |] -let ObAL = [| _Ob; ODReg R.AL |] -let PdEy = [| _Pd; _Ey |] -let PpiWdq = [| _Ppi; _Wdq |] -let PpiWdqq = [| _Ppi; _Wdqq |] -let PpiWpd = [| _Ppi; _Wpd |] -let PpiWps = [| _Ppi; _Wps |] -let PpiWpsq = [| _Ppi; _Wpsq |] -let PqEy = [| _Pq; _Ey |] -let PqQd = [| _Pq; _Qd |] -let PqQq = [| _Pq; _Qq |] -let PqUdq = [| _Pq; _Udq |] -let PqWdq = [| _Pq; _Wdq |] -let QpiWpd = [| _Qpi; _Wpd |] -let QqPq = [| _Qq; _Pq |] -let RdCd = [| _Rd; _Cd |] -let RdDd = [| _Rd; _Dd |] -let SwEw = [| _Sw; _Ew |] -let UdqIb = [| _Udq; _Ib |] -let VdqEy = [| _Vdq; _Ey |] -let VdqMdq = [| _Vdq; _Mdq |] -let VdqMq = [| _Vdq; _Mq |] -let VdqNq = [| _Vdq; _Nq |] -let VdqQq = [| _Vdq; _Qq |] -let VdqUdq = [| _Vdq; _Udq |] -let VdqWdq = [| _Vdq; _Wdq |] -let VdqWdqd = [| _Vdq; _Wdqd |] -let VdqWdqq = [| _Vdq; _Wdqq |] -let VdqWdqw = [| _Vdq; _Wdqw |] -let VpdWpd = [| _Vpd; _Wpd |] -let VpsWps = [| _Vps; _Wps |] -let VqqMdq = [| _Vqq; _Mdq |] -let VsdWsd = [| _Vsd; _Wsd |] -let VsdWsdq = [| _Vsd; _Wsdq |] -let VssWss = [| _Vss; _Wss |] -let VssWssd = [| _Vss; _Wssd |] -let VxMd = [| _Vx; _Md |] -let VxMx = [| _Vx; _Mx |] -let VxWdqdq = [| _Vx; _Wdqdq |] -let VxWdqqdq = [| _Vx; _Wdqqdq |] -let VxWdqwd = [| _Vx; _Wdqwd |] -let VxWss = [| _Vx; _Wss |] -let VxWssd = [| _Vx; _Wssd |] -let VxWssq = [| _Vx; _Wssq |] -let VxWx = [| _Vx; _Wx |] -let VyEy = [| _Vy; _Ey |] -let VZxzWdqd = [| _VZxz; _Wdqd |] -let VZxzWZxz = [| _VZxz; _WZxz |] -let WdqdVdq = [| _Wdqd; _Vdq |] -let WdqqVdq = [| _Wdqq; _Vdq |] -let WdqVdq = [| _Wdq; _Vdq |] -let WpdVpd = [| _Wpd; _Vpd |] -let WpsVps = [| _Wps; _Vps |] -let WssdVx = [| _Wssd; _Vx |] -let WssqVx = [| _Wssq; _Vx |] -let WssVx = [| _Wss; _Vx |] -let WxVx = [| _Wx; _Vx |] -let WZxzVZxz = [| _WZxz; _VZxz |] -let XbYb = [| _Xb; _Yb |] -let XvYv = [| _Xv; _Yv |] -let YbXb = [| _Yb; _Xb |] -let YvXv = [| _Yv; _Xv |] - -let inline RegIb r = [| ODReg r; _Ib |] - -let inline private _RGz rg changeable = - ODRegGrp (rg, OprSize.Z, if changeable then RGrpAttr.ARegInOpREX - else RGrpAttr.ARegInOpNoREX) -let inline private _RGv rg changeable = - ODRegGrp (rg, OprSize.V, if changeable then RGrpAttr.ARegInOpREX - else RGrpAttr.ARegInOpNoREX) - -let inline RGv rg = [| _RGv rg true |] -let inline RGz rg rexChangeable = [| _RGz rg rexChangeable |] -let inline RGvOv rg rc = [| _RGv rg rc; _Ov |] -let inline OvRGv rg rc = [| _Ov; _RGv rg rc |] -let RGzRGz = [| _RGz RegGrp.RG0 false; _RGz RegGrp.RG0 true |] -let inline RGvRGv rg2 = [| _RGv RegGrp.RG0 false; _RGv rg2 true |] -let inline RGvIb rg rc = [| _RGv rg rc; _Ib |] -let inline IbRGv rg rc = [| _Ib; _RGv rg rc |] -let RGvSIz = [| _RGv RegGrp.RG0 false; _SIz |] -let inline RGvIv rg = [| _RGv rg true; _Iv |] -let RGvDX = [| _RGv RegGrp.RG0 false; ODReg R.DX |] -let DXRGv = [| ODReg R.DX; _RGv RegGrp.RG0 false |] -let RGzDX = [| _RGz RegGrp.RG0 false; ODReg R.DX |] -let DXRGz = [| ODReg R.DX; _RGz RegGrp.RG0 false |] - -let EdwVdqIb = [| _Edw; _Vdq; _Ib |] -let EvGvCL = [| _Ev; _Gv; ODReg R.CL |] -let EvGvIb = [| _Ev; _Gv; _Ib |] -let GdNqIb = [| _Gd; _Nq; _Ib |] -let GdUdqIb = [| _Gd; _Udq; _Ib |] -let GvEvIb = [| _Gv; _Ev; _Ib |] -let GvEvIz = [| _Gv; _Ev; _Iz |] -let GvEvSIb = [| _Gv; _Ev; _SIb |] -let GvEvSIz = [| _Gv; _Ev; _SIz |] -let GyByEy = [| _Gy; _By; _Ey |] -let GyEyBy = [| _Gy; _Ey; _By |] -let GyEyIb = [| _Gy; _Ey; _Ib |] -let HxUxIb = [| _Hx; _Ux; _Ib |] -let PqEdwIb = [| _Pq; _Edw; _Ib |] -let PqQqIb = [| _Pq; _Qq; _Ib |] -let VdqEdbIb = [| _Vdq; _Edb; _Ib |] -let VdqEdwIb = [| _Vdq; _Edw; _Ib |] -let VdqHdqMdq = [| _Vdq; _Hdq; _Mdq |] -let VdqHdqMdqd = [| _Vdq; _Hdq; _Mdqd |] -let VdqHdqMq = [| _Vdq; _Hdq; _Mq |] -let VdqHdqUdq = [| _Vdq; _Hdq; _Udq |] -let VdqWdqIb = [| _Vdq; _Wdq; _Ib |] -let VpdHpdWpd = [| _Vpd; _Hpd; _Wpd |] -let VpsHpsWps = [| _Vps; _Hps; _Wps |] -let VsdHsdEy = [| _Vsd; _Hsd; _Ey |] -let VsdHsdWsd = [| _Vsd; _Hsd; _Wsd |] -let VsdHsdWsdq = [| _Vsd; _Hsd; _Wsdq |] -let VsdWsdIb = [| _Vsd; _Wsd; _Ib |] -let VsdWsdqIb = [| _Vsd; _Wsdq; _Ib |] -let VssHssEy = [| _Vss; _Hss; _Ey |] -let VssHssWsdq = [| _Vsd; _Hsd; _Wsdq |] -let VssHssWss = [| _Vss; _Hss; _Wss |] -let VssHssWssd = [| _Vss; _Hss; _Wssd |] -let VssWssdIb = [| _Vss; _Wssd; _Ib |] -let VxHxWdq = [| _Vx; _Hx; _Wdq |] -let VxHxWdqd = [| _Vx; _Hx; _Wdqd |] -let VxHxWdqq = [| _Vx; _Hx; _Wdqq |] -let VxHxWsd = [| _Vx; _Hx; _Wsd |] -let VxHxWss = [| _Vx; _Hx; _Wss |] -let VxHxWx = [| _Vx; _Hx; _Wx |] -let VxWxIb = [| _Vx; _Wx; _Ib |] -let WsdHxVsd = [| _Wsd; _Hx; _Vsd |] -let WssHxVss = [| _Wss; _Hx; _Vss |] - -let VdqHdqEdbIb = [| _Vdq; _Hdq; _Edb; _Ib |] -let VdqHdqEdwIb = [| _Vdq; _Hdq; _Edw; _Ib |] -let VpsHpsWpsIb = [| _Vps; _Hps; _Wps; _Ib |] -let VqqHqqWdqIb = [| _Vqq; _Hqq; _Wdq; _Ib |] -let VxHxWxIb = [| _Vx; _Hx; _Wx; _Ib |] - -let opNor0F1A = [| Opcode.InvalOP; Opcode.BNDMOV; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F1B = [| Opcode.InvalOP; Opcode.BNDMOV; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F10 = [| Opcode.MOVUPS; Opcode.MOVUPD; - Opcode.MOVSS; Opcode.MOVSD |] -let opVex0F10Mem = [| Opcode.VMOVUPS; Opcode.VMOVUPD; - Opcode.VMOVSS; Opcode.VMOVSD |] -let opVex0F10Reg = [| Opcode.VMOVUPS; Opcode.VMOVUPD; - Opcode.VMOVSS; Opcode.VMOVSD |] -let opNor0F11 = [| Opcode.MOVUPS; Opcode.MOVUPD; - Opcode.MOVSS; Opcode.MOVSD |] -let opVex0F11Mem = [| Opcode.VMOVUPS; Opcode.VMOVUPD; - Opcode.VMOVSS; Opcode.VMOVSD |] -let opVex0F11Reg = [| Opcode.VMOVUPS; Opcode.VMOVUPD; - Opcode.VMOVSS; Opcode.VMOVSD |] -let opNor0F12Mem = [| Opcode.MOVLPS; Opcode.MOVLPD; - Opcode.MOVSLDUP; Opcode.MOVDDUP |] -let opNor0F12Reg = [| Opcode.MOVHLPS; Opcode.MOVLPD; - Opcode.MOVSLDUP; Opcode.MOVDDUP |] -let opVex0F12Mem = [| Opcode.VMOVLPS; Opcode.VMOVLPD; - Opcode.VMOVSLDUP; Opcode.VMOVDDUP |] -let opVex0F12Reg = [| Opcode.VMOVHLPS; Opcode.VMOVLPD; - Opcode.VMOVSLDUP; Opcode.VMOVDDUP |] -let opNor0F13 = [| Opcode.MOVLPS; Opcode.MOVLPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F13 = [| Opcode.VMOVLPS; Opcode.VMOVLPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F14 = [| Opcode.UNPCKLPS; Opcode.UNPCKLPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F14 = [| Opcode.VUNPCKLPS; Opcode.VUNPCKLPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F15 = [| Opcode.UNPCKHPS; Opcode.UNPCKHPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F15 = [| Opcode.VUNPCKHPS; Opcode.VUNPCKHPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F16Mem = [| Opcode.MOVHPS; Opcode.MOVHPD; - Opcode.MOVSHDUP; Opcode.InvalOP |] -let opNor0F16Reg = [| Opcode.MOVLHPS; Opcode.MOVHPD; - Opcode.MOVSHDUP; Opcode.InvalOP |] -let opVex0F16Mem = [| Opcode.VMOVHPS; Opcode.VMOVHPD; - Opcode.VMOVSHDUP; Opcode.InvalOP |] -let opVex0F16Reg = [| Opcode.VMOVLHPS; Opcode.VMOVHPD; - Opcode.VMOVSHDUP; Opcode.InvalOP |] -let opNor0F17 = [| Opcode.MOVHPS; Opcode.MOVHPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F17 = [| Opcode.VMOVHPS; Opcode.VMOVHPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F28 = [| Opcode.MOVAPS; Opcode.MOVAPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F28 = [| Opcode.VMOVAPS; Opcode.VMOVAPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F29 = [| Opcode.MOVAPS; Opcode.MOVAPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F29 = [| Opcode.VMOVAPS; Opcode.VMOVAPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F2A = [| Opcode.CVTPI2PS; Opcode.CVTPI2PD; - Opcode.CVTSI2SS; Opcode.CVTSI2SD |] -let opVex0F2A = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.VCVTSI2SS; Opcode.VCVTSI2SD |] -let opNor0F2B = [| Opcode.MOVNTPS; Opcode.MOVNTPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F2B = [| Opcode.VMOVNTPS; Opcode.VMOVNTPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F2C = [| Opcode.CVTTPS2PI; Opcode.CVTTPD2PI; - Opcode.CVTTSS2SI; Opcode.CVTTSD2SI |] -let opVex0F2C = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.VCVTTSS2SI; Opcode.VCVTTSD2SI |] -let opNor0F2D = [| Opcode.CVTPS2PI; Opcode.CVTPD2PI; - Opcode.CVTSS2SI; Opcode.CVTSD2SI |] -let opVex0F2D = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.VCVTSS2SI; Opcode.VCVTSD2SI |] -let opNor0F2E = [| Opcode.UCOMISS; Opcode.UCOMISD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F2E = [| Opcode.VUCOMISS; Opcode.VUCOMISD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F2F = [| Opcode.COMISS; Opcode.COMISD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F2F = [| Opcode.VCOMISS; Opcode.VCOMISD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F50 = [| Opcode.MOVMSKPS; Opcode.MOVMSKPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F50 = [| Opcode.VMOVMSKPS; Opcode.VMOVMSKPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F51 = [| Opcode.SQRTPS; Opcode.SQRTPD; - Opcode.SQRTSS; Opcode.SQRTSD |] -let opVex0F51 = [| Opcode.VSQRTPS; Opcode.VSQRTPD; - Opcode.VSQRTSS; Opcode.VSQRTSD |] -let opNor0F54 = [| Opcode.ANDPS; Opcode.ANDPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F54 = [| Opcode.VANDPS; Opcode.VANDPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F55 = [| Opcode.ANDNPS; Opcode.ANDNPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F55 = [| Opcode.VANDNPS; Opcode.VANDNPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F56 = [| Opcode.ORPS; Opcode.ORPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F56 = [| Opcode.VORPS; Opcode.VORPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F57 = [| Opcode.XORPS; Opcode.XORPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F57 = [| Opcode.VXORPS; Opcode.VXORPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F58 = [| Opcode.ADDPS; Opcode.ADDPD; - Opcode.ADDSS; Opcode.ADDSD |] -let opVex0F58 = [| Opcode.VADDPS; Opcode.VADDPD; - Opcode.VADDSS; Opcode.VADDSD |] -let opNor0F59 = [| Opcode.MULPS; Opcode.MULPD; - Opcode.MULSS; Opcode.MULSD |] -let opVex0F59 = [| Opcode.VMULPS; Opcode.VMULPD; - Opcode.VMULSS; Opcode.VMULSD |] -let opNor0F5A = [| Opcode.CVTPS2PD; Opcode.CVTPD2PS; - Opcode.CVTSS2SD; Opcode.CVTSD2SS |] -let opVex0F5A = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.VCVTSS2SD; Opcode.VCVTSD2SS |] -let opNor0F5B = [| Opcode.CVTDQ2PS; Opcode.CVTPS2DQ; - Opcode.CVTTPS2DQ; Opcode.InvalOP |] -let opVex0F5B = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F5C = [| Opcode.SUBPS; Opcode.SUBPD; - Opcode.SUBSS; Opcode.SUBSD |] -let opVex0F5C = [| Opcode.VSUBPS; Opcode.VSUBPD; - Opcode.VSUBSS; Opcode.VSUBSD |] -let opNor0F5D = [| Opcode.MINPS; Opcode.MINPD; - Opcode.MINSS; Opcode.MINSD |] -let opVex0F5D = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F5E = [| Opcode.DIVPS; Opcode.DIVPD; - Opcode.DIVSS; Opcode.DIVSD |] -let opVex0F5E = [| Opcode.VDIVPS; Opcode.VDIVPD; - Opcode.VDIVSS; Opcode.VDIVSD |] -let opNor0F5F = [| Opcode.MAXPS; Opcode.MAXPD; - Opcode.MAXSS; Opcode.MAXSD |] -let opVex0F5F = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F60 = [| Opcode.PUNPCKLBW; Opcode.PUNPCKLBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F60 = [| Opcode.InvalOP; Opcode.VPUNPCKLBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F61 = [| Opcode.PUNPCKLWD; Opcode.PUNPCKLWD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F61 = [| Opcode.InvalOP; Opcode.VPUNPCKLWD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F62 = [| Opcode.PUNPCKLDQ; Opcode.PUNPCKLDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F62 = [| Opcode.InvalOP; Opcode.VPUNPCKLDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F63 = [| Opcode.PACKSSWB; Opcode.PACKSSWB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F63 = [| Opcode.InvalOP; Opcode.VPACKSSWB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F64 = [| Opcode.PCMPGTB; Opcode.PCMPGTB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F64 = [| Opcode.InvalOP; Opcode.VPCMPGTB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F65 = [| Opcode.PCMPGTW; Opcode.PCMPGTW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F65 = [| Opcode.InvalOP; Opcode.VPCMPGTW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F66 = [| Opcode.PCMPGTD; Opcode.PCMPGTD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F66 = [| Opcode.InvalOP; Opcode.VPCMPGTD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F67 = [| Opcode.PACKUSWB; Opcode.PACKUSWB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F67 = [| Opcode.InvalOP; Opcode.VPACKUSWB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F68 = [| Opcode.PUNPCKHBW; Opcode.PUNPCKHBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F68 = [| Opcode.InvalOP; Opcode.VPUNPCKHBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F69 = [| Opcode.PUNPCKHWD; Opcode.PUNPCKHWD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F69 = [| Opcode.InvalOP; Opcode.VPUNPCKHWD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F6A = [| Opcode.PUNPCKHDQ; Opcode.PUNPCKHDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F6A = [| Opcode.InvalOP; Opcode.VPUNPCKHDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F6B = [| Opcode.PACKSSDW; Opcode.PACKSSDW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F6B = [| Opcode.InvalOP; Opcode.VPACKSSDW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F6C = [| Opcode.InvalOP; Opcode.PUNPCKLQDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F6C = [| Opcode.InvalOP; Opcode.VPUNPCKLQDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F6D = [| Opcode.InvalOP; Opcode.PUNPCKHQDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F6D = [| Opcode.InvalOP; Opcode.VPUNPCKHQDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F6EB64 = [| Opcode.MOVQ; Opcode.MOVQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F6EB32 = [| Opcode.MOVD; Opcode.MOVD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F6EB64 = [| Opcode.InvalOP; Opcode.VMOVQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F6EB32 = [| Opcode.InvalOP; Opcode.VMOVD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F6F = [| Opcode.MOVQ; Opcode.MOVDQA; - Opcode.MOVDQU; Opcode.InvalOP |] -let opVex0F6F = [| Opcode.InvalOP; Opcode.VMOVDQA; - Opcode.VMOVDQU; Opcode.InvalOP |] -let opEVex0F6FB64 = [| Opcode.InvalOP; Opcode.VMOVDQA64; - Opcode.VMOVDQU64; Opcode.InvalOP |] -let opEVex0F6FB32 = [| Opcode.InvalOP; Opcode.VMOVDQA32; - Opcode.VMOVDQU32; Opcode.InvalOP |] -let opNor0F70 = [| Opcode.PSHUFW; Opcode.PSHUFD; - Opcode.PSHUFHW; Opcode.PSHUFLW |] -let opVex0F70 = [| Opcode.InvalOP; Opcode.VPSHUFD; - Opcode.VPSHUFHW; Opcode.VPSHUFLW |] -let opNor0F74 = [| Opcode.PCMPEQB; Opcode.PCMPEQB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F74 = [| Opcode.InvalOP; Opcode.VPCMPEQB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F75 = [| Opcode.PCMPEQW; Opcode.PCMPEQW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F75 = [| Opcode.InvalOP; Opcode.VPCMPEQW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F76 = [| Opcode.PCMPEQD; Opcode.PCMPEQD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F76 = [| Opcode.InvalOP; Opcode.VPCMPEQD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F77 = [| Opcode.EMMS; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F77 = [| Opcode.VZEROUPPER; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F7EB64 = [| Opcode.MOVQ; Opcode.MOVQ; - Opcode.MOVQ; Opcode.InvalOP |] -let opNor0F7EB32 = [| Opcode.MOVD; Opcode.MOVD; - Opcode.MOVQ; Opcode.InvalOP |] -let opVex0F7EB64 = [| Opcode.InvalOP; Opcode.VMOVQ; - Opcode.VMOVQ; Opcode.InvalOP |] -let opVex0F7EB32 = [| Opcode.InvalOP; Opcode.VMOVD; - Opcode.VMOVQ; Opcode.InvalOP |] -let opNor0F7F = [| Opcode.MOVQ; Opcode.MOVDQA; - Opcode.MOVDQU; Opcode.InvalOP |] -let opVex0F7F = [| Opcode.InvalOP; Opcode.VMOVDQA; - Opcode.VMOVDQU; Opcode.InvalOP |] -let opEVex0F7FB64 = [| Opcode.InvalOP; Opcode.VMOVDQA64; - Opcode.InvalOP; Opcode.InvalOP |] -let opEVex0F7FB32 = [| Opcode.InvalOP; Opcode.VMOVDQA32; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FC2 = [| Opcode.CMPPS; Opcode.CMPPD; - Opcode.CMPSS; Opcode.CMPSD |] -let opVex0FC2 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FC4 = [| Opcode.PINSRW; Opcode.PINSRW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FC4 = [| Opcode.InvalOP; Opcode.VPINSRW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FC5 = [| Opcode.PEXTRW; Opcode.PEXTRW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FC5 = [| Opcode.InvalOP; Opcode.VPEXTRW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FC6 = [| Opcode.SHUFPS; Opcode.SHUFPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FC6 = [| Opcode.VSHUFPS; Opcode.VSHUFPD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FD1 = [| Opcode.PSRLW; Opcode.PSRLW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FD1 = [| Opcode.InvalOP; Opcode.VPSRLW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FD2 = [| Opcode.PSRLD; Opcode.PSRLD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FD2 = [| Opcode.InvalOP; Opcode.VPSRLD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FD3 = [| Opcode.PSRLQ; Opcode.PSRLQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FD3 = [| Opcode.InvalOP; Opcode.VPSRLQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FD4 = [| Opcode.PADDQ; Opcode.PADDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FD4 = [| Opcode.InvalOP; Opcode.VPADDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FD5 = [| Opcode.PMULLW; Opcode.PMULLW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FD5 = [| Opcode.InvalOP; Opcode.VPMULLW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FD6 = [| Opcode.InvalOP; Opcode.MOVQ; - Opcode.MOVQ2DQ; Opcode.MOVDQ2Q |] -let opVex0FD6 = [| Opcode.InvalOP; Opcode.VMOVQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FD7 = [| Opcode.PMOVMSKB; Opcode.PMOVMSKB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FD7 = [| Opcode.InvalOP; Opcode.VPMOVMSKB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FD8 = [| Opcode.PSUBUSB; Opcode.PSUBUSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FD8 = [| Opcode.InvalOP; Opcode.VPSUBUSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FD9 = [| Opcode.PSUBUSW; Opcode.PSUBUSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FD9 = [| Opcode.InvalOP; Opcode.VPSUBUSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FDA = [| Opcode.PMINUB; Opcode.PMINUB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FDA = [| Opcode.InvalOP; Opcode.VPMINUB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FDB = [| Opcode.PAND; Opcode.PAND; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FDB = [| Opcode.InvalOP; Opcode.VPAND; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FDC = [| Opcode.PADDUSB; Opcode.PADDUSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FDC = [| Opcode.InvalOP; Opcode.VPADDUSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FDD = [| Opcode.PADDUSW; Opcode.PADDUSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FDD = [| Opcode.InvalOP; Opcode.VPADDUSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FDE = [| Opcode.PMAXUB; Opcode.PMAXUB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FDE = [| Opcode.InvalOP; Opcode.VPMAXUB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FDF = [| Opcode.PANDN; Opcode.PANDN; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FDF = [| Opcode.InvalOP; Opcode.VPANDN; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FE0 = [| Opcode.PAVGB; Opcode.PAVGB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FE0 = [| Opcode.InvalOP; Opcode.VPAVGB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FE1 = [| Opcode.PSRAW; Opcode.PSRAW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FE1 = [| Opcode.InvalOP; Opcode.VPSRAW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FE2 = [| Opcode.PSRAD; Opcode.PSRAD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FE2 = [| Opcode.InvalOP; Opcode.VPSRAD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FE3 = [| Opcode.PAVGW; Opcode.PAVGW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FE3 = [| Opcode.InvalOP; Opcode.VPAVGW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FE4 = [| Opcode.PMULHUW; Opcode.PMULHUW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FE4 = [| Opcode.InvalOP; Opcode.VPMULHUW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FE5 = [| Opcode.PMULHW; Opcode.PMULHW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FE5 = [| Opcode.InvalOP; Opcode.VPMULHW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FE6 = [| Opcode.InvalOP; Opcode.CVTTPD2DQ; - Opcode.CVTDQ2PD; Opcode.CVTPD2DQ |] -let opVex0FE6 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FE7 = [| Opcode.MOVNTQ; Opcode.MOVNTDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FE7 = [| Opcode.InvalOP; Opcode.VMOVNTDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opEVex0FE7B64 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opEVex0FE7B32 = [| Opcode.InvalOP; Opcode.VMOVNTDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FE8 = [| Opcode.PSUBSB; Opcode.PSUBSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FE8 = [| Opcode.InvalOP; Opcode.VPSUBSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FE9 = [| Opcode.PSUBSW; Opcode.PSUBSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FE9 = [| Opcode.InvalOP; Opcode.VPSUBSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FEA = [| Opcode.PMINSW; Opcode.PMINSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FEA = [| Opcode.InvalOP; Opcode.VPMINSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FEB = [| Opcode.POR; Opcode.POR; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FEB = [| Opcode.InvalOP; Opcode.VPOR; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FEC = [| Opcode.PADDSB; Opcode.PADDSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FEC = [| Opcode.InvalOP; Opcode.VPADDSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FED = [| Opcode.PADDSW; Opcode.PADDSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FED = [| Opcode.InvalOP; Opcode.VPADDSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FEE = [| Opcode.PMAXSW; Opcode.PMAXSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FEE = [| Opcode.InvalOP; Opcode.VPMAXSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FEF = [| Opcode.PXOR; Opcode.PXOR; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FEF = [| Opcode.InvalOP; Opcode.VPXOR; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FF0 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.LDDQU |] -let opVex0FF0 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.VLDDQU |] -let opNor0FF1 = [| Opcode.PSLLW; Opcode.PSLLW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FF1 = [| Opcode.InvalOP; Opcode.VPSLLW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FF2 = [| Opcode.PSLLD; Opcode.PSLLD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FF2 = [| Opcode.InvalOP; Opcode.VPSLLD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FF3 = [| Opcode.PSLLQ; Opcode.PSLLQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FF3 = [| Opcode.InvalOP; Opcode.VPSLLQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FF4 = [| Opcode.PMULUDQ; Opcode.PMULUDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FF4 = [| Opcode.InvalOP; Opcode.VPMULUDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FF5 = [| Opcode.PMADDWD; Opcode.PMADDWD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FF5 = [| Opcode.InvalOP; Opcode.VPMADDWD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FF6 = [| Opcode.PSADBW; Opcode.PSADBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FF6 = [| Opcode.InvalOP; Opcode.VPSADBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FF8 = [| Opcode.PSUBB; Opcode.PSUBB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FF8 = [| Opcode.InvalOP; Opcode.VPSUBB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FF9 = [| Opcode.PSUBW; Opcode.PSUBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FF9 = [| Opcode.InvalOP; Opcode.VPSUBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FFA = [| Opcode.PSUBD; Opcode.PSUBD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FFA = [| Opcode.InvalOP; Opcode.VPSUBD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FFB = [| Opcode.PSUBQ; Opcode.PSUBQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FFB = [| Opcode.InvalOP; Opcode.VPSUBQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FFC = [| Opcode.PADDB; Opcode.PADDB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FFC = [| Opcode.InvalOP; Opcode.VPADDB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FFD = [| Opcode.PADDW; Opcode.PADDW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FFD = [| Opcode.InvalOP; Opcode.VPADDW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0FFE = [| Opcode.PADDD; Opcode.PADDD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0FFE = [| Opcode.InvalOP; Opcode.VPADDD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3800 = [| Opcode.PSHUFB; Opcode.PSHUFB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3800 = [| Opcode.InvalOP; Opcode.VPSHUFB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3801 = [| Opcode.PHADDW; Opcode.PHADDW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3801 = [| Opcode.InvalOP; Opcode.VPHADDW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3802 = [| Opcode.PHADDD; Opcode.PHADDD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3802 = [| Opcode.InvalOP; Opcode.VPHADDD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3803 = [| Opcode.PHADDSW; Opcode.PHADDSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3803 = [| Opcode.InvalOP; Opcode.VPHADDSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3805 = [| Opcode.PHSUBW; Opcode.PHSUBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3805 = [| Opcode.InvalOP; Opcode.VPHSUBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3806 = [| Opcode.PHSUBD; Opcode.PHSUBD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3806 = [| Opcode.InvalOP; Opcode.VPHSUBD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3807 = [| Opcode.PHSUBSW; Opcode.PHSUBSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3807 = [| Opcode.InvalOP; Opcode.VPHSUBSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3808 = [| Opcode.PSIGNB; Opcode.PSIGNB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3808 = [| Opcode.InvalOP; Opcode.VPSIGNB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3809 = [| Opcode.PSIGNW; Opcode.PSIGNW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3809 = [| Opcode.InvalOP; Opcode.VPSIGNW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F380A = [| Opcode.PSIGND; Opcode.PSIGND; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F380A = [| Opcode.InvalOP; Opcode.VPSIGND; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F380B = [| Opcode.PMULHRSW; Opcode.PMULHRSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F380B = [| Opcode.InvalOP; Opcode.VPMULHRSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3817 = [| Opcode.InvalOP; Opcode.PTEST; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3817 = [| Opcode.InvalOP; Opcode.VPTEST; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3818 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3818 = [| Opcode.InvalOP; Opcode.VBROADCASTSS; - Opcode.InvalOP; Opcode.InvalOP |] -let opEVex0F3818 = [| Opcode.InvalOP; Opcode.VBROADCASTSS; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F381C = [| Opcode.PABSB; Opcode.PABSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F381C = [| Opcode.InvalOP; Opcode.VPABSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F381D = [| Opcode.PABSW; Opcode.PABSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F381D = [| Opcode.InvalOP; Opcode.VPABSW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F381E = [| Opcode.PABSD; Opcode.PABSD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F381E = [| Opcode.InvalOP; Opcode.VPABSD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3820 = [| Opcode.InvalOP; Opcode.PMOVSXBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3820 = [| Opcode.InvalOP; Opcode.VPMOVSXBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3821 = [| Opcode.InvalOP; Opcode.PMOVSXBD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3821 = [| Opcode.InvalOP; Opcode.VPMOVSXBD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3822 = [| Opcode.InvalOP; Opcode.PMOVSXBQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3822 = [| Opcode.InvalOP; Opcode.VPMOVSXBQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3823 = [| Opcode.InvalOP; Opcode.PMOVSXWD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3823 = [| Opcode.InvalOP; Opcode.VPMOVSXWD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3824 = [| Opcode.InvalOP; Opcode.PMOVSXWQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3824 = [| Opcode.InvalOP; Opcode.VPMOVSXWQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3825 = [| Opcode.InvalOP; Opcode.PMOVSXDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3825 = [| Opcode.InvalOP; Opcode.VPMOVSXDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3828 = [| Opcode.InvalOP; Opcode.PMULDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3828 = [| Opcode.InvalOP; Opcode.VPMULDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3829 = [| Opcode.InvalOP; Opcode.PCMPEQQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3829 = [| Opcode.InvalOP; Opcode.VPCMPEQQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F382B = [| Opcode.InvalOP; Opcode.PACKUSDW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F382B = [| Opcode.InvalOP; Opcode.VPACKUSDW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3830 = [| Opcode.InvalOP; Opcode.PMOVZXBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3830 = [| Opcode.InvalOP; Opcode.VPMOVZXBW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3831 = [| Opcode.InvalOP; Opcode.PMOVZXBD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3831 = [| Opcode.InvalOP; Opcode.VPMOVZXBD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3832 = [| Opcode.InvalOP; Opcode.PMOVZXBQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3832 = [| Opcode.InvalOP; Opcode.VPMOVZXBQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3833 = [| Opcode.InvalOP; Opcode.PMOVZXWD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3833 = [| Opcode.InvalOP; Opcode.VPMOVZXWD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3834 = [| Opcode.InvalOP; Opcode.PMOVZXWQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3834 = [| Opcode.InvalOP; Opcode.VPMOVZXWQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3835 = [| Opcode.InvalOP; Opcode.PMOVZXDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3835 = [| Opcode.InvalOP; Opcode.VPMOVZXDQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3837 = [| Opcode.InvalOP; Opcode.PCMPGTQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3837 = [| Opcode.InvalOP; Opcode.VPCMPGTQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3838 = [| Opcode.InvalOP; Opcode.PMINSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3838 = [| Opcode.InvalOP; Opcode.VPMINSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3839 = [| Opcode.InvalOP; Opcode.PMINSD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3839 = [| Opcode.InvalOP; Opcode.VPMINSD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F383A = [| Opcode.InvalOP; Opcode.PMINUW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F383A = [| Opcode.InvalOP; Opcode.VPMINUW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F383B = [| Opcode.InvalOP; Opcode.PMINUD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F383B = [| Opcode.InvalOP; Opcode.VPMINUD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F383C = [| Opcode.InvalOP; Opcode.PMAXSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F383C = [| Opcode.InvalOP; Opcode.VPMAXSB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F383D = [| Opcode.InvalOP; Opcode.PMAXSD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F383D = [| Opcode.InvalOP; Opcode.VPMAXSD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F383E = [| Opcode.InvalOP; Opcode.PMAXUW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F383E = [| Opcode.InvalOP; Opcode.VPMAXUW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F383F = [| Opcode.InvalOP; Opcode.PMAXUD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F383F = [| Opcode.InvalOP; Opcode.VPMAXUD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3840 = [| Opcode.InvalOP; Opcode.PMULLD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3840 = [| Opcode.InvalOP; Opcode.VPMULLD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3841 = [| Opcode.InvalOP; Opcode.PHMINPOSUW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3841 = [| Opcode.InvalOP; Opcode.VPHMINPOSUW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F385A = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F385A = [| Opcode.InvalOP; Opcode.VBROADCASTI128; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3878 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3878 = [| Opcode.InvalOP; Opcode.VPBROADCASTB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3899W0 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3899W1 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3899W0 = [| Opcode.InvalOP; Opcode.VFMADD132SS; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3899W1 = [| Opcode.InvalOP; Opcode.VFMADD132SD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F38A9W0 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F38A9W1 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F38A9W0 = [| Opcode.InvalOP; Opcode.VFMADD213SS; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F38A9W1 = [| Opcode.InvalOP; Opcode.VFMADD213SD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F38B9W0 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F38B9W1 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F38B9W0 = [| Opcode.InvalOP; Opcode.VFMADD231SS; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F38B9W1 = [| Opcode.InvalOP; Opcode.VFMADD231SD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F38F0 = [| Opcode.MOVBE; Opcode.MOVBE; - Opcode.InvalOP; Opcode.CRC32; Opcode.CRC32 |] -let opNor0F38F1 = [| Opcode.MOVBE; Opcode.MOVBE; - Opcode.InvalOP; Opcode.CRC32; Opcode.CRC32 |] -let opNor0F38F5W0 = [| Opcode.InvalOP; Opcode.WRUSSD; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F38F5W1 = [| Opcode.InvalOP; Opcode.WRUSSQ; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F38F5W0 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F38F5W1 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F38F6W0 = [| Opcode.WRSSD; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F38F6W1 = [| Opcode.WRSSQ; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F38F6W0 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.MULX |] -let opVex0F38F6W1 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.MULX |] -let opNor0F38F7 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F38F7 = [| Opcode.InvalOP; Opcode.SHLX; - Opcode.SARX; Opcode.SHRX |] -let opNor0F3A0F = [| Opcode.PALIGNR; Opcode.PALIGNR; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3A0F = [| Opcode.InvalOP; Opcode.VPALIGNR; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3A15 = [| Opcode.InvalOP; Opcode.PEXTRW; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3A15 = [| Opcode.InvalOP; Opcode.VPEXTRW; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3A20 = [| Opcode.InvalOP; Opcode.PINSRB; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3A20 = [| Opcode.InvalOP; Opcode.VPINSRB; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3A38 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3A38 = [| Opcode.InvalOP; Opcode.VINSERTI128; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3A60 = [| Opcode.InvalOP; Opcode.PCMPESTRM; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3A60 = [| Opcode.InvalOP; Opcode.VPCMPESTRM; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3A61 = [| Opcode.InvalOP; Opcode.PCMPESTRI; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3A61 = [| Opcode.InvalOP; Opcode.VPCMPESTRI; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3A62 = [| Opcode.InvalOP; Opcode.PCMPISTRM; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3A62 = [| Opcode.InvalOP; Opcode.VPCMPISTRM; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3A63 = [| Opcode.InvalOP; Opcode.PCMPISTRI; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3A63 = [| Opcode.InvalOP; Opcode.VPCMPISTRI; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3A0B = [| Opcode.InvalOP; Opcode.ROUNDSD; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3A0B = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opNor0F3AF0 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] -let opVex0F3AF0 = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.RORX |] -let opEmpty = [| Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.InvalOP |] - - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/Intel/IntelHelper.fs b/src/FrontEnd/Intel/IntelHelper.fs deleted file mode 100644 index d3d2222d..00000000 --- a/src/FrontEnd/Intel/IntelHelper.fs +++ /dev/null @@ -1,112 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.Intel.Helper - -open B2R2 -open B2R2.FrontEnd -open System.Runtime.CompilerServices - -[] -do () - -/// Create a new instruction descriptor. -let newTemporaryIns opcode operands preInfo insSize = - { - Prefixes = preInfo.TPrefixes - REXPrefix = preInfo.TREXPrefix - VEXInfo = preInfo.TVEXInfo - Opcode = opcode - Operands = operands - InsSize = insSize - } - -let segRegToBase = function - | R.CS -> R.CSBase - | R.DS -> R.DSBase - | R.ES -> R.ESBase - | R.FS -> R.FSBase - | R.GS -> R.GSBase - | R.SS -> R.SSBase - | _ -> failwith "Unhandled segment." - -let inline hasREXW rexPref = rexPref &&& REXPrefix.REXW = REXPrefix.REXW -let inline hasREXR rexPref = rexPref &&& REXPrefix.REXR = REXPrefix.REXR -let inline hasAddrSz prefs = (prefs &&& Prefix.PrxADDRSIZE) <> Prefix.PrxNone -let inline hasOprSz prefs = (prefs &&& Prefix.PrxOPSIZE) <> Prefix.PrxNone -let inline hasREPZ prefs = (prefs &&& Prefix.PrxREPZ) <> Prefix.PrxNone -let inline hasREPNZ prefs = (prefs &&& Prefix.PrxREPNZ) <> Prefix.PrxNone -let inline hasLock prefs = (prefs &&& Prefix.PrxLOCK) <> Prefix.PrxNone - -let inline ensure32 t = - if WordSize.is64 t.TWordSize then raise ParsingFailureException else () - -let inline ensure64 t = - if WordSize.is32 t.TWordSize then raise ParsingFailureException else () - -/// Filter out segment-related prefixes. -let clearSegMask : Prefix = LanguagePrimitives.EnumOfValue 0xFC0F - -/// Filter out PrxREPNZ, PrxREPZ, and PrxOPSIZE. -let clearVEXPrefMask : Prefix = LanguagePrimitives.EnumOfValue 0xFBF9 - -/// Filter out group 1 prefixes. -let clearGrp1PrefMask : Prefix = LanguagePrimitives.EnumOfValue 0xFFF0 - -let getSegment pref = - if (pref &&& Prefix.PrxCS) <> Prefix.PrxNone then Some R.CS - elif (pref &&& Prefix.PrxDS) <> Prefix.PrxNone then Some R.DS - elif (pref &&& Prefix.PrxES) <> Prefix.PrxNone then Some R.ES - elif (pref &&& Prefix.PrxFS) <> Prefix.PrxNone then Some R.FS - elif (pref &&& Prefix.PrxGS) <> Prefix.PrxNone then Some R.GS - elif (pref &&& Prefix.PrxSS) <> Prefix.PrxNone then Some R.SS - else None - -let isBranch = function - | Opcode.CALLFar | Opcode.CALLNear - | Opcode.JMPFar | Opcode.JMPNear - | Opcode.RETFar | Opcode.RETFarImm | Opcode.RETNear | Opcode.RETNearImm - | Opcode.JA | Opcode.JB | Opcode.JBE | Opcode.JCXZ | Opcode.JECXZ - | Opcode.JG | Opcode.JL | Opcode.JLE | Opcode.JNB | Opcode.JNL | Opcode.JNO - | Opcode.JNP | Opcode.JNS | Opcode.JNZ | Opcode.JO | Opcode.JP - | Opcode.JRCXZ | Opcode.JS | Opcode.JZ | Opcode.LOOP | Opcode.LOOPE - | Opcode.LOOPNE -> true - | _ -> false - -let isCETInstr = function - | Opcode.INCSSPD | Opcode.INCSSPQ | Opcode.RDSSPD | Opcode.RDSSPQ - | Opcode.SAVEPREVSSP | Opcode.RSTORSSP | Opcode.WRSSD | Opcode.WRSSQ - | Opcode.WRUSSD | Opcode.WRUSSQ | Opcode.SETSSBSY | Opcode.CLRSSBSY -> true - | _ -> false - -/// Create a temporary instruction information. -let newTemporaryInfo prefs rexPref vInfo wordSize = - { - TPrefixes = prefs - TREXPrefix = rexPref - TVEXInfo = vInfo - TWordSize = wordSize - } - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/Intel/IntelLifter.fs b/src/FrontEnd/Intel/IntelLifter.fs deleted file mode 100644 index 12fbfc5e..00000000 --- a/src/FrontEnd/Intel/IntelLifter.fs +++ /dev/null @@ -1,7827 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.Intel.Lifter - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.LowUIR -open B2R2.BinIR.LowUIR.AST -open B2R2.FrontEnd -open B2R2.FrontEnd.Intel -open B2R2.FrontEnd.Intel.RegGroup -open B2R2.FrontEnd.Intel.Helper - -type PackType = - | PackMask - | PackSelect - -/// XXX (cleanup required) -/// imm8 control byte operation for PCMPESTRI, PCMPESTRM, etc.. -/// See Chapter 4.1 of the manual vol. 2B. -type Imm8ControlByte = { - PackSize : RegType - NumElems : uint32 - Sign : Sign - Agg : Agg - Polarity : Polarity - OutSelect : OutSelect - Len : Length - Ret : Return -} -and Sign = - | Signed - | UnSigned -and Agg = - | EqualAny - | Ranges - | EqualEach - | EqualOrdered -and Polarity = - | PosPolarity - | NegPolarity - | PosMasked - | NegMasked -and OutSelect = - | Least - | Most -and Length = - | Implicit - | Explicit -and Return = - | Index - | Mask - -let inline getPseudoRegVar (ctxt: TranslationContext) name pos = - ctxt.GetPseudoRegVar (Register.toRegID name) pos - -let inline getRegVar (ctxt: TranslationContext) name = - Register.toRegID name |> ctxt.GetRegVar - -let inline numU32 n t = BitVector.ofUInt32 n t |> num -let inline numI32 n t = BitVector.ofInt32 n t |> num -let inline numU64 n t = BitVector.ofUInt64 n t |> num -let inline numI64 n t = BitVector.ofInt64 n t |> num - -let bvOfBaseAddr addr (ctxt: TranslationContext) = numU64 addr ctxt.WordBitSize - -let bvOfInstrLen insLen (ctxt: TranslationContext) = - numU32 insLen ctxt.WordBitSize - -let bvOfOprSize = function - | 8 | 16 | 32 | 64 | 128 | 256 | 512 as x -> - numI32 (int x) x - | _ -> raise InvalidOperandSizeException - -let inline is64bit (ctxt: TranslationContext) = ctxt.WordBitSize = 64 -let is64REXW ctxt (ins: InsInfo) = - is64bit ctxt && hasREXW ins.REXPrefix - -let inline private addSeg ctxt expr (ins: InsInfo) = - match getSegment ins.Prefixes with - | Some s -> getRegVar ctxt (segRegToBase s) .+ expr - | None -> expr - -let inline private ldMem ins ctxt oprSize e = - loadLE oprSize <| addSeg ctxt e ins - -let inline private numOfAddrSz (ins: InsInfo) (ctxt: TranslationContext) n = - let pref = ins.Prefixes - let sz = - if ctxt.WordBitSize = 32 then if hasAddrSz pref then 16 else 32 - else if hasAddrSz pref then 32 else 64 - numI64 n sz - -let inline private sIdx ins ctxt (r, s) = - (getRegVar ctxt r) .* (numOfAddrSz ins ctxt (int64 s)) - -let transMem ins insAddr insLen ctxt b index (disp: Disp option) oprSize = - match b, index, disp with - | None, None, Some d -> - numOfAddrSz ins ctxt d - |> zExt ctxt.WordBitSize - |> ldMem ins ctxt oprSize - | None, Some i, Some d -> - (sIdx ins ctxt i) .+ (numOfAddrSz ins ctxt d) - |> zExt ctxt.WordBitSize - |> ldMem ins ctxt oprSize - | Some b, None, None -> - getRegVar ctxt b - |> zExt ctxt.WordBitSize - |> ldMem ins ctxt oprSize - | Some R.RIP, None, Some d -> (* RIP-relative addressing *) - int64 insAddr + d + int64 insLen - |> numOfAddrSz ins ctxt - |> ldMem ins ctxt oprSize - | Some b, None, Some d -> - getRegVar ctxt b .+ (numOfAddrSz ins ctxt d) - |> zExt ctxt.WordBitSize - |> ldMem ins ctxt oprSize - | Some b, Some i, None -> - getRegVar ctxt b .+ (sIdx ins ctxt i) - |> zExt ctxt.WordBitSize - |> ldMem ins ctxt oprSize - | Some b, Some i, Some d -> - getRegVar ctxt b .+ (sIdx ins ctxt i) .+ (numOfAddrSz ins ctxt d) - |> zExt ctxt.WordBitSize - |> ldMem ins ctxt oprSize - | _, _, _ -> raise InvalidOperandException - -let transDirAddr wordSize (addr: Addr) = function - | Absolute (_, addr, _) -> numU64 addr wordSize - | Relative (offset) -> let offset = numI64 offset wordSize |> sExt wordSize - let addr = numU64 addr wordSize - offset .+ addr - -let inline private tmpVars2 t = tmpVar t, tmpVar t -let inline private tmpVars3 t = tmpVar t, tmpVar t, tmpVar t -let inline private tmpVars4 t = tmpVar t, tmpVar t, tmpVar t, tmpVar t - -let inline private getOperationSize (i: InsInfo) = i.InsSize.OperationSize -let inline private getEffAddrSz (i: InsInfo) = i.InsSize.MemSize.EffAddrSize -let inline private ( e1 - let e2High = extractHigh 1 e2 - let rHigh = extractHigh 1 r - (e1High == e2High) .& (e1High <+> rHigh) - -let getOFlagOnSub e1 e2 r = - extractHigh 1 (binop BinOpType.AND (e1 <+> e2) (e1 <+> r)) - -let buildAF ctxt e1 e2 r size = - let t1 = r <+> e1 - let t2 = t1 <+> e2 - let t3 = binop BinOpType.SHL (num1 size) (numU32 4ul size) - let t4 = t2 .& t3 - getRegVar ctxt R.AF := t4 == t3 - -let buildPF ctxt r size cond builder = - let t1, t2 = tmpVars2 size - let s2 = r <+> (binop BinOpType.SHR r (zExt size (numU32 4ul 8))) - let s4 = s2 <+> (binop BinOpType.SHR t1 (zExt size (numU32 2ul 8))) - let s5 = s4 <+> (binop BinOpType.SHR t2 (zExt size (num1 8))) - builder s5) - match cond with - | None -> builder builder r) - builder e3) - builder "CF is undefined." -let undefOF = unDef 1 "OF is undefined." -let undefAF = unDef 1 "AF is undefined." -let undefSF = unDef 1 "SF is undefined." -let undefZF = unDef 1 "ZF is undefined." -let undefPF = unDef 1 "PF is undefined." -let undefC0 = unDef 1 "C0 is undefined." -let undefC1 = unDef 1 "C1 is undefined." -let undefC2 = unDef 1 "C2 is undefined." -let undefC3 = unDef 1 "C3 is undefined." - -let allEFLAGSUndefined ctxt builder = - builder getRegVar ctxt reg - | OprMem (b, index, disp, oprSize) -> - transMem ins insAddr insLen ctxt b index disp oprSize - | OprImm imm -> getOperationSize ins |> BitVector.ofInt64 imm |> num - | OprDirAddr jumpTarget -> - transDirAddr ctxt.WordBitSize insAddr jumpTarget - | _ -> Utils.impossible () - -let getMemExpr128 expr = - match expr with - | Load (e, 128, expr, _, _) -> - AST.load e 64 (expr .+ numI32 8 (AST.typeOf expr)), - AST.load e 64 expr - | _ -> raise InvalidOperandException - -let getMemExpr256 expr = - match expr with - | Load (e, 256, expr, _, _) -> - AST.load e 64 (expr .+ numI32 24 (AST.typeOf expr)), - AST.load e 64 (expr .+ numI32 16 (AST.typeOf expr)), - AST.load e 64 (expr .+ numI32 8 (AST.typeOf expr)), - AST.load e 64 expr - | _ -> raise InvalidOperandException - -let getMemExpr512 expr = - match expr with - | Load (e, 512, expr, _, _) -> - AST.load e 64 (expr .+ numI32 56 (AST.typeOf expr)), - AST.load e 64 (expr .+ numI32 48 (AST.typeOf expr)), - AST.load e 64 (expr .+ numI32 40 (AST.typeOf expr)), - AST.load e 64 (expr .+ numI32 32 (AST.typeOf expr)), - AST.load e 64 (expr .+ numI32 24 (AST.typeOf expr)), - AST.load e 64 (expr .+ numI32 16 (AST.typeOf expr)), - AST.load e 64 (expr .+ numI32 8 (AST.typeOf expr)), - AST.load e 64 expr - | _ -> raise InvalidOperandException - -let getMemExprs expr = - match expr with - | Load (e, 128, expr, _, _) -> - [ AST.load e 64 expr; - AST.load e 64 (expr .+ numI32 8 (AST.typeOf expr)) ] - | Load (e, 256, expr, _, _) -> - [ AST.load e 64 expr - AST.load e 64 (expr .+ numI32 8 (AST.typeOf expr)); - AST.load e 64 (expr .+ numI32 16 (AST.typeOf expr)); - AST.load e 64 (expr .+ numI32 24 (AST.typeOf expr)); ] - | _ -> raise InvalidOperandException - -let getPseudoRegVar128 ctxt r = - getPseudoRegVar ctxt r 2, getPseudoRegVar ctxt r 1 - -let getPseudoRegVar256 ctxt r = - getPseudoRegVar ctxt r 4, getPseudoRegVar ctxt r 3, - getPseudoRegVar ctxt r 2, getPseudoRegVar ctxt r 1 - -let getPseudoRegVar512 ctxt r = - getPseudoRegVar ctxt r 8, getPseudoRegVar ctxt r 7, - getPseudoRegVar ctxt r 6, getPseudoRegVar ctxt r 5, - getPseudoRegVar ctxt r 4, getPseudoRegVar ctxt r 3, - getPseudoRegVar ctxt r 2, getPseudoRegVar ctxt r 1 - -let getPseudoRegVars ctxt r = - match Register.getKind r with - | Register.Kind.XMM -> [ getPseudoRegVar ctxt r 1; getPseudoRegVar ctxt r 2 ] - | Register.Kind.YMM -> [ getPseudoRegVar ctxt r 1; getPseudoRegVar ctxt r 2 - getPseudoRegVar ctxt r 3; getPseudoRegVar ctxt r 4 ] - | _ -> raise InvalidOperandException - -let getFPUPseudoRegVars ctxt r = - getPseudoRegVar ctxt r 2, getPseudoRegVar ctxt r 1 - -let transOprToExprVec ins insAddr insLen ctxt opr = - match opr with - | OprReg r -> getPseudoRegVars ctxt r - | OprMem (b, index, disp, oprSize) -> - transMem ins insAddr insLen ctxt b index disp oprSize |> getMemExprs - | OprImm imm -> [ getOperationSize ins |> BitVector.ofInt64 imm |> num ] - | _ -> raise InvalidOperandException - -let transOprToExpr32 ins insAddr insLen ctxt opr = - match opr with - | OprReg r when Register.toRegType r > 64 -> - getPseudoRegVar ctxt r 1 |> extractLow 32 - | OprReg r -> getRegVar ctxt r - | OprMem (b, index, disp, 32) -> - transMem ins insAddr insLen ctxt b index disp 32 - | _ -> raise InvalidOperandException - -let transOprToExpr64 ins insAddr insLen ctxt opr = - match opr with - | OprReg r when Register.toRegType r > 64 -> getPseudoRegVar ctxt r 1 - | OprReg r -> getRegVar ctxt r - | OprMem (b, index, disp, 64) -> - transMem ins insAddr insLen ctxt b index disp 64 - | _ -> raise InvalidOperandException - -let transOprToExpr128 ins insAddr insLen ctxt opr = - match opr with - | OprReg r -> getPseudoRegVar128 ctxt r - | OprMem (b, index, disp, oprSize) -> - transMem ins insAddr insLen ctxt b index disp oprSize |> getMemExpr128 - | _ -> raise InvalidOperandException - -let transOprToExpr256 ins insAddr insLen ctxt opr = - match opr with - | OprReg r -> getPseudoRegVar256 ctxt r - | OprMem (b, index, disp, oprSize) -> - transMem ins insAddr insLen ctxt b index disp oprSize |> getMemExpr256 - | _ -> raise InvalidOperandException - -let transOprToExpr512 ins insAddr insLen ctxt opr = - match opr with - | OprReg r -> getPseudoRegVar512 ctxt r - | OprMem (b, index, disp, oprSize) -> - transMem ins insAddr insLen ctxt b index disp oprSize |> getMemExpr512 - | _ -> raise InvalidOperandException - -let transOprToFloat80 ins insAddr insLen ctxt opr = - match opr with - | OprReg r when Register.toRegType r = 80 -> getRegVar ctxt r - | OprReg r -> - getRegVar ctxt r |> cast CastKind.FloatExt 80 - | OprMem (b, index, disp, 80) -> - transMem ins insAddr insLen ctxt b index disp 80 - | OprMem (b, index, disp, len) -> - transMem ins insAddr insLen ctxt b index disp len - |> cast CastKind.FloatExt 80 - | _ -> raise InvalidOperandException - -let getOneOpr (ins: InsInfo) = - match ins.Operands with - | OneOperand opr -> opr - | _ -> raise InvalidOperandException - -let getTwoOprs (ins: InsInfo) = - match ins.Operands with - | TwoOperands (o1, o2) -> o1, o2 - | _ -> raise InvalidOperandException - -let getThreeOprs (ins: InsInfo) = - match ins.Operands with - | ThreeOperands (o1, o2, o3) -> o1, o2, o3 - | _ -> raise InvalidOperandException - -let getFourOprs (ins: InsInfo) = - match ins.Operands with - | FourOperands (o1, o2, o3, o4) -> o1, o2, o3, o4 - | _ -> raise InvalidOperandException - -let transOneOpr ins insAddr insLen ctxt opr = - transOprToExpr ins insAddr insLen ctxt opr - -let transTwoOprs ins insAddr insLen ctxt (o1, o2) = - transOprToExpr ins insAddr insLen ctxt o1, - transOprToExpr ins insAddr insLen ctxt o2 - -let transThreeOprs ins insAddr insLen ctxt (o1, o2, o3) = - transOprToExpr ins insAddr insLen ctxt o1, - transOprToExpr ins insAddr insLen ctxt o2, - transOprToExpr ins insAddr insLen ctxt o3 - -let castNum newType = function - | Num num -> Num <| BitVector.cast num newType - | _ -> raise InvalidOperandException - -let getInstrPtr ctxt = getRegVar ctxt (if is64bit ctxt then R.RIP else R.EIP) -let getStackPtr ctxt = getRegVar ctxt (if is64bit ctxt then R.RSP else R.ESP) -let getBasePtr ctxt = getRegVar ctxt (if is64bit ctxt then R.RBP else R.EBP) -let getRegOfSize ctxt oprSize (regGrp: Register []) = - getRegVar ctxt <| match oprSize with - | 8 -> regGrp.[0] - | 16 -> regGrp.[1] - | 32 -> regGrp.[2] - | 64 -> regGrp.[3] - | _ -> raise InvalidOperandSizeException - -let getFstOperand = function - | OneOperand o -> o - | TwoOperands (o, _) -> o - | ThreeOperands (o, _, _) -> o - | FourOperands (o, _, _, _) -> o - | _ -> raise InvalidOperandException - -let getSndOperand = function - | TwoOperands (_, o) -> o - | ThreeOperands (_, o, _) -> o - | FourOperands (_, o, _, _) -> o - | _ -> raise InvalidOperandException - -/// This is an Intel-specific assignment to a destination operand. -/// Unlike typical assignments, this function performs zero-padding when -/// necessary (See Intel Manual 3.4.1.1). -/// In 64-bit mode, operand size determines the number of valid bits. -/// 64-bit operands generate a 64-bit result in the destination general-purpose -/// register. 32-bit operands generate a 32-bit result, zero-extended to a -/// 64-bit result in the destination general-purpose register. 8-bit and 16-bit -/// operands generate 8-bit or 16-bit result. The upper 56 or 48 bits -/// (respectively) of the destination general-purpose register are not modified. -let dstAssign oprSize dst src = - match oprSize with - | 8 | 16 -> dst := src (* No extension for 8- and 16-bit operands *) - | _ -> let dst = unwrapExpr dst - let dstOrigSz = dst |> AST.typeOf - let oprBitSize = RegType.toBitWidth oprSize - let dstBitSize = RegType.toBitWidth dstOrigSz - if dstBitSize > oprBitSize then dst := zExt dstOrigSz src - elif dstBitSize = oprBitSize then dst := src - else raise InvalidOperandSizeException - -let getDividend ctxt = function - | 8 -> getRegVar ctxt R.AX - | 16 -> concat (getRegVar ctxt R.DX) (getRegVar ctxt R.AX) - | 32 -> concat (getRegVar ctxt R.EDX) (getRegVar ctxt R.EAX) - | 64 -> concat (getRegVar ctxt R.RDX) (getRegVar ctxt R.RAX) - | _ -> raise InvalidOperandSizeException - -let maxNum = function - | 8 -> BitVector.maxNum8 - | 16 -> BitVector.maxNum16 - | 32 -> BitVector.maxNum32 - | 64 -> BitVector.maxNum64 - | _ -> raise InvalidOperandSizeException - -let packCmp cmp typ e1 e2 oprSize unitWidth builder = - let maxIdx = RegType.toBitWidth oprSize / unitWidth - let unitSz = RegType.fromBitWidth unitWidth - let t1, t2 = tmpVars2 oprSize - let tmps = [| for _ in 1 .. maxIdx -> tmpVar unitSz |] - let getSrc s idx = extract s unitSz (unitWidth * idx) - let packMask e1 e2 unitSz cmp = - let zero = num0 unitSz - let maxVal = num <| maxNum unitSz - ite (cmp e1 e2) maxVal zero - let getDst idx = - let src1 = getSrc t1 idx - let src2 = getSrc t2 idx - match typ with - | PackMask -> packMask src1 src2 unitSz cmp - | PackSelect -> ite (cmp src1 src2) src1 src2 - builder builder true - | _ -> false - match opr with - | Var (_, s, _, _) -> - if isSegReg <| Register.ofRegID s then zExt oprSize opr else opr - | Num (_) -> sExt oprSize opr - | _ -> opr - -let inline getStackWidth wordSize oprSize = - numI32 (RegType.toByteWidth oprSize) wordSize - -let auxPush oprSize ctxt expr builder = - let t = tmpVar oprSize - let sp = getStackPtr ctxt - builder true - | _ -> false - let handleSegPop oprSize = function - | Var (_, x, _, _) when isSegReg <| Register.ofRegID x -> 16 - | _ -> oprSize - builder && oprSize = 16 - then raise InvalidOn64Exception - match ins.Opcode with - | Opcode.JO -> getRegVar ctxt R.OF - | Opcode.JNO -> getRegVar ctxt R.OF == b0 - | Opcode.JB -> getRegVar ctxt R.CF - | Opcode.JNB -> getRegVar ctxt R.CF == b0 - | Opcode.JZ -> getRegVar ctxt R.ZF - | Opcode.JNZ -> getRegVar ctxt R.ZF == b0 - | Opcode.JBE -> (getRegVar ctxt R.CF) .| (getRegVar ctxt R.ZF) - | Opcode.JA -> ((getRegVar ctxt R.CF) .| (getRegVar ctxt R.ZF)) == b0 - | Opcode.JS -> getRegVar ctxt R.SF - | Opcode.JNS -> getRegVar ctxt R.SF == b0 - | Opcode.JP -> getRegVar ctxt R.PF - | Opcode.JNP -> getRegVar ctxt R.PF == b0 - | Opcode.JL -> getRegVar ctxt R.SF != getRegVar ctxt R.OF - | Opcode.JNL -> getRegVar ctxt R.SF == getRegVar ctxt R.OF - | Opcode.JLE -> (getRegVar ctxt R.ZF) .| - (getRegVar ctxt R.SF != getRegVar ctxt R.OF) - | Opcode.JG -> (getRegVar ctxt R.ZF == b0) .& - (getRegVar ctxt R.SF == getRegVar ctxt R.OF) - | Opcode.JCXZ -> (getRegVar ctxt R.CX) == (num0 ctxt.WordBitSize) - | Opcode.JECXZ -> - let addrSize = ctxt.WordBitSize - (cast CastKind.ZeroExt addrSize (getRegVar ctxt R.ECX)) == (num0 addrSize) - | Opcode.JRCXZ -> (getRegVar ctxt R.RCX) == (num0 ctxt.WordBitSize) - | _ -> raise InvalidOpcodeException - -let getCondOfSet (ins: InsInfo) ctxt = - match ins.Opcode with - | Opcode.SETO -> getRegVar ctxt R.OF - | Opcode.SETNO -> getRegVar ctxt R.OF == b0 - | Opcode.SETB -> getRegVar ctxt R.CF - | Opcode.SETNB -> getRegVar ctxt R.CF == b0 - | Opcode.SETZ -> getRegVar ctxt R.ZF - | Opcode.SETNZ -> getRegVar ctxt R.ZF == b0 - | Opcode.SETBE -> (getRegVar ctxt R.CF) .| (getRegVar ctxt R.ZF) - | Opcode.SETA -> ((getRegVar ctxt R.CF) .| (getRegVar ctxt R.ZF)) == b0 - | Opcode.SETS -> getRegVar ctxt R.SF - | Opcode.SETNS -> getRegVar ctxt R.SF == b0 - | Opcode.SETP -> getRegVar ctxt R.PF - | Opcode.SETNP -> getRegVar ctxt R.PF == b0 - | Opcode.SETL -> getRegVar ctxt R.SF != getRegVar ctxt R.OF - | Opcode.SETNL -> getRegVar ctxt R.SF == getRegVar ctxt R.OF - | Opcode.SETLE -> getRegVar ctxt R.ZF .| - (getRegVar ctxt R.SF != getRegVar ctxt R.OF) - | Opcode.SETG -> (getRegVar ctxt R.ZF == b0) .& - (getRegVar ctxt R.SF == getRegVar ctxt R.OF) - | _ -> raise InvalidOpcodeException - -let convertSrc = function - | Load (_, _, expr, _, _) -> expr - | _ -> failwith "Does not apply.(convert SRC)" - -let getCondOfCMov (ins: InsInfo) ctxt = - match ins.Opcode with - | Opcode.CMOVO -> getRegVar ctxt R.OF - | Opcode.CMOVNO -> getRegVar ctxt R.OF == b0 - | Opcode.CMOVB -> getRegVar ctxt R.CF - | Opcode.CMOVAE -> getRegVar ctxt R.CF == b0 - | Opcode.CMOVZ -> getRegVar ctxt R.ZF - | Opcode.CMOVNZ -> getRegVar ctxt R.ZF == b0 - | Opcode.CMOVBE -> (getRegVar ctxt R.CF) .| (getRegVar ctxt R.ZF) - | Opcode.CMOVA -> ((getRegVar ctxt R.CF) .| (getRegVar ctxt R.ZF)) == b0 - | Opcode.CMOVS -> getRegVar ctxt R.SF - | Opcode.CMOVNS -> getRegVar ctxt R.SF == b0 - | Opcode.CMOVP -> getRegVar ctxt R.PF - | Opcode.CMOVNP -> getRegVar ctxt R.PF == b0 - | Opcode.CMOVL -> getRegVar ctxt R.SF != getRegVar ctxt R.OF - | Opcode.CMOVGE -> getRegVar ctxt R.SF == getRegVar ctxt R.OF - | Opcode.CMOVLE -> getRegVar ctxt R.ZF .| - (getRegVar ctxt R.SF != getRegVar ctxt R.OF) - | Opcode.CMOVG -> getRegVar ctxt R.ZF == b0 .& - (getRegVar ctxt R.SF == getRegVar ctxt R.OF) - | _ -> raise InvalidOpcodeException - -let movqRegToReg ctxt r1 r2 builder = - match Register.getKind r1, Register.getKind r2 with - | Register.Kind.XMM, Register.Kind.XMM -> - builder ) - | Register.Kind.XMM, _ -> - builder ) - | Register.Kind.GP, Register.Kind.XMM -> - builder - builder failwith "Not a Register to Register." - -let movqRegToMem ctxt dst r builder = - match Register.getKind r with - | Register.Kind.XMM -> builder builder failwith "Not a Register to Memory." - -let movqMemToReg ctxt src r builder = - match Register.getKind r with - | Register.Kind.XMM -> - builder ) - | Register.Kind.MMX -> builder failwith "Not a Memory to Register." - -let movdRegToReg ctxt r1 r2 builder = - let tmp = tmpVar 32 - match Register.getKind r1, Register.getKind r2 with - | Register.Kind.XMM, _ -> - builder (getRegVar ctxt r2)) - builder ) - | _, Register.Kind.XMM -> - builder (getPseudoRegVar ctxt r2 1)) - builder (getRegVar ctxt r1) tmp) - | Register.Kind.MMX, _ -> - builder (getRegVar ctxt r2)) - | _, Register.Kind.MMX -> - builder (getRegVar ctxt r2)) - builder (getRegVar ctxt r1) tmp) - | _, _ -> failwith "Not a Register to Register." - -let movdRegToMem ctxt dst r builder = - match Register.getKind r with - | Register.Kind.XMM -> - builder (getPseudoRegVar ctxt r 1)) - | Register.Kind.MMX -> builder (getRegVar ctxt r)) - | _ -> failwith "Not a Register to Memory." - -let movdMemToReg ctxt src r builder = - match Register.getKind r with - | Register.Kind.XMM -> - builder src) - builder ) - | Register.Kind.MMX -> builder src) - | _ -> failwith "Not a Register to Memory." - -let maskOffset offset oprSize = - let offset = zExt oprSize offset - match oprSize with - | 16 -> offset .& numU32 0xFu 16 - | 32 -> offset .& numU32 0x1Fu 32 - | 64 -> offset .& numU32 0x3Fu 64 - | _ -> raise InvalidOperandSizeException - -let rec isVar = function - | Var _ | TempVar _ -> true - | Extract (e, _, _, _, _) -> isVar e - | _ -> false - -let calculateOffset offset oprSize = - let offset = zExt oprSize offset - match oprSize with - | 16 -> numU32 2u 16 .* (offset ./ numU32 16u 16), - offset .& numU32 15u 16 - | 32 -> numU32 4u 32 .* (offset ./ numU32 32u 32), - offset .& numU32 31u 32 - | 64 -> numU32 4u 64 .* (offset ./ numU32 32u 64), - offset .& numU32 31u 64 - | _ -> raise InvalidOperandSizeException - -let bit ins bitBase bitOffset oprSize = - match bitBase with - | Load (e, t, expr, _, _) -> - let effAddrSz = getEffAddrSz ins - let addrOffset, bitOffset = calculateOffset bitOffset oprSize - let addrOffset = zExt effAddrSz addrOffset - extractLow 1 ((AST.load e t (expr .+ addrOffset)) >> bitOffset) - | _ -> if isVar bitBase - then extractLow 1 (bitBase >> maskOffset bitOffset oprSize) - else raise InvalidExprException - -let getMask oprSize = - match oprSize with - | 8 -> numI64 0xffL oprSize - | 16 -> numI64 0xffffL oprSize - | 32 -> numI64 0xffffffffL oprSize - | 64 -> numI64 0xffffffffffffffffL oprSize - | _ -> raise InvalidOperandSizeException - -let setBit ins bitBase bitOffset oprSize setValue = - match bitBase with - | Load (e, t, expr, _, _) -> - let effAddrSz = getEffAddrSz ins - let addrOffset, bitOffset = calculateOffset bitOffset oprSize - let addrOffset = zExt effAddrSz addrOffset - let mask = setValue << bitOffset - let loadMem = AST.load e t (expr .+ addrOffset) - loadMem := (loadMem .& (getMask oprSize .- mask)) .| mask - | _ -> if isVar bitBase - then let mask = setValue << maskOffset bitOffset oprSize - bitBase := (bitBase .& (getMask oprSize .- mask)) .| mask - else raise InvalidExprException - -let isFPUStackReg = function - | R.ST0 | R.ST1 | R.ST2 | R.ST3 | R.ST4 | R.ST5 | R.ST6 | R.ST7 -> true - | _ -> false - -let isFPUStackOpr = function - | OprReg r when isFPUStackReg r -> true - | _ -> false - -let checkC1Flag ctxt builder topTagReg = - let c1 = getRegVar ctxt R.FSWC1 - let tagV = getRegVar ctxt topTagReg - let rc = extract (getRegVar ctxt R.FCW) 2 10 - builder ) b1 b0) - builder ) b0 c1) - -let checkFPUOnLoad ctxt builder = - let top = getRegVar ctxt R.FTOP - let c1Flag = getRegVar ctxt R.FSWC1 - let cond1, cond2 = tmpVars2 1 - builder ) - builder ) != num0 2) - builder ) - -let fpuRegValue ctxt reg = - let stb, sta = getFPUPseudoRegVars ctxt reg - concat stb sta - -let assignFPUReg reg expr80 ctxt builder = - let stb, sta = getFPUPseudoRegVars ctxt reg - builder expr80) - builder expr80) - -let getTagValueOnLoad ctxt builder = - let tmp = tmpVar 2 - let st0 = fpuRegValue ctxt R.ST0 - let exponent = extract st0 11 52 - let zero = num0 11 - let max = BitVector.unsignedMax 11 |> num - let cond0 = (extractLow 63 st0) == num0 63 - let condSpecial = (exponent == zero) .| (exponent == max) - builder ) - builder |> num) tmp) - builder ) tmp) - tmp - -let updateTagWordOnLoad ctxt builder = - let top = getRegVar ctxt R.FTOP - let tagWord = getRegVar ctxt R.FTW - let top16, mask, shifter, tagValue16 = tmpVars4 16 - let tagValue = getTagValueOnLoad ctxt builder - let value3 = BitVector.ofInt32 3 16 |> num - builder top) - builder |> num) .* top16) - builder tagValue) - builder - let value3 = BitVector.ofInt32 3 16 |> num - builder top) - builder |> num) .* top16) - builder - assignFPUReg R.ST0 (fpuRegValue ctxt R.ST1) ctxt builder - assignFPUReg R.ST1 (fpuRegValue ctxt R.ST2) ctxt builder - assignFPUReg R.ST2 (fpuRegValue ctxt R.ST3) ctxt builder - assignFPUReg R.ST3 (fpuRegValue ctxt R.ST4) ctxt builder - assignFPUReg R.ST4 (fpuRegValue ctxt R.ST5) ctxt builder - assignFPUReg R.ST5 (fpuRegValue ctxt R.ST6) ctxt builder - assignFPUReg R.ST6 (fpuRegValue ctxt R.ST7) ctxt builder - assignFPUReg R.ST7 (num0 80) ctxt builder - builder ) - builder ) == num0 2) - builder ) - -let rec subPackedByte opFn s1 s2 (tDstArr: Expr []) oprSz sepSz idx sz builder = - let tS1, tS2 = tmpVars2 sepSz - if sz = 0 then () - else builder tmpVar 8 |] - subPackedByte (.-) src1 src2 tDstArr oprSize 8 0 size builder - concatExprs tDstArr - -let oneOperandImul ins insAddr insLen ctxt oprSize builder = - let src = getOneOpr ins |> transOneOpr ins insAddr insLen ctxt - let sF = getRegVar ctxt R.SF - let shiftNum = RegType.toBitWidth oprSize - let mulSize = RegType.double oprSize - let t = tmpVar mulSize - let cond = sExt mulSize (extractLow oprSize t) == t - match oprSize with - | 8 -> - builder | 32 | 64 -> - let r1 = getRegOfSize ctxt oprSize GrpEDX - let r2 = getRegOfSize ctxt oprSize GrpEAX - builder raise InvalidOperandSizeException - builder (shiftNum - 1)) - builder - let d, s = getTwoOprs ins |> transTwoOprs ins insAddr insLen ctxt - d, d, s - | ThreeOperands _ -> - getThreeOprs ins |> transThreeOprs ins insAddr insLen ctxt - | _ -> raise InvalidOperandException - let doubleWidth = RegType.double oprSize - let t = tmpVar doubleWidth - let cond = (sExt doubleWidth dst) != t - builder dst) - builder BitVector.getValue n - | _ -> raise InvalidExprException - let agg = match (immByte >>> 2) &&& 3I with - | v when v = 0I -> EqualAny - | v when v = 1I -> Ranges - | v when v = 2I -> EqualEach - | v when v = 3I -> EqualOrdered - | _ -> failwith "Invalid value" - let pol = match (immByte >>> 4) &&& 3I with - | v when v = 0I -> PosPolarity - | v when v = 1I -> NegPolarity - | v when v = 2I -> PosMasked - | v when v = 3I -> NegMasked - | _ -> failwith "Invalid value" - let size, nElem = - if immByte &&& 1I = 0I then 8, 16u else 16, 8u - let len, ret = - match opCode with - | Opcode.PCMPISTRI | Opcode.VPCMPISTRI -> Implicit, Index - | Opcode.PCMPESTRI | Opcode.VPCMPESTRI -> Explicit, Index - | Opcode.PCMPISTRM | Opcode.VPCMPISTRM -> Implicit, Mask - | Opcode.PCMPESTRM | Opcode.VPCMPESTRM -> Explicit, Mask - | _ -> raise InvalidOpcodeException - { - PackSize = size - NumElems = nElem - Sign = if (immByte >>> 1) &&& 1I = 0I then UnSigned else Signed - Agg = agg - Polarity = pol - OutSelect = if (immByte >>> 6) &&& 1I = 0I then Least else Most - Len = len - Ret = ret - } - -let getIntRes2 e ctrInfo (booRes: Expr []) = - let elemSz = RegType.fromBitWidth <| int ctrInfo.NumElems - let elemCnt = ctrInfo.NumElems |> int - match ctrInfo.Polarity with - | PosPolarity | PosMasked -> e - | NegPolarity -> numI32 -1 elemSz <+> e - | NegMasked -> - List.fold (fun acc i -> - let e1 = e .& numI32 (pown 2 i) elemSz - let e2 = (AST.not e) .& numI32 (pown 2 i) elemSz - (ite (booRes.[i]) e2 e1) :: acc) [] [0 .. elemCnt - 1] - |> List.reduce (.|) - -let rec genOutput ctrl e acc i = - let elemSz = RegType.fromBitWidth <| int ctrl.NumElems - let isSmallOut = ctrl.OutSelect = Least - let e' = e >> numI32 i elemSz - let next = if isSmallOut then i - 1 else i + 1 - let cond = if isSmallOut then i = 0 else i = int ctrl.NumElems - 1 - if cond then ite (extractLow 1 e') (numI32 i elemSz) acc - else genOutput ctrl e (ite (extractLow 1 e') (numI32 i elemSz) acc) next - -let implicitValidCheck ctrl srcB srcA builder = - let unitWidth = RegType.toBitWidth ctrl.PackSize - let tmps = [| for _ in 1u .. ctrl.NumElems -> tmpVar 1 |] - let getSrc idx e = extract e ctrl.PackSize (unitWidth * idx) - let rec getValue idx = - if idx = int ctrl.NumElems then () - else - let half = int ctrl.NumElems / 2 - let e, amount = if idx < half then srcA, idx else srcB, idx - half - let v e = tmps.[idx - 1] .& (getSrc amount e != num0 ctrl.PackSize) - builder tmpVar 1 |] - let checkNum = numU32 ctrl.NumElems rSz - let rec getValue idx = - let v = lt (numU32 idx rSz) (ite (lt checkNum reg) checkNum reg) - if idx = ctrl.NumElems then () - else builder implicitValidCheck ctrl src1B src1A builder, - implicitValidCheck ctrl src2B src2A builder - | Explicit -> - let regSize, ax, dx = - if hasREXW ins.REXPrefix - then 64, getRegVar ctxt R.RAX, getRegVar ctxt R.RDX - else 32, getRegVar ctxt R.EAX, getRegVar ctxt R.EDX - explicitValidCheck ctrl ax regSize builder, - explicitValidCheck ctrl dx regSize builder - -let genBoolRes ins insAddr insLen // XXX - ctrl ctxt e1 e2 (ck1: Expr []) (ck2: Expr []) j i cmp = - let src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt e1 - let src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt e2 - let elemSz = RegType.fromBitWidth <| int ctrl.NumElems - let getSrc s idx = - let unitWidth = RegType.toBitWidth ctrl.PackSize - let amount = unitWidth * idx - let amount = if amount < 64 then amount else amount - 64 - extract s ctrl.PackSize amount - let b = - let e1 = if j < int ctrl.NumElems / 2 then src1A else src1B - let e2 = if i < int ctrl.NumElems / 2 then src2A else src2B - (ite (cmp (getSrc e1 j) (getSrc e2 i)) (num1 elemSz) (num0 elemSz)) - match ctrl.Agg with - | EqualAny | Ranges -> - ite (AST.not ck1.[j] .& AST.not ck2.[i]) (num0 elemSz) - (ite (AST.not ck1.[j] .| AST.not ck2.[i]) (num0 elemSz) b) - | EqualEach -> - ite (AST.not ck1.[i] .& AST.not ck2.[i]) (num1 elemSz) - (ite (AST.not ck1.[i] .| AST.not ck2.[i]) (num0 elemSz) b) - | EqualOrdered -> - ite (AST.not ck1.[j] .& AST.not ck2.[i]) (num1 elemSz) - (ite (AST.not ck1.[j] .& ck2.[i]) (num1 elemSz) - (ite (ck1.[j] .& AST.not ck2.[i]) (num0 elemSz) b)) - -let sideEffects insAddr insLen name = - let builder = new StmtBuilder (4) - startMark insAddr insLen builder - builder builder - builder R.YMM0 - | OprReg R.XMM1 -> R.YMM1 - | OprReg R.XMM2 -> R.YMM2 - | OprReg R.XMM3 -> R.YMM3 - | OprReg R.XMM4 -> R.YMM4 - | OprReg R.XMM5 -> R.YMM5 - | OprReg R.XMM6 -> R.YMM6 - | OprReg R.XMM7 -> R.YMM7 - | OprReg R.XMM8 -> R.YMM8 - | OprReg R.XMM9 -> R.YMM9 - | OprReg R.XMM10 -> R.YMM10 - | OprReg R.XMM11 -> R.YMM11 - | OprReg R.XMM12 -> R.YMM12 - | OprReg R.XMM13 -> R.YMM13 - | OprReg R.XMM14 -> R.YMM14 - | OprReg R.XMM15 -> R.YMM15 - | _ -> raise InvalidOperandException - -let r128to512 = function - | OprReg R.XMM0 -> R.ZMM0 - | OprReg R.XMM1 -> R.ZMM1 - | OprReg R.XMM2 -> R.ZMM2 - | OprReg R.XMM3 -> R.ZMM3 - | OprReg R.XMM4 -> R.ZMM4 - | OprReg R.XMM5 -> R.ZMM5 - | OprReg R.XMM6 -> R.ZMM6 - | OprReg R.XMM7 -> R.ZMM7 - | OprReg R.XMM8 -> R.ZMM8 - | OprReg R.XMM9 -> R.ZMM9 - | OprReg R.XMM10 -> R.ZMM10 - | OprReg R.XMM11 -> R.ZMM11 - | OprReg R.XMM12 -> R.ZMM12 - | OprReg R.XMM13 -> R.ZMM13 - | OprReg R.XMM14 -> R.ZMM14 - | OprReg R.XMM15 -> R.ZMM15 - | _ -> raise InvalidOperandException - -let r256to512 = function - | OprReg R.YMM0 -> R.ZMM0 - | OprReg R.YMM1 -> R.ZMM1 - | OprReg R.YMM2 -> R.ZMM2 - | OprReg R.YMM3 -> R.ZMM3 - | OprReg R.YMM4 -> R.ZMM4 - | OprReg R.YMM5 -> R.ZMM5 - | OprReg R.YMM6 -> R.ZMM6 - | OprReg R.YMM7 -> R.ZMM7 - | OprReg R.YMM8 -> R.ZMM8 - | OprReg R.YMM9 -> R.ZMM9 - | OprReg R.YMM10 -> R.ZMM10 - | OprReg R.YMM11 -> R.ZMM11 - | OprReg R.YMM12 -> R.ZMM12 - | OprReg R.YMM13 -> R.ZMM13 - | OprReg R.YMM14 -> R.ZMM14 - | OprReg R.YMM15 -> R.ZMM15 - | _ -> raise InvalidOperandException - -let fillZeroHigh ins ctxt dst builder = - match getOperationSize ins with - | 128 -> - let dst = r128to256 dst - let dstC, dstD = getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4 - let n0 = num0 64 - builder -> - let dst = r256to512 dst - let dstE, dstF, dstG, dstH = - getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4, - getPseudoRegVar ctxt dst 5, getPseudoRegVar ctxt dst 6 - let n0 = num0 64 - builder raise InvalidOperandSizeException - -let fillZeroHigh128 ctxt dst builder = - let dst = r128to256 dst - let dstC, dstD = getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4 - let n0 = num0 64 - builder - builder - match maxVl, vl with - | 512, 128 -> - let dst = r128to512 dst - let dstC, dstD, dstE, dstF, dstG, dstH = - getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4, - getPseudoRegVar ctxt dst 5, getPseudoRegVar ctxt dst 6, - getPseudoRegVar ctxt dst 7, getPseudoRegVar ctxt dst 8 - builder - let dst = r256to512 dst - let dstE, dstF, dstG, dstH = - getPseudoRegVar ctxt dst 5, getPseudoRegVar ctxt dst 6, - getPseudoRegVar ctxt dst 7, getPseudoRegVar ctxt dst 8 - builder failwith "Invalid MAX Vector Length" - -let saturateSignedWordToSignedByte expr = - let checkMin = slt expr (numI32 -128 16) - let checkMax = sgt expr (numI32 127 16) - let minNum = numI32 -128 8 - let maxNum = numI32 127 8 - ite checkMin minNum (ite checkMax maxNum (extractLow 8 expr)) - -let saturateSignedDwordToSignedWord expr = - let checkMin = slt expr (numI32 -32768 32) - let checkMax = sgt expr (numI32 32767 32) - let minNum = numI32 -32768 16 - let maxNum = numI32 32767 16 - ite checkMin minNum (ite checkMax maxNum (extractLow 16 expr)) - -let saturateSignedWordToUnsignedByte expr = - let checkMin = slt expr (numI32 0 16) - let checkMax = sgt expr (numI32 255 16) - let minNum = numU32 0u 8 - let maxNum = numU32 0xffu 8 - ite checkMin minNum (ite checkMax maxNum (extractLow 8 expr)) - -let saturateToSignedByte expr = - let checkMin = slt expr (numI32 -128 8) - let checkMax = sgt expr (numI32 127 8) - let minNum = numI32 -128 8 - let maxNum = numI32 127 8 - ite checkMin minNum (ite checkMax maxNum expr) - -let saturateToSignedWord expr = - let checkMin = slt expr (numI32 -32768 16) - let checkMax = sgt expr (numI32 32767 16) - let minNum = numI32 -32768 16 - let maxNum = numI32 32767 16 - ite checkMin minNum (ite checkMax maxNum expr) - -let saturateToUnsignedByte expr = - let checkMin = lt expr (numU32 0u 8) - let checkMax = gt expr (numU32 0xffu 8) - let minNum = numU32 0u 8 - let maxNum = numU32 0xffu 8 - ite checkMin minNum (ite checkMax maxNum expr) - -let saturateToUnsignedWord expr = - let checkMin = lt expr (numU32 0u 16) - let checkMax = gt expr (numU32 0xffffu 16) - let minNum = numU32 0u 16 - let maxNum = numU32 0xffu 16 - ite checkMin minNum (ite checkMax maxNum expr) - -let buildMove ins insAddr insLen ctxt bufSize = - let builder = new StmtBuilder (bufSize) - let dst, src = getTwoOprs ins - let oprSize = getOperationSize ins - startMark insAddr insLen builder - match oprSize with - | 32 | 64 -> - let dst, src = transTwoOprs ins insAddr insLen ctxt (dst, src) - builder | 256 | 512 -> - let dst = transOprToExprVec ins insAddr insLen ctxt dst - let src = transOprToExprVec ins insAddr insLen ctxt src - List.iter2 (fun d s -> builder raise InvalidOperandSizeException - endMark insAddr insLen builder - -let makeSrc builder packSize packNum src = - let tSrc = Array.init packNum (fun _ -> tmpVar packSize) - for i in 0 .. packNum - 1 do - builder -> - let dst, src = transTwoOprs ins insAddr insLen ctxt (dst, src) - let src1 = makeSrc packNum dst - let src2 = match src with - | Load (_, rt, _, _, _) -> makeSrc (rt / packSz) src - | _ -> makeSrc packNum src - builder concatExprs) - | 128 -> - let packNum = packNum / (oprSize / 64) - let srcAppend src = - let src = transOprToExprVec ins insAddr insLen ctxt src - List.map (makeSrc packNum) src |> List.fold Array.append [||] - let tSrc = opFn oprSize (srcAppend dst) (srcAppend src) - let dst = transOprToExprVec ins insAddr insLen ctxt dst - let packNum = Array.length tSrc / List.length dst - let assign idx dst = - builder concatExprs) - List.iteri assign dst - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let buildPackedInstrThreeOprs ins iAddr iLen ctxt packSz opFn bufSz dst s1 s2 = - let builder = new StmtBuilder (bufSz) - let oprSize = getOperationSize ins - let packNum = oprSize / packSz - let makeSrc = makeSrc builder packSz - startMark iAddr iLen builder - match oprSize with - | 64 -> - let dst, src1, src2 = transThreeOprs ins iAddr iLen ctxt (dst, s1, s2) - let src1 = makeSrc packNum src1 - let src2 = makeSrc packNum src2 - builder concatExprs) - | 128 | 256 -> - let packNum = packNum / (oprSize / 64) - let dst = transOprToExprVec ins iAddr iLen ctxt dst - let srcAppend src = - let src = transOprToExprVec ins iAddr iLen ctxt src - List.map (makeSrc packNum) src |> List.fold Array.append [||] - let tSrc = opFn oprSize (srcAppend s1) (srcAppend s2) - let assign idx dst = - builder concatExprs) - List.iteri assign dst - | _ -> raise InvalidOperandSizeException - endMark iAddr iLen builder - -let buildPackedInstr ins insAddr insLen ctxt packSz opFn bufSz = - match ins.Operands with - | TwoOperands (o1, o2) -> - buildPackedInstrTwoOprs ins insAddr insLen ctxt packSz opFn bufSz o1 o2 - | ThreeOperands (o1, o2, o3) -> - buildPackedInstrThreeOprs ins insAddr insLen ctxt packSz opFn bufSz o1 o2 o3 - | _ -> raise InvalidOperandException - -let getTwoSrcOperands = function - | TwoOperands (op1, op2) -> (op1, op2) - | ThreeOperands (_op1, op2, op3) -> (op2, op3) - | _ -> raise InvalidOperandException - -let handleScalarFPOp ins insAddr insLen ctxt sz op = - let builder = new StmtBuilder(8) - let _dst2, dst1 = - ins.Operands |> getFstOperand |> transOprToExpr128 ins insAddr insLen ctxt - let src1, src2 = getTwoSrcOperands ins.Operands - let src1 = transOprToExpr64 ins insAddr insLen ctxt src1 - let src2 = - if sz = 32 then transOprToExpr32 ins insAddr insLen ctxt src2 - else transOprToExpr64 ins insAddr insLen ctxt src2 - let dst1, src1 = - if sz = 32 then extractLow 32 dst1, extractLow 32 src1 - else dst1, src1 - let t1, t2, t3 = tmpVars3 sz - startMark insAddr insLen builder - builder startPos |> sExt 64 - let n num = - numI64 num 64 - builder ) - builder - let mod10 = intgr .% n10 |> zExt 4 - let digitAt startPos = extract bcd 4 startPos - let rec doAssign startPos = - if startPos >= 72 then () - else - builder - let cond1 = gt alAnd0f (numI32 9 8) - let cond2 = af == b1 - let cond = tmpVar 1 - startMark insAddr insLen builder - if oprSize = 64 then () - else - builder ) ax) - builder transOneOpr ins insAddr insLen ctxt |> extractLow 8 - let oprSize = getOperationSize ins - let al = getRegVar ctxt R.AL - let ah = getRegVar ctxt R.AH - startMark insAddr insLen builder - if oprSize = 64 then () - else - builder )) - builder ) - enumSZPFlags ctxt al 8 builder - builder transOneOpr ins insAddr insLen ctxt |> extractLow 8 - let oprSize = getOperationSize ins - let al = getRegVar ctxt R.AL - let ah = getRegVar ctxt R.AH - startMark insAddr insLen builder - if oprSize = 64 then () - else - builder builder - builder - let cond1 = gt alAnd0f (numI32 9 8) - let cond2 = af == b1 - let cond = tmpVar 1 - startMark insAddr insLen builder - if oprSize = 64 then () - else - builder ) ax) - builder ) ah) - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let cf = getRegVar ctxt R.CF - let t1, t2, t3, t4 = tmpVars4 oprSize - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t1, t2, t3 = tmpVars3 oprSize - startMark insAddr insLen builder - builder (opP fadd) 8 - -let addps ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 (opP fadd) 8 - -let addsd ins insAddr insLen ctxt = - handleScalarFPOp ins insAddr insLen ctxt 64 fadd - -let addss ins insAddr insLen ctxt = - handleScalarFPOp ins insAddr insLen ctxt 32 fadd - -let divpd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 (opP fdiv) 8 - -let divps ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 (opP fdiv) 8 - -let divsd ins insAddr insLen ctxt = - handleScalarFPOp ins insAddr insLen ctxt 64 fdiv - -let divss ins insAddr insLen ctxt = - handleScalarFPOp ins insAddr insLen ctxt 32 fdiv - -let mulpd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 (opP fmul) 8 - -let mulps ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 (opP fmul) 8 - -let mulsd ins insAddr insLen ctxt = - handleScalarFPOp ins insAddr insLen ctxt 64 fmul - -let mulss ins insAddr insLen ctxt = - handleScalarFPOp ins insAddr insLen ctxt 32 fmul - -let subps ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 (opP fsub) 8 - -let subsd ins insAddr insLen ctxt = - handleScalarFPOp ins insAddr insLen ctxt 64 fsub - -let subss ins insAddr insLen ctxt = - handleScalarFPOp ins insAddr insLen ctxt 32 fsub - -let sqrtpd ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let opr1, opr2 = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt opr1 - let src2, src1 = transOprToExpr128 ins insAddr insLen ctxt opr2 - startMark insAddr insLen builder - builder - startMark insAddr insLen builder - builder src1) - builder src1) - builder src2) - builder src2) - builder dst1 := unop UnOpType.FSQRT tmp1) - builder dst1 := unop UnOpType.FSQRT tmp2) - builder dst2 := unop UnOpType.FSQRT tmp3) - builder dst2 := unop UnOpType.FSQRT tmp4) - endMark insAddr insLen builder - -let sqrtsd ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let opr1, opr2 = getTwoOprs ins - let dst = transOprToExpr64 ins insAddr insLen ctxt opr1 - let src = transOprToExpr64 ins insAddr insLen ctxt opr2 - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t = tmpVar oprSize - startMark insAddr insLen builder - builder (AST.not e1) .& e2) - -let andnpd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPandn 8 - -let andnps ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPandn 8 - -let opPand _ = Array.map2 (.&) - -let andpd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPand 16 - -let andps ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPand 16 - -let arpl ins insAddr insLen ctxt = - if is64bit ctxt then raise InvalidOn64Exception - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins |> transTwoOprs ins insAddr insLen ctxt - let t1, t2 = tmpVars2 16 - let mask = numI32 0xfffc 16 - let zF = getRegVar ctxt R.ZF - startMark insAddr insLen builder - builder ) - builder ) - builder - let dst1, dst2 = transOprToExpr128 ins insAddr insLen ctxt dst - let src = transOprToExpr ins insAddr insLen ctxt src - builder src |> zExt 64) - builder src |> zExt 64) - | OprMem _, OprReg _ -> - let src1, src2 = transOprToExpr128 ins insAddr insLen ctxt src - let dst = transOprToExpr ins insAddr insLen ctxt dst - builder dst := extractLow 32 src1) - builder dst := extractLow 32 src2) - | _ -> raise InvalidOperandException - endMark insAddr insLen builder - -let bsf ins insAddr insLen ctxt = - let builder = new StmtBuilder (32) - let lblL0 = lblSymbol "L0" - let lblL1 = lblSymbol "L1" - let lblEnd = lblSymbol "End" - let lblLoopCond = lblSymbol "LoopCond" - let lblLoopEnd = lblSymbol "LoopEnd" - let lblLoop = lblSymbol "Loop" - let dst, src = getTwoOprs ins |> transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let cond = src == num0 oprSize - let t = tmpVar oprSize - startMark insAddr insLen builder - builder (src >> t)) == b0, Name lblLoop, Name lblLoopEnd)) - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let cond = src == num0 oprSize - let t = tmpVar oprSize - startMark insAddr insLen builder - builder (src >> t)) == b0, Name lblLoop, Name lblLoopE)) - builder transOneOpr ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t = tmpVar oprSize - let cnt = RegType.toByteWidth oprSize |> int - let tmps = Array.init cnt (fun _ -> tmpVar 8) - let builder = new StmtBuilder (2 * cnt) - startMark insAddr insLen builder - builder (i * 8)) - done - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let setValue = zExt oprSize setValue - startMark insAddr insLen builder - builder not) -let btr ins insAddr insLen ctxt = bitTest ins insAddr insLen ctxt b0 -let bts ins insAddr insLen ctxt = bitTest ins insAddr insLen ctxt b1 - -let call ins insAddr insLen ctxt isFar = - let builder = new StmtBuilder (4) - match isFar with - | false -> - let pc = getInstrPtr ctxt - let target = tmpVar ctxt.WordBitSize - let oprSize = getOperationSize ins - startMark insAddr insLen builder - builder transOneOpr ins insAddr insLen ctxt) - let r = (bvOfBaseAddr insAddr ctxt .+ bvOfInstrLen insLen ctxt) - auxPush oprSize ctxt r builder - builder sideEffects insAddr insLen UnsupportedFAR - -let convBWQ ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let oprSize = getOperationSize ins - let opr = getRegVar ctxt (if is64bit ctxt then R.RAX else R.EAX) - startMark insAddr insLen builder - match oprSize with - | 16 -> - builder opr := sExt 16 (extractLow 8 opr)) - | 32 -> - builder opr := sExt 32 (extractLow 16 opr)) - | 64 -> - builder (extractLow 32 opr)) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let clearFlag insAddr insLen ctxt flagReg = - let builder = new StmtBuilder (4) - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let s1 = tmpVar oprSize - let r, ext = tmpVars2 oprSize - startMark insAddr insLen builder - builder 52 == num (BitVector.unsignedMax 11)) - .& (extractLow 52 expr != num0 52) - let cmpCond c expr1 expr2 = - builder ) (expr1 == expr2) c) - builder ) (flt expr1 expr2) c) - builder ) (fle expr1 expr2) c) - builder ) (isNan expr1 .| isNan expr2) c) - builder ) (expr1 != expr2) c) - builder ) (flt expr1 expr2 |> not) c) - builder ) (fle expr1 expr2 |> not) c) - builder ) (isNan expr1 .| isNan expr2 |> not) c) - let cond1, cond2 = tmpVars2 1 - startMark insAddr insLen builder - cmpCond cond1 dst1 src1 - cmpCond cond2 dst2 src2 - builder |> num) (num0 64)) - builder |> num) (num0 64)) - endMark insAddr insLen builder - -let cmpps ins insAddr insLen ctxt = - let builder = new StmtBuilder (64) - let op1, op2, op3 = getThreeOprs ins - let dst1, dst2 = transOprToExpr128 ins insAddr insLen ctxt op1 - let src1, src2 = transOprToExpr128 ins insAddr insLen ctxt op2 - let dst1A, dst1B = extractLow 32 dst1, extractHigh 32 dst1 - let dst2A, dst2B = extractLow 32 dst2, extractHigh 32 dst2 - let imm = transOprToExpr ins insAddr insLen ctxt op3 - let isNan expr = - (extract expr 8 23 == num (BitVector.unsignedMax 8)) - .& (extractLow 23 expr != num0 23) - let cmpCond c expr1 expr2 = - builder ) (expr1 == expr2) c) - builder ) (flt expr1 expr2) c) - builder ) (fle expr1 expr2) c) - builder ) (isNan expr1 .| isNan expr2) c) - builder ) (expr1 != expr2) c) - builder ) (flt expr1 expr2 |> not) c) - builder ) (fle expr1 expr2 |> not) c) - builder ) (isNan expr1 .| isNan expr2 |> not) c) - let cond1, cond2, cond3, cond4 = tmpVars4 1 - startMark insAddr insLen builder - cmpCond cond1 dst1A (extractLow 32 src1) - cmpCond cond2 dst1B (extractHigh 32 src1) - cmpCond cond3 dst2A (extractLow 32 src2) - cmpCond cond4 dst2B (extractHigh 32 src2) - builder |> num) (num0 32)) - builder |> num) (num0 32)) - builder |> num) (num0 32)) - builder |> num) (num0 32)) - endMark insAddr insLen builder - -let cmps ins insAddr insLen ctxt = - let builder = new StmtBuilder (32) - startMark insAddr insLen builder - let pref = ins.Prefixes - let body () = - let oprSize = getOperationSize ins - let df = getRegVar ctxt R.DF - let si = getRegVar ctxt (if is64bit ctxt then R.RSI else R.ESI) - let di = getRegVar ctxt (if is64bit ctxt then R.RDI else R.EDI) - let src1 = loadLE oprSize si - let src2 = loadLE oprSize di - let t1, t2, t3 = tmpVars3 oprSize - builder cmps ins insAddr insLen ctxt - | ThreeOperands (dst, src, imm) -> - let builder = new StmtBuilder (16) - let dst = transOprToExpr64 ins insAddr insLen ctxt dst - let src = transOprToExpr64 ins insAddr insLen ctxt src - let imm = transOprToExpr ins insAddr insLen ctxt imm |> extractLow 8 - let n num = numI32 num 8 - let max64 = maxNum 64 |> num - let isNan expr = - (extract expr 11 52 == num (BitVector.unsignedMax 11)) - .& (extractLow 52 expr != num0 52) - let cond = tmpVar 1 - startMark insAddr insLen builder - builder not) cond) - builder not) cond) - builder not) cond) - builder )) - endMark insAddr insLen builder - | _ -> raise InvalidOperandException - -let cmpss ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let dst, src, imm = getThreeOprs ins - let dst = transOprToExpr32 ins insAddr insLen ctxt dst - let src = transOprToExpr32 ins insAddr insLen ctxt src - let imm = transOprToExpr ins insAddr insLen ctxt imm |> extractLow 8 - let n num = numI32 num 8 - let max32 = maxNum 32 |> num - let isNan expr = - (extract expr 8 23 == num (BitVector.unsignedMax 8)) - .& (extractLow 23 expr != num0 23) - let cond = tmpVar 1 - startMark insAddr insLen builder - builder not) cond) - builder not) cond) - builder not) cond) - builder )) - endMark insAddr insLen builder - -let cmpxchg ins insAddr insLen ctxt = - let builder = new StmtBuilder (32) - let dst, src = getTwoOprs ins |> transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - startMark insAddr insLen builder - if hasLock ins.Prefixes then builder - builder r) - builder 52 == num (BitVector.unsignedMax 11)) - .& (extractLow 52 expr != num0 52) - builder 23 == num (BitVector.unsignedMax 8)) - .& (extractLow 23 expr != num0 23) - builder - startMark insAddr insLen builder - match oprSize with - | 64 -> - let dst = transOneOpr ins insAddr insLen ctxt dst - let edx = getRegOfSize ctxt 32 GrpEDX - let eax = getRegOfSize ctxt 32 GrpEAX - let ecx = getRegOfSize ctxt 32 GrpECX - let ebx = getRegOfSize ctxt 32 GrpEBX - let t = tmpVar oprSize - builder 0)) - builder 32)) - builder -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let rdx = getRegOfSize ctxt 64 GrpEDX - let rax = getRegOfSize ctxt 64 GrpEAX - let rcx = getRegOfSize ctxt 64 GrpECX - let rbx = getRegOfSize ctxt 64 GrpEBX - builder raise InvalidOperandSizeException - endMark insAddr insLen builder - -let convWDQ ins insAddr insLen (ctxt: TranslationContext) = - let builder = new StmtBuilder (8) - let oprSize = getOperationSize ins - startMark insAddr insLen builder - match oprSize, ctxt.WordBitSize with - | 16, _ -> - let t = tmpVar 32 - let ax = getRegVar ctxt R.AX - let dx = getRegVar ctxt R.DX - builder ax) - builder t) - builder t) - | 32, _ -> - let t = tmpVar 64 - let eax = getRegVar ctxt R.EAX - let edx = getRegVar ctxt R.EDX - builder eax) - builder t) - builder t) - | 64, 64 -> - let t = tmpVar 128 - let rdx = getRegVar ctxt R.RDX - let rax = getRegVar ctxt R.RAX - builder rax) - builder t) - builder t) - | _, _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let cvtdq2pd ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src = transOprToExpr64 ins insAddr insLen ctxt src - let tmp1, tmp2 = tmpVars2 32 - startMark insAddr insLen builder - builder src) - builder src) - builder tmp1) - builder tmp2) - endMark insAddr insLen builder - -let cvtdq2ps ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let dst, src = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insAddr insLen ctxt src - let tmp1, tmp2, tmp3, tmp4 = tmpVars4 32 - startMark insAddr insLen builder - builder src1) - builder src1) - builder src2) - builder src2) - builder dst1 := cast CastKind.IntToFloat 32 tmp1) - builder dst1 := cast CastKind.IntToFloat 32 tmp2) - builder dst2 := cast CastKind.IntToFloat 32 tmp3) - builder dst2 := cast CastKind.IntToFloat 32 tmp4) - endMark insAddr insLen builder - -let cvtpd2dq ins insAddr insLen ctxt rounded = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insAddr insLen ctxt src - let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc - startMark insAddr insLen builder - builder dst1 := cast castKind 32 src1) - builder dst1 := cast castKind 32 src2) - builder ) - endMark insAddr insLen builder - -let cvtpd2pi ins insAddr insLen ctxt rounded = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let dst = transOprToExpr ins insAddr insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insAddr insLen ctxt src - let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc - startMark insAddr insLen builder - builder dst := cast castKind 32 src1) - builder dst := cast castKind 32 src2) - endMark insAddr insLen builder - -let cvtpd2ps ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insAddr insLen ctxt src - startMark insAddr insLen builder - builder dst1 := cast CastKind.FloatExt 32 src1) - builder dst1 := cast CastKind.FloatExt 32 src2) - builder ) - endMark insAddr insLen builder - -let cvtpi2pd ins insAddr insLen ctxt = cvtdq2pd ins insAddr insLen ctxt - -let cvtpi2ps ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - let dst = transOprToExpr64 ins insAddr insLen ctxt dst - let src = transOprToExpr64 ins insAddr insLen ctxt src - let tmp2, tmp1 = tmpVars2 32 - startMark insAddr insLen builder - builder src) - builder src) - builder dst := cast CastKind.IntToFloat 32 tmp1) - builder dst := cast CastKind.IntToFloat 32 tmp2) - endMark insAddr insLen builder - -let cvtps2dq ins insAddr insLen ctxt rounded = - let builder = new StmtBuilder (16) - let dst, src = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insAddr insLen ctxt src - let tmp1, tmp2, tmp3, tmp4 = tmpVars4 32 - let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc - startMark insAddr insLen builder - builder src1) - builder src1) - builder src2) - builder src2) - builder dst1 := cast castKind 32 tmp1) - builder dst1 := cast castKind 32 tmp2) - builder dst2 := cast castKind 32 tmp3) - builder dst2 := cast castKind 32 tmp4) - endMark insAddr insLen builder - -let cvtps2pd ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src = transOprToExpr64 ins insAddr insLen ctxt src - let tmp1, tmp2 = tmpVars2 32 - startMark insAddr insLen builder - builder src) - builder src) - builder tmp1) - builder tmp2) - endMark insAddr insLen builder - -let cvtps2pi ins insAddr insLen ctxt rounded = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - let dst = transOprToExpr ins insAddr insLen ctxt dst - let src = transOprToExpr64 ins insAddr insLen ctxt src - let tmp1, tmp2 = tmpVars2 32 - let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc - startMark insAddr insLen builder - builder src) - builder src) - builder dst := cast castKind 32 tmp1) - builder dst := cast castKind 32 tmp2) - endMark insAddr insLen builder - -let cvtsd2si ins insAddr insLen ctxt rounded = - let builder = new StmtBuilder (8) - let oprSize = getOperationSize ins - let dst, src = getTwoOprs ins - let dst = transOprToExpr ins insAddr insLen ctxt dst - let src = transOprToExpr64 ins insAddr insLen ctxt src - let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc - let tmp = tmpVar 32 - startMark insAddr insLen builder - if is64bit ctxt && oprSize = 64 then - builder src) - else - builder src) - builder dst tmp - endMark insAddr insLen builder - -let cvtsd2ss ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let dst = transOprToExpr64 ins insAddr insLen ctxt dst - let src = transOprToExpr64 ins insAddr insLen ctxt src - startMark insAddr insLen builder - builder dst := cast CastKind.FloatExt 32 src) - endMark insAddr insLen builder - -let cvtsi2sd ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let dst = transOprToExpr64 ins insAddr insLen ctxt dst - let src = transOprToExpr ins insAddr insLen ctxt src - startMark insAddr insLen builder - builder src) - endMark insAddr insLen builder - -let cvtsi2ss ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let dst = transOprToExpr64 ins insAddr insLen ctxt dst - let src = transOprToExpr ins insAddr insLen ctxt src - startMark insAddr insLen builder - builder dst := cast CastKind.IntToFloat 32 src) - endMark insAddr insLen builder - -let cvtss2sd ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let dst = transOprToExpr64 ins insAddr insLen ctxt dst - let src = transOprToExpr32 ins insAddr insLen ctxt src - startMark insAddr insLen builder - builder src) - endMark insAddr insLen builder - -let cvtss2si ins insAddr insLen ctxt rounded = - let builder = new StmtBuilder (4) - let oprSize = getOperationSize ins - let dst, src = getTwoOprs ins - let dst = transOprToExpr ins insAddr insLen ctxt dst - let src = transOprToExpr32 ins insAddr insLen ctxt src - let tmp = tmpVar 32 - let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc - startMark insAddr insLen builder - if is64bit ctxt && oprSize = 64 then - builder src) - else - builder src) - builder dst tmp) - endMark insAddr insLen builder - -let daa ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let oprSize = getOperationSize ins - let al = getRegVar ctxt R.AL - let cf = getRegVar ctxt R.CF - let af = getRegVar ctxt R.AF - let oldAl = tmpVar 8 - let oldCf = tmpVar 1 - let alAnd0f = al .& numI32 0x0f 8 - let subCond1 = gt alAnd0f (numI32 9 8) - let subCond2 = af == b1 - let cond1 = tmpVar 1 - let subCond3 = gt oldAl (numI32 0x99 8) - let subCond4 = oldCf == b1 - let cond2 = tmpVar 1 - startMark insAddr insLen builder - if oprSize = 64 then () - else - builder ) al) - builder ) al) - builder builder - builder - let oldCf = tmpVar 1 - let alAnd0f = al .& numI32 0x0f 8 - let subCond1 = gt alAnd0f (numI32 9 8) - let subCond2 = af == b1 - let cond1 = tmpVar 1 - let subCond3 = gt oldAl (numI32 0x99 8) - let subCond4 = oldCf == b1 - let cond2 = tmpVar 1 - startMark insAddr insLen builder - if oprSize = 64 then () - else - builder ) al) - builder ) al) - builder builder - builder transOneOpr ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t1, t2, t3 = tmpVars3 oprSize - startMark insAddr insLen builder - builder "Divide Error" - let divisor = getOneOpr ins |> transOneOpr ins insAddr insLen ctxt - let oprSize = getOperationSize ins - startMark insAddr insLen builder - builder q - let negRes = lt q (zExt sz mask) - let posRes = gt q (zExt sz (mask .- (num1 oprSize))) - let cond = ite (msb == b1) negRes posRes - CJmp (cond, errExp, Name lblAssign) - match ins.Opcode with - | Opcode.DIV -> let divisor = zExt sz divisor - builder let divisor = sExt sz divisor - builder raise InvalidOpcodeException - builder -> - builder | 32 | 64 -> - let q = getRegOfSize ctxt oprSize GrpEAX - let r = getRegOfSize ctxt oprSize GrpEDX - builder raise InvalidOperandSizeException - allEFLAGSUndefined ctxt builder - endMark insAddr insLen builder - -let emms _ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - startMark insAddr insLen builder - builder |> num) - endMark insAddr insLen builder - -let enter ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let imm16, imm8 = getTwoOprs ins |> transTwoOprs ins insAddr insLen ctxt - let oSz = getOperationSize ins - let allocSize, nestingLevel, cnt = tmpVars3 oSz - let frameTemp, addrSize = tmpVars2 ctxt.WordBitSize - let bp = getBasePtr ctxt - let sp = getStackPtr ctxt - let lblLoop = lblSymbol "Loop" - let lblCont = lblSymbol "Continue" - let lblLevelCheck = lblSymbol "NestingLevelCheck" - let lblLv1 = lblSymbol "NestingLevel1" - let getAddrSize bitSize = - if bitSize = 64 then numI32 8 bitSize else numI32 4 bitSize - startMark insAddr insLen builder - builder reg - | Load (_, _, BinOp (_, _, e, _, _, _), _, _) -> e - | Load (_, _, expr, _, _) -> expr - | _ -> failwith "Invalid memory" - -let updateAddrByOffset addr offset = - match addr with - (* Save *) - | Load (_, _, BinOp (_, _, BinOp (_, _, reg, _, _, _), _, _, _), _, _) -> - reg := reg .+ offset (* SIB *) - | Load (_, _, BinOp (_, _, e, _, _, _), _, _) -> - e := e .+ offset (* Displacemnt *) - | Load (_, _, expr, _, _) -> expr := expr .+ offset - | _ -> failwith "Invalid memory" - -let extendAddr src regType = - match src with - | Load (e, _, expr, _, _) -> AST.load e regType expr - | _ -> failwith "Invalid memory" - -let getAddrRegSize = function - (* Save *) - | Load (_, _, Var (t, _, _, _), _, _) -> t - | Load (_, _, BinOp (_, t, _, _, _, _), _, _) -> t - (* Load *) - | TempVar (t, _) -> t - | _ -> failwith "Invalid memory" - -let saveFxsaveMMX addr offset grv builder = - let r64 = num0 64 - let mRegs = [ r64; grv R.MM0; r64; grv R.MM1; r64; grv R.MM2; r64; grv R.MM3; - r64; grv R.MM4; r64; grv R.MM5; r64; grv R.MM6; r64; grv R.MM7 ] - List.iter (fun reg -> builder builder let r2, r1 = pv r in r1 :: (r2 :: acc)) [] xRegs - List.iter (fun reg -> builder let r2, r1 = pv r in r1 :: (r2 :: acc)) [] xRegs - List.iter (fun reg -> builder - let num3 = numI32 3 2 - let v r = getRegVar ctxt r - let t0, t1, t2, t3 = tmpVars4 1 - let t4, t5, t6, t7 = tmpVars4 1 - let abrTagW = tmpVar 8 - let offset = num (BitVector.ofInt32 8 (getAddrRegSize dst)) - let regSave = tmpVar (getAddrRegSize dst) - let baseReg = getBaseReg dst - let xRegs = - [ R.XMM0; R.XMM1; R.XMM2; R.XMM3; R.XMM4; R.XMM5; R.XMM6; R.XMM7; - R.XMM8; R.XMM9; R.XMM10; R.XMM11; R.XMM12; R.XMM13; R.XMM14; R.XMM15 ] - builder - let reserved16 = num0 16 - let num3 = numI32 3 2 - let v r = getRegVar ctxt r - let t0, t1, t2, t3 = tmpVars4 1 - let t4, t5, t6, t7 = tmpVars4 1 - let abrTagW = tmpVar 8 - let offset = num (BitVector.ofInt32 8 (getAddrRegSize dst)) - let regSave = tmpVar (getAddrRegSize dst) - let baseReg = getBaseReg dst - let xRegs = - [ R.XMM0; R.XMM1; R.XMM2; R.XMM3; R.XMM4; R.XMM5; R.XMM6; R.XMM7; - R.XMM8; R.XMM9; R.XMM10; R.XMM11; R.XMM12; R.XMM13; R.XMM14; R.XMM15 ] - builder (v R.FIP)) - (concat (v R.FCS) reserved16)) - builder (v R.FDP)) - (concat (v R.FDS) reserved16)) - builder - let reserved16 = num0 16 - let num3 = numI32 3 2 - let v r = getRegVar ctxt r - let t0, t1, t2, t3 = tmpVars4 1 - let t4, t5, t6, t7 = tmpVars4 1 - let abrTagW = tmpVar 8 - let offset = num (BitVector.ofInt32 8 (getAddrRegSize dst)) - let regSave = tmpVar (getAddrRegSize dst) - let baseReg = getBaseReg dst - let xRegs = [ R.XMM0; R.XMM1; R.XMM2; R.XMM3; R.XMM4; R.XMM5; R.XMM6; R.XMM7 ] - builder (v R.FIP)) (concat (v R.FCS) reserved16)) - builder (v R.FDP)) - (concat (v R.FDS) reserved16)) - builder - builder tSrc) - builder 16) - builder 32) - builder 48) - builder tSrc) - builder tSrc) - loadFxrstorMMX src grv builder - loadFxrstorXMM ctxt src xRegs builder - -let load64BitDefaultFxrstor ctxt src builder = - let grv r = getRegVar ctxt r - let offset = num (BitVector.ofInt32 8 (getAddrRegSize src)) - let regSave = tmpVar (getAddrRegSize src) - let baseReg = getBaseReg src - let t0, t1, t2, t3 = tmpVars4 2 - let t4, t5, t6, t7 = tmpVars4 2 - let tmp8 = tmpVar 8 - let zero2 = num0 2 - let three2 = numI32 3 2 - let xRegs = - [ R.XMM0; R.XMM1; R.XMM2; R.XMM3; R.XMM4; R.XMM5; R.XMM6; R.XMM7; - R.XMM8; R.XMM9; R.XMM10; R.XMM11; R.XMM12; R.XMM13; R.XMM14; R.XMM15 ] - builder 32) - builder tmp8) zero2 three2) - builder 1) zero2 three2) - builder 2) zero2 three2) - builder 3) zero2 three2) - builder 4) zero2 three2) - builder 5) zero2 three2) - builder 6) zero2 three2) - builder 7) zero2 three2) - builder src) - builder 16) - builder 48) - builder (grv R.FIP) := extractLow 32 src) - builder 32) - builder (grv R.FDP) := extractLow 32 src) - builder 32) - builder src) - builder src) - loadFxrstorMMX src grv builder - loadFxrstorXMM ctxt src (List.rev xRegs) builder - builder - builder tSrc) - builder 16) - builder 32) - builder 48) - builder (grv R.FIP) := extractLow 32 tSrc) - builder 32) - builder (grv R.FDP) := extractLow 32 tSrc) - builder 32) - builder tSrc) - builder tSrc) - loadFxrstorMMX src grv builder - loadFxrstorXMM ctxt src xRegs builder - -let fpuFBinOp ins insAddr insLen ctxt binOp doPop leftToRight = - let builder = new StmtBuilder (64) - let res = tmpVar 80 - startMark insAddr insLen builder - match ins.Operands with - | NoOperand -> - let st0 = fpuRegValue ctxt R.ST0 - let st1 = fpuRegValue ctxt R.ST1 - if leftToRight then builder - let oprExpr = transOprToFloat80 ins insAddr insLen ctxt opr - let st0 = fpuRegValue ctxt R.ST0 - if leftToRight then builder - let oprExpr1 = getRegVar ctxt reg1 - let oprExpr2 = transOprToExpr ins insAddr insLen ctxt opr2 - if leftToRight then builder raise InvalidOperandException - if doPop then popFPUStack ctxt builder else () - endMark insAddr insLen builder - -let fpuIntOp ins insAddr insLen ctxt binOp leftToRight = - let builder = new StmtBuilder (8) - let st0 = fpuRegValue ctxt R.ST0 - let oprExpr = getOneOpr ins |> transOprToExpr ins insAddr insLen ctxt - let tmp = tmpVar 80 - startMark insAddr insLen builder - builder oprExpr) - if leftToRight then builder 15 := b1) - builder src) st0a) - builder src) st0b) - builder |> cast CastKind.IntToFloat 80 - let flt2 = numI32 2 32 |> cast CastKind.IntToFloat 80 - let tmp = tmpVar 80 - startMark insAddr insLen builder - builder transOprToExpr ins insAddr insLen ctxt - let sign = extractHigh 1 src - let intgr = tmpVar 64 - let bcdNum = tmpVar 72 - let tmp = tmpVar 80 - startMark insAddr insLen builder - bcdToInt intgr bcdNum builder - builder intgr := sign) - builder intgr) - checkFPUOnLoad ctxt builder - shiftFPUStackDown ctxt builder - assignFPUReg R.ST0 tmp ctxt builder - updateTagWordOnLoad ctxt builder - endMark insAddr insLen builder - -let fbstp ins insAddr insLen ctxt = - let builder = new StmtBuilder (64) - let dst = getOneOpr ins |> transOprToExpr ins insAddr insLen ctxt - let st0 = fpuRegValue ctxt R.ST0 - let sign = extractHigh 1 st0 - let intgr = tmpVar 64 - let bcdNum = tmpVar 72 - let tmp = tmpVar 80 - startMark insAddr insLen builder - builder st0) - intTobcd bcdNum intgr builder - builder ) - builder tmp := sign) - builder tmp := bcdNum) - builder fcmov ins insAddr insLen ctxt - -let fcmove ins insAddr insLen ctxt = - getRegVar ctxt R.ZF |> fcmov ins insAddr insLen ctxt - -let fcmovbe ins insAddr insLen ctxt = - (getRegVar ctxt R.CF .| getRegVar ctxt R.ZF) |> fcmov ins insAddr insLen ctxt - -let fcmovu ins insAddr insLen ctxt = - getRegVar ctxt R.PF |> fcmov ins insAddr insLen ctxt - -let fcmovnb ins insAddr insLen ctxt = - getRegVar ctxt R.CF |> not |> fcmov ins insAddr insLen ctxt - -let fcmovne ins insAddr insLen ctxt = - getRegVar ctxt R.ZF |> not |> fcmov ins insAddr insLen ctxt - -let fcmovnbe ins insAddr insLen ctxt = - let cond1 = getRegVar ctxt R.CF |> not - let cond2 = getRegVar ctxt R.ZF |> not - cond1 .& cond2 |> fcmov ins insAddr insLen ctxt - -let fcmovnu ins insAddr insLen ctxt = - getRegVar ctxt R.PF |> not |> fcmov ins insAddr insLen ctxt - -let fchs _ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let st0b, _st0a = getFPUPseudoRegVars ctxt R.ST0 - let tmp = tmpVar 1 - startMark insAddr insLen builder - builder st0b) - builder st0b := not tmp) - builder stsWrd := num0 7) - builder stsWrd := b0) - builder extractLow 1 - let tmp1, tmp2 = tmpVars2 80 - startMark insAddr insLen builder - match ins.Operands with - | NoOperand -> - builder - let oprExpr = transOprToFloat80 ins insAddr insLen ctxt opr - builder raise InvalidOperandException - builder 64 == num (BitVector.unsignedMax 15)) - .& (extractLow 62 expr != num0 62) - let cond = - if unordered then - let tmp1qNanCond = isNan tmp1 .& (extract tmp1 1 62 == b1) - let tmp2qNanCond = isNan tmp2 .& (extract tmp2 1 62 == b1) - tmp1qNanCond .| tmp2qNanCond .& (im == b0) - else isNan tmp1 .| isNan tmp2 .& (im == b0) - builder 0 then popFPUStack ctxt builder else () - if nPop = 2 then popFPUStack ctxt builder else () - endMark insAddr insLen builder - -let fcomi ins insAddr insLen ctxt doPop = - let builder = new StmtBuilder (64) - let opr1, opr2 = getTwoOprs ins - let opr1 = transOprToExpr ins insAddr insLen ctxt opr1 - let opr2 = transOprToExpr ins insAddr insLen ctxt opr2 - let im = getRegVar ctxt R.FCW |> extractLow 1 - let lblQNan = lblSymbol "IsQNan" - let lblNan = lblSymbol "IsNan" - let lblExit = lblSymbol "Exit" - let lblCond = lblSymbol "IsNanCond" - let zf = getRegVar ctxt R.ZF - let pf = getRegVar ctxt R.PF - let cf = getRegVar ctxt R.CF - startMark insAddr insLen builder - builder 64 == num (BitVector.unsignedMax 15)) - .& (extractLow 62 opr1 != num0 62) - let opr2NanCond = - (extract opr2 15 64 == num (BitVector.unsignedMax 15)) - .& (extractLow 62 opr2 != num0 62) - let cond = opr1NanCond .| opr2NanCond .& (im == b0) - match ins.Opcode with - | Opcode.FCOMI | Opcode.FCOMIP -> - builder - let opr1qNanCond = opr1NanCond .& (extract opr1 1 62 == b1) - let opr2qNanCond = opr2NanCond .& (extract opr2 1 62 == b1) - builder raise InvalidOpcodeException - builder - let float80SignUnmask = BitVector.signedMax 80 |> num - let maxLimit = numI64 (1L <<< 63) 64 - let maxFloat = cast CastKind.IntToFloat 80 maxLimit - let num3 = BitVector.ofInt32 3 2 |> num - let c0 = getRegVar ctxt R.FSWC0 - let c1 = getRegVar ctxt R.FSWC1 - let c2 = getRegVar ctxt R.FSWC2 - let c3 = getRegVar ctxt R.FSWC3 - let lblOutOfRange = lblSymbol "IsOutOfRange" - let lblInRange = lblSymbol "IsInRange" - let tmp = tmpVar 80 - startMark insAddr insLen builder - builder ) - builder - let value3 = BitVector.ofInt32 3 16 |> num - let offset = - match getOneOpr ins with - | OprReg R.ST0 -> BitVector.ofInt32 0 16 |> num - | OprReg R.ST1 -> BitVector.ofInt32 1 16 |> num - | OprReg R.ST2 -> BitVector.ofInt32 2 16 |> num - | OprReg R.ST3 -> BitVector.ofInt32 3 16 |> num - | OprReg R.ST4 -> BitVector.ofInt32 4 16 |> num - | OprReg R.ST5 -> BitVector.ofInt32 5 16 |> num - | OprReg R.ST6 -> BitVector.ofInt32 6 16 |> num - | OprReg R.ST7 -> BitVector.ofInt32 7 16 |> num - | _ -> raise InvalidOperandException - startMark insAddr insLen builder - builder top) - builder |> num) .* top16) - builder transOprToExpr ins insAddr insLen ctxt - let st0 = fpuRegValue ctxt R.ST0 - let tmp = tmpVar 80 - startMark insAddr insLen builder - builder oprExpr) - builder transOprToExpr ins insAddr insLen ctxt - let tmp = tmpVar 80 - startMark insAddr insLen builder - builder oprExpr) - checkFPUOnLoad ctxt builder - shiftFPUStackDown ctxt builder - assignFPUReg R.ST0 tmp ctxt builder - updateTagWordOnLoad ctxt builder - endMark insAddr insLen builder - -let fimul ins insAddr insLen ctxt = - fpuIntOp ins insAddr insLen ctxt fmul true - -let fincstp _ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let top = getRegVar ctxt R.FTOP - startMark insAddr insLen builder - builder ) - builder |> num - let tw = BitVector.maxNum16 |> num - builder ) - builder transOprToExpr ins insAddr insLen ctxt - let sz = AST.typeOf oprExpr - let st0 = fpuRegValue ctxt R.ST0 - let tmp1 = tmpVar sz - let tmp2 = tmpVar 2 - let num2 = numI32 2 2 - let cstK castKind = cast castKind sz st0 - startMark insAddr insLen builder - builder 10) - builder ) - (cstK CastKind.FtoIRound) (cstK CastKind.FtoITrunc)) - builder ) (cstK CastKind.FtoIFloor) tmp1) - builder transOprToExpr ins insAddr insLen ctxt - let sz = AST.typeOf oprExpr - let st0 = fpuRegValue ctxt R.ST0 - startMark insAddr insLen builder - builder transOprToExpr ins insAddr insLen ctxt - startMark insAddr insLen builder - builder transOprToExpr ins insAddr insLen ctxt - startMark insAddr insLen builder - builder - startMark insAddr insLen builder - builder |> num - let maxLimit = numI64 (1L <<< 63) 64 - let maxFloat = cast CastKind.IntToFloat 80 maxLimit - let num3 = BitVector.ofInt32 3 2 |> num - let c0 = getRegVar ctxt R.FSWC0 - let c1 = getRegVar ctxt R.FSWC1 - let c2 = getRegVar ctxt R.FSWC2 - let c3 = getRegVar ctxt R.FSWC3 - let lblOutOfRange = lblSymbol "IsOutOfRange" - let lblInRange = lblSymbol "IsInRange" - let tmp = tmpVar 80 - startMark insAddr insLen builder - builder ) - checkFPUOnLoad ctxt builder - shiftFPUStackDown ctxt builder - assignFPUReg R.ST0 tmp ctxt builder - updateTagWordOnLoad ctxt builder - endMark insAddr insLen builder - -let fisub ins insAddr insLen ctxt = - fpuIntOp ins insAddr insLen ctxt fsub true - -let fisubr ins insAddr insLen ctxt = - fpuIntOp ins insAddr insLen ctxt fsub false - -let fpumul ins insAddr insLen ctxt doPop = - fpuFBinOp ins insAddr insLen ctxt fmul doPop true - -let fprem _ins insAddr insLen ctxt round = - let builder = new StmtBuilder (32) - let st0 = fpuRegValue ctxt R.ST0 - let st1 = fpuRegValue ctxt R.ST1 - let caster = if round then CastKind.FtoIRound else CastKind.FtoITrunc - let lblLT64 = lblSymbol "ExpDiffInRange" - let lblGT64 = lblSymbol "ExpDiffOutOfRange" - let lblExit = lblSymbol "Exit" - let expDiff = tmpVar 15 - let tmp80A, tmp80B, tmpres = tmpVars3 80 - let tmp64 = tmpVar 64 - startMark insAddr insLen builder - builder 64 .- extract st1 15 64) - builder ), Name lblLT64, Name lblGT64)) - builder tmp80A) - builder tmp64)) - builder tmp64) - builder 1) - builder 2) - builder expDiff) .- numI32 63 64) - builder ) - builder tmp64) - builder tmp80A) - builder tmp64) - builder - let tmp1 = tmpVar 64 - let tmp2 = tmpVar 2 - let num2 = numI32 2 2 - let cstK castKind = cast castKind 64 st0 - startMark insAddr insLen builder - builder 10) - builder ) - (cstK CastKind.FtoIRound) (cstK CastKind.FtoITrunc)) - builder ) (cstK CastKind.FtoIFloor) tmp1) - builder tmp1) - assignFPUReg R.ST0 tmp ctxt builder - builder - let tmp3 = tmpVar 80 - let st0 = fpuRegValue ctxt R.ST0 - let st1 = fpuRegValue ctxt R.ST1 - startMark insAddr insLen builder - builder st1) - builder << tmp1) - builder tmp2) - builder |> num - let maxLimit = numI64 (1L <<< 63) 64 - let maxFloat = cast CastKind.IntToFloat 80 maxLimit - let num3 = BitVector.ofInt32 3 2 |> num - let lblOutOfRange = lblSymbol "IsOutOfRange" - let lblInRange = lblSymbol "IsInRange" - let tmp1, tmp2 = tmpVars2 80 - startMark insAddr insLen builder - builder assignFPUReg r tmp ctxt builder - | _ -> builder transOprToExpr ins insAddr insLen ctxt - startMark insAddr insLen builder - checkFPUExceptions ctxt builder - builder transOprToExpr ins insAddr insLen ctxt - startMark insAddr insLen builder - checkFPUExceptions ctxt builder - builder - let c0 = getRegVar ctxt R.FSWC0 - let c2 = getRegVar ctxt R.FSWC2 - let c3 = getRegVar ctxt R.FSWC3 - let lblNan = lblSymbol "IsNan" - let lblExit = lblSymbol "Exit" - startMark insAddr insLen builder - builder 64 - let st0NanCond = - (st0Exponent == num (BitVector.unsignedMax 15)) - .& (extractLow 62 st0 != num0 62) - builder - startMark insAddr insLen builder - builder - startMark insAddr insLen builder - builder oprExpr) - checkFPUOnLoad ctxt builder - shiftFPUStackDown ctxt builder - assignFPUReg R.ST0 tmp ctxt builder - updateTagWordOnLoad ctxt builder - endMark insAddr insLen builder - -let fld ins insAddr insLen ctxt = - let opr = getOneOpr ins - let oprExpr = transOprToExpr ins insAddr insLen ctxt opr - fpuLoad insAddr insLen ctxt oprExpr - -let fld1 _ins insAddr insLen ctxt = - let oprExpr = BitVector.ofUInt64 0x3FF0000000000000UL 64 |> num - fpuLoad insAddr insLen ctxt oprExpr - -let fldcw ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let oprExpr = getOneOpr ins |> transOprToExpr ins insAddr insLen ctxt - startMark insAddr insLen builder - builder |> num - fpuLoad insAddr insLen ctxt oprExpr - -let fldl2e _ins insAddr insLen ctxt = - let oprExpr = BitVector.ofUInt64 4599094494223104509UL 64 |> num - fpuLoad insAddr insLen ctxt oprExpr - -let fldpi _ins insAddr insLen ctxt = - let oprExpr = BitVector.ofUInt64 4614256656552045848UL 64 |> num - fpuLoad insAddr insLen ctxt oprExpr - -let fldlg2 _ins insAddr insLen ctxt = - let oprExpr = BitVector.ofUInt64 4599094494223104511UL 64 |> num - fpuLoad insAddr insLen ctxt oprExpr - -let fldln2 _ins insAddr insLen ctxt = - let oprExpr = BitVector.ofUInt64 4604418534313441775UL 64 |> num - fpuLoad insAddr insLen ctxt oprExpr - -let fldz _ins insAddr insLen ctxt = - let oprExpr = num0 64 - fpuLoad insAddr insLen ctxt oprExpr - -let m14Stenv dst ctxt builder = - let v r = getRegVar ctxt r - let tmp = tmpVar 112 - builder ) - builder tmp := concat (v R.FCW) - (concat (v R.FSW) (v R.FTW))) - builder 48 := extractLow 16 (v R.FIP)) - builder 64 := extractLow 11 (v R.FOP)) - builder 76 := extract (v R.FIP) 4 16) - builder 80 := extractLow 16 (v R.FDP)) - builder tmp := extract (v R.FDP) 4 16) - builder - builder tmp) - builder 16) - builder 32) - builder (v R.FIP) := extract tmp 16 48) - builder (v R.FOP) := extract tmp 11 64) - builder 16 := extract tmp 4 76) - builder (v R.FDP) := extract tmp 16 80) - builder 16 := extractHigh 4 tmp) - -let m28fldenv src ctxt builder = - let v r = getRegVar ctxt r - let tmp = tmpVar 224 - builder tmp) - builder 32) - builder 64) - builder (v R.FIP) := extract tmp 16 96) - builder (v R.FOP) := extract tmp 11 128) - builder 16 := extract tmp 16 139) - builder (v R.FDP) := extract tmp 16 160) - builder 16 := extract tmp 16 204) - -let m28fstenv dst ctxt builder = - let v r = getRegVar ctxt r - let tmp = tmpVar 224 - builder ) - builder tmp := v R.FCW) - builder 32 := v R.FSW) - builder 64 := v R.FTW) - builder 96 := extractLow 16 (v R.FIP)) - builder 128 := extractLow 11 (v R.FOP)) - builder 139 := extract (v R.FIP) 16 16) - builder 160 := extractLow 16 (v R.FDP)) - builder 204 := extract (v R.FDP) 16 16) - builder src) ctxt builder - assignFPUReg R.ST1 (extract src 80 80) ctxt builder - assignFPUReg R.ST2 (extract src 80 160) ctxt builder - assignFPUReg R.ST3 (extract src 80 240) ctxt builder - assignFPUReg R.ST4 (extract src 80 320) ctxt builder - assignFPUReg R.ST5 (extract src 80 400) ctxt builder - assignFPUReg R.ST6 (extract src 80 480) ctxt builder - assignFPUReg R.ST7 (extract src 80 560) ctxt builder - -let stSts dst ctxt builder = - let v r = getRegVar ctxt r - builder dst := v R.ST0) - builder 80 := v R.ST1) - builder 160 := v R.ST2) - builder 240 := v R.ST3) - builder 320 := v R.ST4) - builder 400 := v R.ST5) - builder 480 := v R.ST6) - builder 560 := v R.ST7) - -let fldenv ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let src = getOneOpr ins |> transOprToExpr ins insAddr insLen ctxt - startMark insAddr insLen builder - match AST.typeOf src with - | 112 -> m14fldenv src ctxt builder - | 224 -> m28fldenv src ctxt builder - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let frstor ins insAddr insLen ctxt = - let builder = new StmtBuilder (32) - let src = getOneOpr ins |> transOprToExpr ins insAddr insLen ctxt - startMark insAddr insLen builder - match AST.typeOf src with - | 752 -> - m14fldenv (extractLow 112 src) ctxt builder - | 864 -> - m28fldenv (extractLow 224 src) ctxt builder - | _ -> raise InvalidOperandSizeException - ldSts (extractHigh 640 src) ctxt builder - endMark insAddr insLen builder - -let fsave ins insAddr insLen ctxt = - let builder = new StmtBuilder (32) - let dst = getOneOpr ins |> transOprToExpr ins insAddr insLen ctxt - let v r = getRegVar ctxt r - startMark insAddr insLen builder - m14Stenv (extractLow 112 dst) ctxt builder - stSts (extractHigh 640 dst) ctxt builder - builder ) - builder ) - builder ) - builder ) - builder ) - builder ) - endMark insAddr insLen builder - -let fstenv ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let dst = getOneOpr ins |> transOprToExpr ins insAddr insLen ctxt - startMark insAddr insLen builder - match AST.typeOf dst with - | 112 -> m14Stenv dst ctxt builder - | 224 -> m28fstenv dst ctxt builder - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let fxam _ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let st0 = fpuRegValue ctxt R.ST0 - let exponent = extract st0 15 64 - let maxExponent = BitVector.unsignedMax 15 |> num - let tag7 = getRegVar ctxt R.FTW7 - let nanCond = - (exponent == maxExponent) .& (extractLow 62 st0 != num0 62) - let c3Cond1 = (tag7 == numI32 3 2) .| (exponent == num0 15) - let c2Cond0 = (tag7 == numI32 3 2) .| (st0 == num0 80) .| nanCond - let c0Cond1 = (tag7 == numI32 3 2) .| (exponent == maxExponent) - startMark insAddr insLen builder - builder st0) - builder - let exponent = tmpVar 64 - let significand = tmpVar 80 - startMark insAddr insLen builder - builder ) - builder ) - builder significand := extractLow 64 st0) - builder significand := extractHigh 1 st0) - builder 64 := numI32 16383 15) - builder exponent := extract st0 15 64) - builder ) - builder exponent) - assignFPUReg R.ST0 tmp ctxt builder - checkFPUOnLoad ctxt builder - shiftFPUStackDown ctxt builder - assignFPUReg R.ST0 significand ctxt builder - updateTagWordOnLoad ctxt builder - checkC1Flag ctxt builder R.FTW7 - cflagsUndefined023 ctxt builder - endMark insAddr insLen builder - -let fyl2x _ins insAddr insLen ctxt = - let builder = new StmtBuilder (64) - let st0 = fpuRegValue ctxt R.ST0 - let st1 = fpuRegValue ctxt R.ST1 - let flt2 = numI32 2 32 |> cast CastKind.IntToFloat 80 - let tmp = tmpVar 80 - startMark insAddr insLen builder - builder |> cast CastKind.IntToFloat 80 - let f1 = numI32 1 32 |> cast CastKind.IntToFloat 80 - let tmp = tmpVar 80 - startMark insAddr insLen builder - builder transOneOpr ins insAddr insLen ctxt - let eSrc = extendAddr src 64 - startMark insAddr insLen builder - if ctxt.WordBitSize = 64 then - if hasREXW ins.REXPrefix then load64BitPromotedFxrstor ctxt eSrc builder - else load64BitDefaultFxrstor ctxt eSrc builder - else loadLegacyFxrstor ctxt eSrc builder - endMark insAddr insLen builder - -let fxch ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let tmp = tmpVar 80 - let st0 = fpuRegValue ctxt R.ST0 - startMark insAddr insLen builder - match ins.Operands with - | OneOperand (OprReg reg as opr) -> - let oprExpr = transOprToExpr ins insAddr insLen ctxt opr - builder - let st1 = fpuRegValue ctxt R.ST1 - builder raise InvalidOperandException - builder transOneOpr ins insAddr insLen ctxt - let eDst = extendAddr dst 64 - startMark insAddr insLen builder - if ctxt.WordBitSize = 64 then - if hasREXW ins.REXPrefix then save64BitPromotedFxsave ctxt eDst builder - else save64BitDefaultFxsave ctxt eDst builder - else saveLegacyFxsave ctxt eDst builder - endMark insAddr insLen builder - -let imul ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let oprSize = getOperationSize ins - startMark insAddr insLen builder - match ins.Operands with - | OneOperand _ -> oneOperandImul ins insAddr insLen ctxt oprSize builder - | TwoOperands _ - | ThreeOperands _ -> operandsImul ins insAddr insLen ctxt oprSize builder - | _ -> raise InvalidOperandException - builder transOneOpr ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t1, t2, t3 = tmpVars3 oprSize - startMark insAddr insLen builder - builder transOneOpr ins insAddr insLen ctxt with - | Num n -> Interrupt (BitVector.toInt32 n) |> sideEffects insAddr insLen - | _ -> raise InvalidOperandException - -let jcc ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let pc = getInstrPtr ctxt - let jmpTarget = getOneOpr ins |> transOneOpr ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let cond = getCondOfJcc ins ctxt oprSize - let fallThrough = - bvOfBaseAddr insAddr ctxt .+ bvOfInstrLen insLen ctxt - startMark insAddr insLen builder - builder transOneOpr ins insAddr insLen ctxt - let pc = getInstrPtr ctxt - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let src = convertSrc src - let addrSize = getEffAddrSz ins - startMark insAddr insLen builder - match oprSize, addrSize with - | 16, 16 | 32, 32 | 64, 64 -> - builder , 32 | 16, 64 -> - builder src)) - | 32, 16 -> builder src)) - | 32, 64 -> builder src)) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let leave ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let sp = getStackPtr ctxt - let bp = getBasePtr ctxt - startMark insAddr insLen builder - builder transOneOpr ins insAddr insLen ctxt - startMark insAddr insLen builder - builder transOneOpr ins insAddr insLen ctxt - let addrSize = getEffAddrSz ins - let oprSize = getOperationSize ins - let pc = getInstrPtr ctxt - let count, cntSize = - if addrSize = 32 then getRegVar ctxt R.ECX, 32 - elif addrSize = 64 then getRegVar ctxt R.RCX, 64 - else getRegVar ctxt R.CX, 16 - let zf = getRegVar ctxt R.ZF - startMark insAddr insLen builder - builder count != num0 cntSize - | Opcode.LOOPE -> (zf == b1) .& (count != num0 cntSize) - | Opcode.LOOPNE -> (zf == b0) .& (count != num0 cntSize) - | _ -> raise InvalidOpcodeException - let fallThrough = bvOfBaseAddr insAddr ctxt .+ bvOfInstrLen insLen ctxt - let jumpTarget = if oprSize = 16 then pc .& numI32 0xFFFF 32 - else sExt oprSize dst - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let num0 = num0 oprSize - startMark insAddr insLen builder - let temp = tmpVar oprSize - builder (src >> temp)) == b0) - builder - startMark insAddr insLen builder - builder dst1, extractHigh 32 dst1 - let dst2A, dst2B = extractLow 32 dst2, extractHigh 32 dst2 - let src1A, src1B = extractLow 32 src1, extractHigh 32 src1 - let src2A, src2B = extractLow 32 src2, extractHigh 32 src2 - let val4, val3, val2, val1 = tmpVars4 32 - startMark insAddr insLen builder - builder - startMark insAddr insLen builder - builder - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t = tmpVar oprSize - let cnt = RegType.toByteWidth oprSize |> int - let tmps = Array.init cnt (fun _ -> tmpVar 8) - let builder = new StmtBuilder (2 * cnt) - startMark insAddr insLen builder - builder (i * 8)) - done - builder movdRegToReg ctxt r1 r2 builder - | OprMem _, OprReg r -> let dst = transOprToExpr ins insAddr insLen ctxt dst - movdRegToMem ctxt dst r builder - | OprReg r, OprMem _ -> let src = transOprToExpr ins insAddr insLen ctxt src - movdMemToReg ctxt src r builder - | _, _ -> raise InvalidOperandException - endMark insAddr insLen builder - -let movddup ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let dst1, dst0 = transOprToExpr128 ins insAddr insLen ctxt dst - let src = transOprToExpr64 ins insAddr insLen ctxt src - startMark insAddr insLen builder - builder - let src = transOprToExpr ins insAddr insLen ctxt src - builder - let dst = transOprToExpr ins insAddr insLen ctxt dst - builder raise InvalidOperandException - endMark insAddr insLen builder - -let movhlps ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let dst = transOprToExpr128 ins insAddr insLen ctxt dst |> snd - let src = transOprToExpr128 ins insAddr insLen ctxt src |> fst - startMark insAddr insLen builder - builder ), OprReg r -> - let dst = transOprToExpr ins insAddr insLen ctxt dst - builder )-> - let src = transOprToExpr ins insAddr insLen ctxt src - builder raise InvalidOperandException - endMark insAddr insLen builder - -let movlhps ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let dst = transOprToExpr128 ins insAddr insLen ctxt dst |> fst - let src = transOprToExpr128 ins insAddr insLen ctxt src |> snd - startMark insAddr insLen builder - builder - let src = transOprToExpr ins insAddr insLen ctxt src - builder - let dst = transOprToExpr ins insAddr insLen ctxt dst - builder raise InvalidOperandException - endMark insAddr insLen builder - -let movlps ins insAddr insLen ctxt = movlpd ins insAddr insLen ctxt - -let movmskpd ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let dst = transOprToExpr ins insAddr insLen ctxt dst - let src1, src2 = transOprToExpr128 ins insAddr insLen ctxt src - let oprSize = getOperationSize ins - startMark insAddr insLen builder - let src63 = sExt oprSize (extractHigh 1 src2) - let src127 = (sExt oprSize (extractHigh 1 src1)) << num1 oprSize - builder 63) (extract srcA 1 31) - let srcB = concat (extract srcB 1 63) (extract srcB 1 31) - builder movqRegToReg ctxt r1 r2 builder - | OprMem _, OprReg r -> let dst = transOprToExpr ins insAddr insLen ctxt dst - movqRegToMem ctxt dst r builder - | OprReg r, OprMem _ -> let src = transOprToExpr ins insAddr insLen ctxt src - movqMemToReg ctxt src r builder - | _, _ -> raise InvalidOperandException - endMark insAddr insLen builder - -let movq2dq ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src = transOprToExpr ins insAddr insLen ctxt src - startMark insAddr insLen builder - builder ) - endMark insAddr insLen builder - -let movs ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - startMark insAddr insLen builder - let body () = - let oprSize = getOperationSize ins - let df = getRegVar ctxt R.DF - let si = getRegVar ctxt (if is64bit ctxt then R.RSI else R.ESI) - let di = getRegVar ctxt (if is64bit ctxt then R.RDI else R.EDI) - builder - let dst = getPseudoRegVar ctxt r1 1 - let src = getPseudoRegVar ctxt r2 1 - builder - let dst2, dst1 = getPseudoRegVar128 ctxt r1 - let src = transOprToExpr ins insAddr insLen ctxt src - builder ) - | OprMem _ , OprReg r1 -> - let dst = transOprToExpr ins insAddr insLen ctxt dst - let src = getPseudoRegVar ctxt r1 1 - builder dst src) - | _ -> raise InvalidOperandException - endMark insAddr insLen builder - -let movss (ins: InsInfo) insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - startMark insAddr insLen builder - match dst, src with - | OprReg r1, OprReg r2 -> - let dst = getPseudoRegVar ctxt r1 1 |> extractLow 32 - let src = getPseudoRegVar ctxt r2 1 |> extractLow 32 - builder - let dst2, dst1 = getPseudoRegVar128 ctxt r1 - let src = transOprToExpr ins insAddr insLen ctxt src - builder dst1 src) - builder ) - | OprMem _ , OprReg r1 -> - let dst = transOprToExpr ins insAddr insLen ctxt dst - let src = getPseudoRegVar ctxt r1 1 |> extractLow 32 - builder dst src) - | _ -> raise InvalidOperandException - endMark insAddr insLen builder - -let movshdup ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insAddr insLen ctxt src - let tmp1, tmp2 = tmpVars2 32 - startMark insAddr insLen builder - builder src1) - builder src2) - builder dst1 := tmp1) - builder dst1 := tmp1) - builder dst2 := tmp2) - builder dst2 := tmp2) - endMark insAddr insLen builder - -let movsldup ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insAddr insLen ctxt src - let tmp1, tmp2 = tmpVars2 32 - startMark insAddr insLen builder - builder src1) - builder src2) - builder dst1 := tmp1) - builder dst1 := tmp1) - builder dst2 := tmp2) - builder dst2 := tmp2) - endMark insAddr insLen builder - -let movsx ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins |> transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - startMark insAddr insLen builder - builder transOneOpr ins insAddr insLen ctxt) - let t = tmpVar dblWidth - startMark insAddr insLen builder - builder - match oprSize with - | 8 -> builder | 32 | 64 -> - builder raise InvalidOperandSizeException - builder transOneOpr ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t = tmpVar oprSize - let oFCond = t == (num1 oprSize << (numU32 31u oprSize) ) - startMark insAddr insLen builder - builder transOneOpr ins insAddr insLen ctxt - let oprSize = getOperationSize ins - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t = tmpVar oprSize - startMark insAddr insLen builder - builder opPor 16 - -let orps ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPor 16 - -let outs ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - startMark insAddr insLen builder - let body () = - let oprSize = getOperationSize ins - let df = getRegVar ctxt R.DF - let si = getRegVar ctxt (if is64bit ctxt then R.RSI else R.ESI) - let src = getRegVar ctxt R.DX - let amount = numI32 (RegType.toByteWidth oprSize) ctxt.WordBitSize - match oprSize with - | 8 -> - builder (loadLE oprSize si)) - builder -> - builder -> - builder (loadLE oprSize si)) - | _ -> raise InvalidOperandSizeException - if hasREPZ ins.Prefixes then - strRepeat ctxt body None insAddr insLen builder - elif hasREPNZ ins.Prefixes then raise InvalidPrefixException - else body () - endMark insAddr insLen builder - -let opPackssdw _ src1 src2 = - Array.append src1 src2 |> Array.map saturateSignedDwordToSignedWord - -let packssdw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPackssdw 16 - -let opPacksswb _ src1 src2 = - Array.append src1 src2 |> Array.map saturateSignedWordToSignedByte - -let packsswb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPacksswb 16 - -let opPackuswb _ src1 src2 = - Array.append src1 src2 |> Array.map saturateSignedWordToUnsignedByte - -let packuswb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPackuswb 16 - -let paddb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 (opP (.+)) 8 - -let paddd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 (opP (.+)) 8 - -let paddq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 (opP (.+)) 8 - -let opPaddsb oprSize src1 src2 = - (opP (.+)) oprSize src1 src2 |> Array.map saturateToSignedByte - -let paddsb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPaddsb 16 - -let opPaddsw oprSize src1 src2 = - (opP (.+)) oprSize src1 src2 |> Array.map saturateToSignedWord - -let paddsw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPaddsw 16 - -let opPaddusb oprSize src1 src2 = - (opP (.+)) oprSize src1 src2 |> Array.map saturateToUnsignedByte - -let paddusb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPaddusb 16 - -let opPaddusw oprSize src1 src2 = - (opP (.+)) oprSize src1 src2 |> Array.map saturateToUnsignedWord - -let paddusw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPaddusw 16 - -let paddw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 (opP (.+)) 8 - -let palignr ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src, imm = getThreeOprs ins - let imm = transOprToExpr ins insAddr insLen ctxt imm - startMark insAddr insLen builder - match getOperationSize ins with - | 64 -> - let dst = transOprToExpr ins insAddr insLen ctxt dst - let src = transOprToExpr ins insAddr insLen ctxt src - let t = tmpVar 128 - builder > (zExt 128 (imm .* numU32 8u 64))) - builder t) - | 128 -> - let dst1, dst2 = transOprToExpr128 ins insAddr insLen ctxt dst - let src1, src2 = transOprToExpr128 ins insAddr insLen ctxt src - let dst = concat dst1 dst2 - let src = concat src1 src2 - let t = tmpVar 256 - builder > (zExt 256 (imm .* numU32 8u 128))) - builder 64) - builder t) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let pand ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPand 8 - -let pandn ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPandn 8 - -let opAveragePackedInt (packSz: int) = - let dblSz = packSz * 2 - let dblExt expr = zExt dblSz expr - let avg e1 e2 = extract (dblExt e1 .+ dblExt e2 .+ num1 dblSz) packSz 1 - Array.map2 avg - -let opPavgb _ = opAveragePackedInt 8 - -let pavgb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPavgb 64 - -let opPavgw _ = opAveragePackedInt 16 - -let pavgw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPavgw 32 - -let opPcmp packSz cmpOp = - Array.map2 (fun e1 e2 -> ite (cmpOp e1 e2) (getMask packSz) (num0 packSz)) - -let opPcmpeqb _ = opPcmp 8 (==) -let opPcmpeqd _ = opPcmp 32 (==) -let opPcmpeqq _ = opPcmp 64 (==) -let opPcmpeqw _ = opPcmp 16 (==) -let opPcmpgtb _ = opPcmp 8 sgt -let opPcmpgtd _ = opPcmp 32 sgt -let opPcmpgtw _ = opPcmp 16 sgt - -let pcmpeqb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPcmpeqb 32 - -let pcmpeqd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPcmpeqd 16 - -let pcmpeqq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPcmpeqq 8 - -let pcmpeqw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPcmpeqw 32 - -let pcmpgtb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPcmpgtb 32 - -let pcmpgtd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPcmpgtd 16 - -let pcmpgtw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPcmpgtw 32 - -let aggOpr ins insAddr insLen - ctxt ctrl src1 src2 ck1 ck2 (res1 : Expr []) builder = - let nElem = int ctrl.NumElems - let elemSz = RegType.fromBitWidth <| nElem - let boolRes = genBoolRes ins insAddr insLen ctrl ctxt src2 src1 ck2 ck1 - let rangesCmp idx = - match ctrl.Sign, idx % 2 = 0 with - | Signed, true -> sge | Signed, _ -> sle | _, true -> ge | _, _ -> le - match ctrl.Agg with - | EqualAny -> - for j in 0 .. nElem - 1 do - let tRes = [| for _ in 1 .. nElem -> tmpVar elemSz |] - let boolRes i = boolRes j i (==) - builder - for i in 0 .. nElem - 1 do - let boolRes i = boolRes i i (==) - builder - for j in 0 .. nElem - 1 do - let tRes = [| for _ in 1 .. nElem -> tmpVar elemSz |] - let boolRes k i = boolRes k i (==) - builder - for j in 0 .. nElem - 1 do - let tRes = [| for _ in 1 .. nElem -> tmpVar elemSz |] - let cmp i = rangesCmp i - let boolRes i = boolRes j i (cmp i) - builder reg) (AST.neg reg) reg) - (numU32 ctrl.NumElems 32) - let rec getImZSFlag acc srcB srcA idx = - let packSz = ctrl.PackSize - let packWidth = RegType.toBitWidth packSz - let half = ctrl.NumElems / 2u |> int - let e, amount = if idx < half then srcA, idx else srcB, idx - half - let v e = e >> numI32 (amount * packWidth) 64 - let next, cond = idx - 1, idx = 0 - if cond then ite (extractLow packSz (v e) == num0 packSz) b1 acc - else let acc = ite (extractLow packSz (v e) == num0 packSz) b1 acc - getImZSFlag acc srcB srcA next - match ctrl.Len with - | Implicit -> - builder int)) - builder int)) - | Explicit -> - builder - let outSz, cx = - if hasREXW ins.REXPrefix then 64, R.RCX else 32, R.ECX - let cx = getRegVar ctxt cx - let nMaxSz = numI32 nElem elemSz - let idx = if info.OutSelect = Least then nElem - 1 else 0 - let out = zExt outSz <| genOutput info intRes2 nMaxSz idx - builder - let xmmB, xmmA = getPseudoRegVar128 ctxt Register.XMM0 - let loop (acc1, acc2) i = - let src = extract intRes2 1 i - if (i < nElem / 2) then (acc1, (zExt info.PackSize src) :: acc2) - else ((zExt info.PackSize src) :: acc1, acc2) - if info.OutSelect = Least then - builder intRes2) - builder ) - else let r1, r2 = List.fold loop ([], []) [0 .. nElem - 1] - builder tmpVar elemSz |] - aggOpr ins insAddr insLen ctxt ctrl src1 src2 ck1 ck2 res1 builder - builder intRes2) - builder extractLow 8 .& numU32 7u 8 - let oprSize = getOperationSize ins - startMark insAddr insLen builder - match src with - | OprReg reg -> - match Register.getKind reg with - | Register.Kind.MMX -> - let src = transOprToExpr ins insAddr insLen ctxt src - let srcOffset = tmpVar 64 - builder count) - let t = (src >> (srcOffset .* numU32 16u 64)) .& numU32 0xFFFFu 64 - builder - let srcB, srcA = getPseudoRegVar128 ctxt reg - let tSrc = tmpVar 128 - let srcOffset = tmpVar 128 - builder count) - builder > (srcOffset .* numU32 16u 128)) .& - numU32 0xFFFFu 128 - builder raise InvalidRegisterException - | _ -> raise InvalidOperandException - endMark insAddr insLen builder - -let pinsrb ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src, count = getThreeOprs ins - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src, count = transTwoOprs ins insAddr insLen ctxt (src, count) - let oprSize = getOperationSize ins - let sel, mask, temp, tDst = tmpVars4 oprSize - let sel8 = sel .* numI32 8 oprSize - startMark insAddr insLen builder - builder 0) << sel8) .& mask) - builder tDst) - builder tDst) - endMark insAddr insLen builder - -let pinsrw ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src, count = getThreeOprs ins - let src = transOprToExpr ins insAddr insLen ctxt src - let sel = tmpVar 64 - let getImm = function - | OprImm imm -> imm - | _ -> raise InvalidOperandException - startMark insAddr insLen builder - match getOperationSize ins with - | 64 -> - let dst = transOprToExpr ins insAddr insLen ctxt dst - let count = transOprToExpr ins insAddr insLen ctxt count - let mask = tmpVar 64 - builder ) - let pos = sel .* numU64 0x10UL 64 - builder ) << pos) - builder src << pos .& mask)) - | 128 -> - let dst1, dst2 = transOprToExpr128 ins insAddr insLen ctxt dst - let mask = tmpVar 64 - let count = getImm count - builder .| numI64 7L 64) - if count > 3L then - let pos = (sel .- numI32 4 64) .* numI32 16 64 - builder ) << pos) - builder src << pos .& mask)) - else - let pos = sel .* numI32 16 64 - builder ) << pos) - builder src << pos .& mask)) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let opPmaddwd _ = - let lowAndSExt expr = extractLow 16 expr |> sExt 32 - let highAndSExt expr = extractHigh 16 expr |> sExt 32 - let mulLow e1 e2 = lowAndSExt e1 .* lowAndSExt e2 - let mulHigh e1 e2 = highAndSExt e1 .* highAndSExt e2 - let packAdd e1 e2 = mulLow e1 e2 .+ mulHigh e1 e2 - Array.map2 packAdd - -let pmaddwd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPmaddwd 16 - -let opMaxMinPacked cmp = Array.map2 (fun e1 e2 -> ite (cmp e1 e2) e1 e2) - -let opPmaxsb _ = opMaxMinPacked sgt - -let pmaxsb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPmaxsb 64 - -let opPmaxsw _ = opMaxMinPacked sgt - -let pmaxsw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPmaxsw 32 - -let opPmaxub _ = opMaxMinPacked gt - -let pmaxub ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPmaxub 64 - -let opPminsb _ = opMaxMinPacked slt - -let pminsb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPminsb 32 - -let opPminsw _ = opMaxMinPacked slt - -let pminsw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPminsw 32 - -let opPminub _ = opMaxMinPacked lt - -let pminub ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPminub 64 - -let opPminud _ = opMaxMinPacked lt - -let pminud ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPminud 32 - -let pmovmskb ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let oprSize = getOperationSize ins - startMark insAddr insLen builder - let r = match src with | OprReg r -> r | _ -> raise InvalidOperandException - let arrayInit cnt src = - Array.init cnt (fun i -> extract src 1 (i * 8 + 7)) - match Register.getKind r with - | Register.Kind.MMX -> - let dst, src = transTwoOprs ins insAddr insLen ctxt (dst, src) - let srcSize = AST.typeOf src - let cnt = RegType.toByteWidth srcSize - let tmps = arrayInit cnt src - builder - let dst = transOprToExpr ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - let srcSize = AST.typeOf srcA - let cnt = RegType.toByteWidth srcSize - let tmpsA = arrayInit cnt srcA - let tmpsB = arrayInit cnt srcB - let tmps = concat (concatExprs tmpsB) (concatExprs tmpsA) - builder - let dst = transOprToExpr ins insAddr insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insAddr insLen ctxt src - let srcSize = AST.typeOf srcA - let cnt = RegType.toByteWidth srcSize - let tmpsA = arrayInit cnt srcA - let tmpsB = arrayInit cnt srcB - let tmpsC = arrayInit cnt srcC - let tmpsD = arrayInit cnt srcD - let tmps = concat (concat (concatExprs tmpsD) (concatExprs tmpsC)) - (concat (concatExprs tmpsB) (concatExprs tmpsA)) - builder raise InvalidOperandException - endMark insAddr insLen builder - -let opPmul resType extr extSz packSz src1 src2 = - Array.map2 (fun e1 e2 -> extr extSz e1 .* extr extSz e2) src1 src2 - |> Array.map (resType packSz) - -let opPmulhw _ = opPmul extractHigh sExt 32 16 - -let pmulhw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPmulhw 32 - -let opPmulhuw _ = opPmul extractHigh zExt 32 16 - -let pmulhuw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPmulhuw 32 - -let opPmullw _ = opPmul extractLow sExt 32 16 - -let pmullw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPmullw 32 - -let opPmuludq _ = - let low32 expr = expr .& numI64 0xffffffffL 64 - Array.map2 (fun e1 e2 -> low32 e1 .* low32 e2) - -let pmuludq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPmuludq 8 - -let pop ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst = getOneOpr ins |> transOneOpr ins insAddr insLen ctxt - let oprSize = getOperationSize ins - startMark insAddr insLen builder - auxPop oprSize ctxt dst builder - endMark insAddr insLen builder - -let popa ins insAddr insLen ctxt oprSize = - let builder = new StmtBuilder (16) - let sp = getRegVar ctxt R.ESP - let di = if oprSize = 32 then R.EDI else R.DI - let si = if oprSize = 32 then R.ESI else R.SI - let bp = if oprSize = 32 then R.EBP else R.BP - let bx = if oprSize = 32 then R.EBX else R.BX - let dx = if oprSize = 32 then R.EDX else R.DX - let cx = if oprSize = 32 then R.ECX else R.CX - let ax = if oprSize = 32 then R.EAX else R.AX - startMark insAddr insLen builder - auxPop oprSize ctxt (getRegVar ctxt di) builder - auxPop oprSize ctxt (getRegVar ctxt si) builder - auxPop oprSize ctxt (getRegVar ctxt bp) builder - builder )) - auxPop oprSize ctxt (getRegVar ctxt bx) builder - auxPop oprSize ctxt (getRegVar ctxt dx) builder - auxPop oprSize ctxt (getRegVar ctxt cx) builder - auxPop oprSize ctxt (getRegVar ctxt ax) builder - endMark insAddr insLen builder - -let popcnt ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let lblLoop = lblSymbol "Loop" - let lblExit = lblSymbol "Exit" - let lblLoopCond = lblSymbol "LoopCond" - let dst, src = getTwoOprs ins |> transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let max = numI32 (RegType.toBitWidth oprSize) oprSize - startMark insAddr insLen builder - let i = tmpVar oprSize - let count = tmpVar oprSize - builder (src >> i)) == b1 - builder 11) - builder 10) - builder 9) - builder 8) - builder 7) - builder 6) - builder 4) - builder 2) - builder t) - endMark insAddr insLen builder - -let por ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPor 8 - -let opPsadbw _ = - let abs expr = ite (lt expr (num0 8)) (AST.neg expr) (expr) - Array.map2 (fun e1 e2 -> abs (e1 .- e2)) - -let psadbw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPsadbw 64 - -let pshufb ins insAddr insLen ctxt = - let dst, src = getTwoOprs ins - let oprSize = getOperationSize ins - let cnt = RegType.toBitWidth oprSize / 8 - let builder = new StmtBuilder (2 * cnt) - startMark insAddr insLen builder - let tmps = Array.init cnt (fun _ -> tmpVar 8) - let mask = numI32 (cnt - 1) 8 - let genTmps dst src = - for i in 0 .. cnt - 1 do - let cond = extract src 1 (i * 8 + 7) - let idx = (extract src 8 (i * 8)) .& mask - let numShift = zExt oprSize idx .* numI32 8 oprSize - builder ) (extractLow 8 (dst >> numShift))) - done - match oprSize with - | 64 -> - let dst, src = transTwoOprs ins insAddr insLen ctxt (dst, src) - genTmps dst src - builder -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - let conDst, conSrc = tmpVars2 oprSize - let tDst = tmpVar oprSize - builder tDst) - builder tDst) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let pshufd ins insAddr insLen ctxt = - let dst, src, ord = getThreeOprs ins - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - let ord = transOprToExpr ins insAddr insLen ctxt ord - let oprSize = getOperationSize ins - let cnt = RegType.toBitWidth oprSize / 32 - let builder = new StmtBuilder (2 * cnt) - startMark insAddr insLen builder - let tmps = Array.init cnt (fun _ -> tmpVar 32) - let n32 = numI32 32 oprSize - let mask2 = numI32 3 32 (* 2-bit mask *) - let tSrc = tmpVar oprSize - let tDst = tmpVar oprSize - builder ord) >> (numI32 ((i - 1) * 2) 32)) .& mask2 - let order' = zExt oprSize order - builder (tSrc >> (order' .* n32))) - done - builder tDst) - builder tDst) - endMark insAddr insLen builder - -let pshufhw ins insAddr insLen ctxt = - let dst, src, imm = getThreeOprs ins - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - let imm = transOprToExpr ins insAddr insLen ctxt imm - let builder = new StmtBuilder (8) - startMark insAddr insLen builder - let tmps = Array.init 4 (fun _ -> tmpVar 16) - let n16 = numI32 16 64 - let mask2 = numI32 3 64 (* 2-bit mask *) - for i in 1 .. 4 do - let imm = - ((extractLow 64 imm) >> (numI32 ((i - 1) * 2) 64)) .& mask2 - builder (srcB >> (imm .* n16))) - done - builder tmpVar 16) - let n16 = numI32 16 64 - let mask2 = numI32 3 64 (* 2-bit mask *) - for i in 1 .. 4 do - let imm = - ((extractLow 64 imm) >> (numI32 ((i - 1) * 2) 64)) .& mask2 - builder (srcA >> (imm .* n16))) - done - builder transThreeOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let cnt = RegType.toBitWidth oprSize / 16 - let builder = new StmtBuilder (2 * cnt) - startMark insAddr insLen builder - let tmps = Array.init cnt (fun _ -> tmpVar 16) - let n16 = numI32 16 oprSize - let mask2 = numI32 3 16 (* 2-bit mask *) - for i in 1 .. cnt do - let order = - ((extractLow 16 ord) >> (numI32 ((i - 1) * 2) 16)) .& mask2 - let order' = zExt oprSize order - builder (src >> (order' .* n16))) - done - builder tmpVar (oprSize / tCnt)) - for i in 0 .. tCnt - 1 do - let t = zExt oprSize ((src >> numI32 (i * 32) oprSize) << cntSrc) - builder t) - done - ite (gt cntSrc (numU32 31u oprSize)) (num0 oprSize) (concatExprs tmps) - -let opShiftPackedDataLogical oprSize packSz shift src1 src2 = - let count = concatExprs src2 |> zExt oprSize - let cond = gt count (numI32 ((int packSz) - 1) oprSize) - let shifted expr = extract (shift (zExt oprSize expr) count) packSz 0 - Array.map (fun e -> ite cond (num0 packSz) (shifted e)) src1 - -let opPslld oprSize = opShiftPackedDataLogical oprSize 32 (<<) - -let pslld ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPslld 8 - -let opPsllq oprSize = opShiftPackedDataLogical oprSize 64 (<<) - -let psllq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPsllq 8 - -let opPsllw oprSize = opShiftPackedDataLogical oprSize 16 (<<) - -let psllw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPsllw 8 - -let shiftDQ ins insAddr insLen ctxt shift = - let builder = new StmtBuilder (8) - let dst, cnt = getTwoOprs ins - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let cnt = transOprToExpr ins insAddr insLen ctxt cnt |> castNum 8 - let oprSize = getOperationSize ins - let t1 = tmpVar 8 - let t2, tDst = tmpVars2 oprSize - startMark insAddr insLen builder - builder ) cnt) (numU32 16u 8) cnt) - builder )))) - builder tDst) - builder tDst) - endMark insAddr insLen builder - -let pslldq ins insAddr insLen ctxt = shiftDQ ins insAddr insLen ctxt (<<) -let psrldq ins insAddr insLen ctxt = shiftDQ ins insAddr insLen ctxt (>>) - -let opShiftPackedDataRightArith oprSize packSz src1 src2 = - let count = concatExprs src2 - let cond = gt count (numI32 ((int packSz) - 1) oprSize) - let count = ite cond (numI32 (int packSz) oprSize) count - let shifted expr = extract ((sExt oprSize expr) ?>> count) packSz 0 - Array.map shifted src1 - -let opPsrad oprSize = opShiftPackedDataRightArith oprSize 32 - -let psrad ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPsrad 16 - -let opPsraw oprSize = opShiftPackedDataRightArith oprSize 16 - -let psraw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPsraw 32 - -let opPsrld oprSize = opShiftPackedDataLogical oprSize 32 (>>) - -let psrld ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPsrld 16 - -let opPsrlq oprSize = opShiftPackedDataLogical oprSize 64 (>>) - -let psrlq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPsrlq 8 - -let opPsrlw oprSize = opShiftPackedDataLogical oprSize 16 (>>) - -let psrlw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPsrlw 32 - -let opPsub _ = Array.map2 (.-) - -let psubb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPsub 8 - -let psubq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPsub 8 - -let psubw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPsub 8 - -let psubd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPsub 8 - -let opPsubsb oprSize src1 src2 = - opPsub oprSize src1 src2 |> Array.map saturateToSignedByte - -let psubsb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPsubsb 8 - -let opPsubsw oprSize src1 src2 = - opPsub oprSize src1 src2 |> Array.map saturateToSignedWord - -let psubsw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPsubsw 8 - -let opPsubusb oprSize src1 src2 = - opPsub oprSize src1 src2 |> Array.map saturateToUnsignedByte - -let psubusb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPsubusb 8 - -let opPsubusw oprSize src1 src2 = - opPsub oprSize src1 src2 |> Array.map saturateToUnsignedWord - -let psubusw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPsubusw 8 - -let ptest ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let src1, src2 = getTwoOprs ins - let src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - let t1, t2, t3, t4 = tmpVars4 64 - startMark insAddr insLen builder - builder )) - builder )) - builder then ptest ins insAddr insLen ctxt - else - let builder = new StmtBuilder (16) - let src1, src2 = getTwoOprs ins - let src1D, src1C, src1B, src1A = - transOprToExpr256 ins insAddr insLen ctxt src1 - let src2D, src2C, src2B, src2A = - transOprToExpr256 ins insAddr insLen ctxt src2 - let t1, t2, t3, t4 = tmpVars4 64 - let t5, t6, t7, t8 = tmpVars4 64 - startMark insAddr insLen builder - builder )) - builder )) - builder | 128 -> - let half = Array.length src1 / 2 - let sPos = if isHigh then half else 0 - let src1 = Array.sub src1 sPos half - let src2 = Array.sub src2 sPos half - Array.fold2 (fun acc e1 e2 -> e2 :: e1 :: acc) [] src1 src2 - |> List.rev |> List.toArray - | 256 -> - let half = Array.length src1 / 2 - let src1A = Array.sub src1 0 half - let src1B = Array.sub src1 half half - let src2A = Array.sub src2 0 half - let src2B = Array.sub src2 half half - let half = Array.length src1A / 2 - let sPos = if isHigh then half else 0 - let src1A = Array.sub src1A sPos half - let src2A = Array.sub src2A sPos half - let src1B = Array.sub src1B sPos half - let src2B = Array.sub src2B sPos half - List.append - (Array.fold2 (fun acc e1 e2 -> e2 :: e1 :: acc) [] src1B src2B) - (Array.fold2 (fun acc e1 e2 -> e2 :: e1 :: acc) [] src1A src2A) - |> List.rev |> List.toArray - | _ -> raise InvalidOperandSizeException - -let opPunpckHigh oprSize src1 src2 = opPunpck oprSize src1 src2 true - -let punpckhbw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPunpckHigh 64 - -let punpckhdq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPunpckHigh 16 - -let punpckhqdq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPunpckHigh 8 - -let punpckhwd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPunpckHigh 32 - -let opPunpckLow oprSize src1 src2 = opPunpck oprSize src1 src2 false - -let punpcklbw ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPunpckLow 64 - -let punpckldq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPunpckLow 16 - -let punpcklqdq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPunpckLow 8 - -let punpcklwd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 16 opPunpckLow 32 - -let push ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let src = getOneOpr ins |> transOneOpr ins insAddr insLen ctxt - let oprSize = getOperationSize ins - startMark insAddr insLen builder - auxPush oprSize ctxt (padPushExpr oprSize src) builder - endMark insAddr insLen builder - -let pusha ins insAddr insLen ctxt oprSize = - let builder = new StmtBuilder (16) - let t = tmpVar oprSize - let sp = if oprSize = 32 then R.ESP else R.SP - let ax = if oprSize = 32 then R.EAX else R.AX - let cx = if oprSize = 32 then R.ECX else R.CX - let dx = if oprSize = 32 then R.EDX else R.DX - let bx = if oprSize = 32 then R.EBX else R.BX - let bp = if oprSize = 32 then R.EBP else R.BP - let si = if oprSize = 32 then R.ESI else R.SI - let di = if oprSize = 32 then R.EDI else R.DI - startMark insAddr insLen builder - builder -> e - | 32 -> e .& (numI32 0xfcffff 32) - | 64 -> e .& (numI32 0xfcffff 64) - | _ -> raise InvalidOperandSizeException - startMark insAddr insLen builder - auxPush oprSize ctxt e builder - endMark insAddr insLen builder - -let pxor ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let oprSize = getOperationSize ins - startMark insAddr insLen builder - match oprSize with - | 64 -> - let dst, src = transTwoOprs ins insAddr insLen ctxt (dst, src) - builder src) - | 128 -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - builder srcA) - builder srcB) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let rcl ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, count = getTwoOprs ins |> transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let cF = getRegVar ctxt R.CF - let oF = getRegVar ctxt R.OF - let tmpCount = tmpVar oprSize - let size = numI32 (RegType.toBitWidth oprSize) oprSize - let count = zExt oprSize count - let cnt = - match oprSize with - | 8 -> (count .& numI32 0x1f oprSize) .% numI32 9 oprSize - | 16 -> (count .& numI32 0x1f oprSize) .% numI32 17 oprSize - | 32 -> count .& numI32 0x1f oprSize - | 64 -> count .& numI32 0x3f oprSize - | _ -> raise InvalidOperandSizeException - let cond = count == num1 oprSize - startMark insAddr insLen builder - builder > (size .- tmpCount))) - builder dst) - builder dst <+> cF) undefOF) - endMark insAddr insLen builder - -let rcr ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, count = getTwoOprs ins |> transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let cF = getRegVar ctxt R.CF - let oF = getRegVar ctxt R.OF - let tmpCount = tmpVar oprSize - let size = numI32 (RegType.toBitWidth oprSize) oprSize - let count = zExt oprSize count - let cnt = - match oprSize with - | 8 -> (count .& numI32 0x1f oprSize) .% numI32 9 oprSize - | 16 -> (count .& numI32 0x1f oprSize) .% numI32 17 oprSize - | 32 -> count .& numI32 0x1f oprSize - | 64 -> count .& numI32 0x3f oprSize - | _ -> raise InvalidOperandSizeException - let cond = count == num1 oprSize - startMark insAddr insLen builder - builder dst <+> cF) undefOF) - builder > tmpCount) .| (dst << (size .- tmpCount))) - builder dst) - endMark insAddr insLen builder - -let rdpkru ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let errExp = unDef 1 "#GP(0) error" - let lblSucc = lblSymbol "Succ" - let oprSize = getOperationSize ins - let ecx = getRegVar ctxt R.ECX - let eax = getRegOfSize ctxt ctxt.WordBitSize GrpEAX - let edx = getRegOfSize ctxt ctxt.WordBitSize GrpEDX - startMark insAddr insLen builder - builder - let src = getOneOpr ins |> transOneOpr ins insAddr insLen ctxt - startMark insAddr insLen builder - auxPop oprSize ctxt t builder - builder - startMark insAddr insLen builder - auxPop oprSize ctxt t builder - builder sideEffects insAddr insLen UnsupportedFAR - -let rotate ins insAddr insLen ctxt lfn hfn cfFn ofFn = - let builder = new StmtBuilder (8) - let dst, count = getTwoOprs ins |> transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let cF = getRegVar ctxt R.CF - let oF = getRegVar ctxt R.OF - let countMask = if is64REXW ctxt ins then numU32 0x3Fu oprSize - else numU32 0x1Fu oprSize - let size = numI32 (RegType.toBitWidth oprSize) oprSize - let orgCount = tmpVar oprSize - let cond1 = orgCount == num0 oprSize - let cond2 = orgCount == num1 oprSize - startMark insAddr insLen builder - builder dst)) - builder extractHigh 1 dst - rotate ins insAddr insLen ctxt (<<) (>>) extractLow ofFn - -let ror ins insAddr insLen ctxt = - let ofFn dst _cF = - extractHigh 1 dst <+> extract dst 1 1 - rotate ins insAddr insLen ctxt (>>) (<<) extractHigh ofFn - -let roundsd ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src, imm = getThreeOprs ins - let dst = transOprToExpr64 ins insAddr insLen ctxt dst - let src = transOprToExpr64 ins insAddr insLen ctxt src - let imm = transOprToExpr ins insAddr insLen ctxt imm - let rc = extract (getRegVar ctxt R.FCW) 2 10 - let tmp = tmpVar 2 - let cster castKind = cast castKind 64 src - startMark insAddr insLen builder - builder 2) rc (extractLow 2 imm)) - builder ) - builder ) (cster CastKind.FtoIRound) dst) - builder ) (cster CastKind.FtoIFloor) dst) - builder ) (cster CastKind.FtoICeil) dst) - builder ) (cster CastKind.FtoITrunc) dst) - endMark insAddr insLen builder - -let sahf ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let ah = getRegVar ctxt R.AH - startMark insAddr insLen builder - builder ah) - builder 2) - builder 4) - builder 6) - builder 7) - endMark insAddr insLen builder - -let shufpd ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src, imm = getThreeOprs ins - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insAddr insLen ctxt src - let imm = transOprToExpr ins insAddr insLen ctxt imm - let cond1 = extractLow 1 imm - let cond2 = extract imm 1 1 - startMark insAddr insLen builder - builder dst1, extractHigh 32 dst1 - let dst2A, dst2B = extractLow 32 dst2, extractHigh 32 dst2 - let src1A, src1B = extractLow 32 src1, extractHigh 32 src1 - let src2A, src2B = extractLow 32 src2, extractHigh 32 src2 - let doShuf cond dst e0 e1 e2 e3 = - builder ) - builder ) e0 dst) - builder ) e1 dst) - builder ) e2 dst) - builder ) e3 dst) - let cond1 = extractLow 2 imm - let cond2 = extract imm 2 2 - let cond3 = extract imm 2 4 - let cond4 = extract imm 2 6 - let tmp1, tmp2, tmp3, tmp4 = tmpVars4 32 - startMark insAddr insLen builder - doShuf cond1 tmp1 dst1A dst1B dst2A dst2B - doShuf cond2 tmp2 dst1A dst1B dst2A dst2B - doShuf cond3 tmp3 src1A src1B src2A src2B - doShuf cond4 tmp4 src1A src1B src2A src2B - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let n0 = num0 oprSize - let n1 = num1 oprSize - let countMask = if is64REXW ctxt ins then numU32 0x3Fu oprSize - else numU32 0x1Fu oprSize - let cnt = (zExt oprSize src) .& countMask - let cond1 = cnt == n1 - let cond2 = cnt == n0 - let oF = getRegVar ctxt R.OF - let cF = getRegVar ctxt R.CF - let sF = getRegVar ctxt R.SF - let zF = getRegVar ctxt R.ZF - let aF = getRegVar ctxt R.AF - let tDst = tmpVar oprSize - let tCnt = tmpVar oprSize - startMark insAddr insLen builder - builder - builder > cnt) - builder (tDst ?>> tCnt) - builder - builder (tDst << tCnt) - builder dst <+> cF - builder - builder > cnt)) - builder (tDst ?>> tCnt) - builder tDst) (ite cond2 oF undefOF)) - | _ -> raise InvalidOpcodeException - builder dst)) - let cbPF computedPF = ite cond2 (getRegVar ctxt R.PF) computedPF - buildPF ctxt dst oprSize (Some cbPF) builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t1, t2, t3, t4 = tmpVars4 oprSize - let cf = getRegVar ctxt R.CF - startMark insAddr insLen builder - builder transOneOpr ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let cond = getCondOfSet ins ctxt |> zExt oprSize - startMark insAddr insLen builder - builder transThreeOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let orig = tmpVar oprSize - let c = tmpVar oprSize - let cond1 = c == num0 oprSize - let cond2 = c == num1 oprSize - let cF = getRegVar ctxt R.CF - let oF = getRegVar ctxt R.OF - let aF = getRegVar ctxt R.AF - startMark insAddr insLen builder - builder (orig >> (maxSz .- c)))) - else - builder (orig >> (c .- num1 oprSize)))) - builder (orig <+> dst)) undefOF)) - builder >) true - -let shrd ins insAddr insLen ctxt = - shiftDblPrec ins insAddr insLen ctxt (>>) (<<) false - -let stmxcsr ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst = getOneOpr ins |> transOneOpr ins insAddr insLen ctxt - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t1, t2, t3 = tmpVars3 oprSize - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t = tmpVar oprSize - startMark insAddr insLen builder - builder t) - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let max = numI32 (RegType.toBitWidth oprSize) oprSize - startMark insAddr insLen builder - let t1 = tmpVar oprSize - builder (src >> t1) == b0) - builder 52 == num (BitVector.unsignedMax 11)) - .& (extractLow 52 expr != num0 52) - builder 23 == num (BitVector.unsignedMax 8)) - .& (extractLow 23 expr != num0 23) - builder dst1, extractHigh 32 dst1 - let dst2A, dst2B = extractLow 32 dst2, extractHigh 32 dst2 - let src2A, src2B = extractLow 32 src2, extractHigh 32 src2 - startMark insAddr insLen builder - builder dst1, extractHigh 32 dst1 - let dst2A, dst2B = extractLow 32 dst2, extractHigh 32 dst2 - let src1A, src1B = extractLow 32 src1, extractHigh 32 src1 - startMark insAddr insLen builder - builder -> - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - builder -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insAddr insLen ctxt dst - let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ins insAddr insLen ctxt src1 - let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ins insAddr insLen ctxt src2 - builder raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vexedPackedFPBinOp32 ins insAddr insLen ctxt op = - let builder = new StmtBuilder (16) - let dst, src1, src2 = getThreeOprs ins - let oprSz = getOperationSize ins - let do32PackedOp dst64 src1 src2 builder = - let dstA, dstB = extractLow 32 dst64, extractHigh 32 dst64 - let src1A, src1B = extractLow 32 src1, extractHigh 32 src1 - let src2A, src2B = extractLow 32 src2, extractHigh 32 src2 - builder -> - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - do32PackedOp dst1 src1A src2A builder - do32PackedOp dst2 src1B src2B builder - fillZeroHigh128 ctxt dst builder - | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insAddr insLen ctxt dst - let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ins insAddr insLen ctxt src1 - let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ins insAddr insLen ctxt src2 - do32PackedOp dst1 sr1A sr2A builder - do32PackedOp dst2 sr1B sr2B builder - do32PackedOp dst3 sr1C sr2C builder - do32PackedOp dst4 sr1D sr2D builder - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vexedScalarFPBinOp ins insAddr insLen ctxt sz op = - let builder = new StmtBuilder (8) - let dst, src1, src2 = getThreeOprs ins - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - startMark insAddr insLen builder - match sz with - | 32 -> - let src2 = transOprToExpr32 ins insAddr insLen ctxt src2 - builder dst1 := op (extractLow 32 src1A) src2) - builder dst1 := extractHigh 32 src1A) - | 64 -> - let src2 = transOprToExpr64 ins insAddr insLen ctxt src2 - builder raise InvalidOperandSizeException - builder v.EVEXPrx <> None - | _ -> false - -let vaddpd ins insAddr insLen ctxt = - vexedPackedFPBinOp64 ins insAddr insLen ctxt fadd - -let vaddps ins insAddr insLen ctxt = - vexedPackedFPBinOp32 ins insAddr insLen ctxt fadd - -let vaddsd ins insAddr insLen ctxt = - vexedScalarFPBinOp ins insAddr insLen ctxt 64 fadd - -let vaddss ins insAddr insLen ctxt = - vexedScalarFPBinOp ins insAddr insLen ctxt 32 fadd - -let vandpd ins insAddr insLen ctxt = - vexedPackedFPBinOp64 ins insAddr insLen ctxt (.&) - -let vandps ins insAddr insLen ctxt = - vexedPackedFPBinOp32 ins insAddr insLen ctxt (.&) - -let andnpdOp e1 e2 = (AST.not e1) .& e2 - -let vandnpd ins insAddr insLen ctxt = - vexedPackedFPBinOp64 ins insAddr insLen ctxt andnpdOp - -let vandnps ins insAddr insLen ctxt = - vexedPackedFPBinOp32 ins insAddr insLen ctxt andnpdOp - -let vbroadcasti128 ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - startMark insAddr insLen builder - builder - startMark insAddr insLen builder - match getOperationSize ins with - | 128 -> - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - builder dst1 := tmp) - builder dst1 := tmp) - builder dst2 := tmp) - builder dst2 := tmp) - fillZeroHigh128 ctxt dst builder - | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insAddr insLen ctxt dst - builder dst1 := tmp) - builder dst1 := tmp) - builder dst2 := tmp) - builder dst2 := tmp) - builder dst3 := tmp) - builder dst3 := tmp) - builder dst4 := tmp) - builder dst4 := tmp) - | _ -> raise InvalidOperandException - endMark insAddr insLen builder - -let vcvtsd2ss ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src1, src2 = getThreeOprs ins - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let src2 = transOprToExpr64 ins insAddr insLen ctxt src2 - startMark insAddr insLen builder - builder dstA := cast CastKind.FloatExt 32 src2) - builder dstA := extractHigh 32 src1A) - builder src2) - builder src2) - builder dstA := cast CastKind.IntToFloat 32 src2) - builder dstA := extractHigh 32 src1A) - builder fdiv - -let vdivss ins insAddr insLen ctxt = - vexedScalarFPBinOp ins insAddr insLen ctxt 32 fdiv - -let vfmadd132sd ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src2, src3 = getThreeOprs ins - let _dstB , dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src2 = transOprToExpr64 ins insAddr insLen ctxt src2 - let src3 = transOprToExpr64 ins insAddr insLen ctxt src3 - let tmp = tmpVar 64 - startMark insAddr insLen builder - builder - startMark insAddr insLen builder - builder - startMark insAddr insLen builder - builder - startMark insAddr insLen builder - builder imm) - builder - let regToReg r1 r2 = - match Register.getKind r1, Register.getKind r2 with - | Register.Kind.XMM, Register.Kind.GP -> - let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) - let src = getRegVar ctxt r2 - builder dstA src) - builder - let dst = getRegVar ctxt r1 - let srcA = getPseudoRegVar ctxt r2 1 - builder srcA)) - | _ -> raise InvalidOperandException - match dst, src with - | OprReg r1, OprReg r2 -> regToReg r1 r2 - | OprReg r, OprMem _ -> - let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) - let src = transOprToExpr ins insAddr insLen ctxt src - builder dstA src) - builder - let dst = transOprToExpr ins insAddr insLen ctxt dst - let srcA = getPseudoRegVar ctxt r 1 - builder srcA) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vmovddup ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - startMark insAddr insLen builder - match getOperationSize ins with - | 128 -> - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src = transOprToExpr64 ins insAddr insLen ctxt src - builder -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insAddr insLen ctxt dst - let _src4, src3, _src2, src1 = transOprToExpr256 ins insAddr insLen ctxt src - builder raise InvalidOperandSizeException - endMark insAddr insLen builder - -let buildVectorMove ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - let oprSize = getOperationSize ins - startMark insAddr insLen builder - if oprSize = 128 then - match dst with - | OprReg _ -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - builder - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - builder raise InvalidOperandException - elif oprSize = 256 then - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insAddr insLen ctxt src - builder match v.EVEXPrx with - | Some ev -> ev - | None -> raise InvalidPrefixException - | None -> raise InvalidPrefixException - -let vmovdqu64 ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - let oprSize = getOperationSize ins - let ePrx = getEVEXPrx ins.VEXInfo - let k = getRegVar ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) - let masking dst = - match ePrx.Z with - | Zeroing -> num0 64 - | Merging -> dst - let cond idx = - if ePrx.AAA = 0uy then num0 1 (* no write mask *) - else extract k 1 idx - startMark insAddr insLen builder - match oprSize with - | 128 -> - let kl, vl = 4, 128 - match dst with - | OprReg _ -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - builder - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - builder raise InvalidOperandException - | 256 -> - let kl, vl = 8, 256 - match dst with - | OprReg _ -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insAddr insLen ctxt src - builder - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insAddr insLen ctxt src - builder raise InvalidOperandException - | 512 -> - let kl, vl = 16, 512 - match dst with - | OprReg _ -> - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insAddr insLen ctxt dst - let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = - transOprToExpr512 ins insAddr insLen ctxt src - builder - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insAddr insLen ctxt dst - let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = - transOprToExpr512 ins insAddr insLen ctxt src - builder raise InvalidOperandException - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vmovhpd ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - startMark insAddr insLen builder - match ins.Operands with - | TwoOperands (dst, src) -> - let dst = transOprToExpr64 ins insAddr insLen ctxt dst - let src2, _src1 = transOprToExpr128 ins insAddr insLen ctxt src - builder - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let _src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let _src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - builder raise InvalidOperandException - endMark insAddr insLen builder - -let vmovhlps ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src1, src2 = getThreeOprs ins - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, _src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let src2B, _src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - startMark insAddr insLen builder - builder - let dst = transOprToExpr64 ins insAddr insLen ctxt dst - let _src2, src1 = transOprToExpr128 ins insAddr insLen ctxt src - builder - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, _src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let _src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - builder raise InvalidOperandException - endMark insAddr insLen builder - -let vmovmskpd ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let dst = transOprToExpr ins insAddr insLen ctxt dst - let dstSz = typeOf dst - let mskpd r = - match Register.getKind r with - | Register.Kind.XMM -> movmskpd ins insAddr insLen ctxt - | Register.Kind.YMM -> - startMark insAddr insLen builder - let src4, src3, src2, src1 = transOprToExpr256 ins insAddr insLen ctxt src - let src63 = sExt dstSz (extractHigh 1 src1) - let src127 = (sExt dstSz (extractHigh 1 src2)) << num1 dstSz - let src191 = (sExt dstSz (extractHigh 1 src3)) << numI32 2 dstSz - let src255 = (sExt dstSz (extractHigh 1 src4)) << numI32 3 dstSz - builder raise InvalidOperandException - match src with - | OprReg r -> mskpd r - | _ -> raise InvalidOperandSizeException - -let vmovmskps ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - let dst = transOprToExpr ins insAddr insLen ctxt dst - let dstSz = typeOf dst - let mskpd r = - match Register.getKind r with - | Register.Kind.XMM -> movmskps ins insAddr insLen ctxt - | Register.Kind.YMM -> - startMark insAddr insLen builder - let src4, src3, src2, src1 = transOprToExpr256 ins insAddr insLen ctxt src - let src1A, src1B = extractLow 32 src1, extractHigh 32 src1 - let src2A, src2B = extractLow 32 src2, extractHigh 32 src2 - let src3A, src3B = extractLow 32 src3, extractHigh 32 src3 - let src4A, src4B = extractLow 32 src4, extractHigh 32 src4 - let src31 = sExt dstSz (extractHigh 1 src1A) - let src63 = sExt dstSz (extractHigh 1 src1B) << num1 dstSz - let src95 = (sExt dstSz (extractHigh 1 src2A)) << numI32 2 dstSz - let src127 = (sExt dstSz (extractHigh 1 src2B)) << numI32 3 dstSz - let src159 = (sExt dstSz (extractHigh 1 src3A)) << numI32 4 dstSz - let src191 = (sExt dstSz (extractHigh 1 src3B)) << numI32 5 dstSz - let src223 = (sExt dstSz (extractHigh 1 src4A)) << numI32 6 dstSz - let src255 = (sExt dstSz (extractHigh 1 src4B)) << numI32 7 dstSz - builder raise InvalidOperandException - match src with - | OprReg r -> mskpd r - | _ -> raise InvalidOperandSizeException - -let vmovq ins insAddr insLen ctxt = - let builder = new StmtBuilder (4) - let dst, src = getTwoOprs ins - startMark insAddr insLen builder - let n0 = num0 64 - let regToReg r1 r2 = - match Register.getKind r1, Register.getKind r2 with - | Register.Kind.XMM, Register.Kind.XMM -> - let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) - let srcA = getPseudoRegVar ctxt r2 1 - builder - let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) - let src = getRegVar ctxt r2 - builder - let dst = getRegVar ctxt r1 - let srcA = getPseudoRegVar ctxt r2 1 - builder raise InvalidOperandException - match dst, src with - | OprReg r1, OprReg r2 -> regToReg r1 r2 - | OprReg _, OprMem _ -> - let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) - let src = transOprToExpr ins insAddr insLen ctxt src - builder - let dst = transOprToExpr ins insAddr insLen ctxt dst - let srcA = getPseudoRegVar ctxt r 1 - builder raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vmovsd ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - startMark insAddr insLen builder - match ins.Operands with - | TwoOperands (OprMem _ , _) -> movsd ins insAddr insLen ctxt - | TwoOperands (OprReg _ as dst, src) -> - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src = transOprToExpr64 ins insAddr insLen ctxt src - builder ) - fillZeroHigh128 ctxt dst builder - endMark insAddr insLen builder - | ThreeOperands (dst, src1, src2)-> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, _src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let _src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - builder raise InvalidOperandException - -let vmovshdup ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let dst, src = getTwoOprs ins - startMark insAddr insLen builder - match getOperationSize ins with - | 128 -> - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insAddr insLen ctxt src - builder dst1 := extractHigh 32 src1) - builder dst1 := extractHigh 32 src1) - builder dst2 := extractHigh 32 src2) - builder dst2 := extractHigh 32 src2) - fillZeroHigh128 ctxt dst builder - | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insAddr insLen ctxt dst - let src4, src3, src2, src1 = transOprToExpr256 ins insAddr insLen ctxt src - builder dst1 := extractHigh 32 src1) - builder dst1 := extractHigh 32 src1) - builder dst2 := extractHigh 32 src2) - builder dst2 := extractHigh 32 src2) - builder dst3 := extractHigh 32 src3) - builder dst3 := extractHigh 32 src3) - builder dst4 := extractHigh 32 src4) - builder dst4 := extractHigh 32 src4) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vmovsldup ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let dst, src = getTwoOprs ins - startMark insAddr insLen builder - match getOperationSize ins with - | 128 -> - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insAddr insLen ctxt src - builder dst1 := extractLow 32 src1) - builder dst1 := extractLow 32 src1) - builder dst2 := extractLow 32 src2) - builder dst2 := extractLow 32 src2) - fillZeroHigh128 ctxt dst builder - | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insAddr insLen ctxt dst - let src4, src3, src2, src1 = transOprToExpr256 ins insAddr insLen ctxt src - builder dst1 := extractLow 32 src1) - builder dst1 := extractLow 32 src1) - builder dst2 := extractLow 32 src2) - builder dst2 := extractLow 32 src2) - builder dst3 := extractLow 32 src3) - builder dst3 := extractLow 32 src3) - builder dst4 := extractLow 32 src4) - builder dst4 := extractLow 32 src4) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vmovss ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - startMark insAddr insLen builder - match ins.Operands with - | TwoOperands (OprMem _ , _) -> movss ins insAddr insLen ctxt - | TwoOperands (OprReg _ as dst, src) -> - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src = transOprToExpr32 ins insAddr insLen ctxt src - builder dst1 := src) - builder dst1 := num0 32) - builder ) - fillZeroHigh128 ctxt dst builder - endMark insAddr insLen builder - | ThreeOperands (dst, src1, src2)-> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let _src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - builder dstA := extractLow 32 src2A) - builder dstA := extractHigh 32 src1A) - builder raise InvalidOperandException - -let vmovups ins insAddr insLen ctxt = buildVectorMove ins insAddr insLen ctxt - -let vmovupd ins insAddr insLen ctxt = buildVectorMove ins insAddr insLen ctxt - -let vmulpd ins insAddr insLen ctxt = - vexedPackedFPBinOp64 ins insAddr insLen ctxt fmul - -let vmulps ins insAddr insLen ctxt = - vexedPackedFPBinOp32 ins insAddr insLen ctxt fmul - -let vmulsd ins insAddr insLen ctxt = - vexedScalarFPBinOp ins insAddr insLen ctxt 64 fmul - -let vmulss ins insAddr insLen ctxt = - vexedScalarFPBinOp ins insAddr insLen ctxt 32 fmul - -let vorpd ins insAddr insLen ctxt = - vexedPackedFPBinOp64 ins insAddr insLen ctxt (.|) - -let vorps ins insAddr insLen ctxt = - vexedPackedFPBinOp32 ins insAddr insLen ctxt (.|) - -let vpaddb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 (opP (.+)) 32 - -let vpaddd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 (opP (.+)) 16 - -let vpaddq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 (opP (.+)) 16 - -let vpalignr ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let dst, src1, src2, imm = getFourOprs ins - let oprSize = getOperationSize ins - let imm = transOprToExpr ins insAddr insLen ctxt imm - let n8 = numU32 8u 256 - let imm = zExt 256 imm - startMark insAddr insLen builder - if oprSize = 128 then - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - let t = tmpVar 256 - let tSrc1, tSrc2 = tmpVars2 oprSize - builder > (imm .* n8)) - builder t) - builder (extractLow 128 t)) - fillZeroHigh128 ctxt dst builder - elif oprSize = 256 then - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let src1D, src1C, src1B, src1A = transOprToExpr256 ins insAddr insLen ctxt src1 - let src2D, src2C, src2B, src2A = transOprToExpr256 ins insAddr insLen ctxt src2 - let t1, t2 = tmpVars2 256 - let tSrc1High, tSrc1Low, tSrc2High, tSrc2Low = tmpVars4 128 - builder > (imm .* n8)) - builder t1) - builder (extractLow 128 t1)) - builder > (imm .* n8)) - builder t2) - builder (extractLow 128 t2)) - else raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vpand ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPand 16 - -let vpandn ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPandn 16 - -let vpbroadcastb ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src = getTwoOprs ins - let oprSize = getOperationSize ins - let src = - match src with - | OprReg _ -> transOprToExpr128 ins insAddr insLen ctxt src |> snd - | OprMem _ -> transOprToExpr ins insAddr insLen ctxt src - | _ -> raise InvalidOperandException - |> extractLow 8 - let tSrc = tmpVar 8 - startMark insAddr insLen builder - builder tmpVar 8) - for i in 0 .. 7 do builder - builder -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - builder -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - builder raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vpcmpeqb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPcmpeqb 64 - -let vpcmpeqd ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPcmpeqd 32 - -let vpcmpeqq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPcmpeqq 16 - -let vpcmpgtb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPcmpgtb 64 - -let vpminub ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPminub 64 - -let vpminud ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPminud 32 - -let opVpmuludq _ = - let low32 expr = expr .& numI64 0xffffffffL 64 - Array.map2 (fun e1 e2 -> low32 e1 .* low32 e2) - -let vpmuludq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opVpmuludq 16 - -let vpor ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPor 8 - -let vpshufb ins insAddr insLen ctxt = - let dst, src1, src2 = getThreeOprs ins - let oprSize = getOperationSize ins - let cnt = if oprSize = 128 then 16 else 32 - let builder = new StmtBuilder (2 * cnt) - let tDst, tSrc1, tSrc2 = tmpVars3 oprSize - startMark insAddr insLen builder - match oprSize with - | 128 -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - builder tmpVar 8) - let mask = numU32 0x0Fu 8 - for i in 0 .. cnt - 1 do - let cond = extract tSrc2 1 (i * 8 + 7) - let idx = (extract tSrc2 8 (i * 8)) .& mask - let s = zExt oprSize idx .* numI32 8 oprSize - builder ) (extractLow 8 (tSrc1 >> s))) - done - builder tDst) - builder tDst) - | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let src1D, src1C, src1B, src1A = - transOprToExpr256 ins insAddr insLen ctxt src1 - let src2D, src2C, src2B, src2A = - transOprToExpr256 ins insAddr insLen ctxt src2 - builder tmpVar 8) - let mask = numU32 0x0Fu 8 - for i in 0 .. cnt - 1 do - let cond = extract tSrc2 1 (i * 8 + 7) - let idx = (extract tSrc2 8 (i * 8)) .& mask - let s = zExt oprSize idx .* numI32 8 oprSize - builder ) (extractLow 8 (tSrc1 >> s))) - done - builder tDst) - builder 64) - builder (RegType.toBitWidth (typeOf tDst) - 64)) - builder tDst) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vpshufd ins insAddr insLen ctxt = - let dst, src, ord = getThreeOprs ins - let ord = transOprToExpr ins insAddr insLen ctxt ord - let oprSize = getOperationSize ins - let cnt = RegType.toBitWidth oprSize / 32 - let builder = new StmtBuilder (2 * cnt) - let tmps = Array.init cnt (fun _ -> tmpVar 32) - let n32 = numI32 32 oprSize - let mask2 = numI32 3 32 (* 2-bit mask *) - let tSrc = tmpVar oprSize - let tDst = tmpVar oprSize - let shuffleDword src = - for i in 1 .. cnt do - let order = - ((extractLow 32 ord) >> (numI32 ((i - 1) * 2) 32)) .& mask2 - let order' = zExt oprSize order - builder (src >> (order' .* n32))) - done - startMark insAddr insLen builder - match oprSize with - | 128 -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - builder 0) - builder 64) - fillZeroHigh128 ctxt dst builder - | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insAddr insLen ctxt src - builder 0) - builder 64) - builder 128) - builder 192) - fillZeroHigh256 ctxt dst builder - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let opShiftVpackedDataLogical oprSize packSz shift src1 (src2: Expr []) = - let count = src2.[0] |> zExt oprSize - let cond = gt count (numI32 ((int packSz) - 1) oprSize) - let shifted expr = extract (shift (zExt oprSize expr) count) packSz 0 - Array.map (fun e -> ite cond (num0 packSz) (shifted e)) src1 - -let opVpslld oprSize = opShiftVpackedDataLogical oprSize 32 (<<) - -let vpslld ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opVpslld 16 - -let opVpsrld oprSize = opShiftVpackedDataLogical oprSize 32 (<<) - -let vpsrld ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opVpsrld 16 - -let shiftVDQ ins insAddr insLen ctxt shift = - let builder = new StmtBuilder (8) - let dst, src, cnt = getThreeOprs ins - let cnt = transOprToExpr ins insAddr insLen ctxt cnt |> castNum 8 - let oprSize = getOperationSize ins - let t = tmpVar 8 - startMark insAddr insLen builder - builder ) cnt) (numU32 16u 8) cnt) - match oprSize with - | 128 -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - let tDst, tSrc = tmpVars2 128 - builder )))) - builder tDst) - builder tDst) - fillZeroHigh128 ctxt dst builder - | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insAddr insLen ctxt src - let tDst, tSrc = tmpVars2 256 - builder )))) - builder tDst) - builder tDst) - builder 128) - builder tDst) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -(* -let opVpslldq oprSize = opShiftVpackedDataLogical oprSize 128 (<<) -let opVpslrdq oprSize = opShiftVpackedDataLogical oprSize 128 (>>) - -let vpslldq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 128 opVpslldq 16 - -let vpsrldq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 128 opVpslrdq 16 -*) - -let vpslldq ins insAddr insLen ctxt = shiftVDQ ins insAddr insLen ctxt (<<) -let vpsrldq ins insAddr insLen ctxt = shiftVDQ ins insAddr insLen ctxt (>>) - -let opVpsllq oprSize = opShiftVpackedDataLogical oprSize 64 (<<) -let opVpsrlq oprSize = opShiftVpackedDataLogical oprSize 64 (>>) - -let vpsllq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opVpsllq 16 - -let vpsrlq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opVpsllq 16 - -let vpsubb ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 8 opPsub 128 - -let vpunpckhdq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPunpckHigh 16 - -let vpunpckhqdq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPunpckHigh 16 - -let vpunpckldq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPunpckLow 16 - -let vpunpcklqdq ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 64 opPunpckLow 16 - -let vpxor ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src1, src2 = getThreeOprs ins - let oprSize = getOperationSize ins - startMark insAddr insLen builder - match oprSize with - | 128 -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - builder src2B) - builder src2A) - fillZeroHigh128 ctxt dst builder - | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let src1D, src1C, src1B, src1A = - transOprToExpr256 ins insAddr insLen ctxt src1 - let src2D, src2C, src2B, src2A = - transOprToExpr256 ins insAddr insLen ctxt src2 - builder src2D) - builder src2C) - builder src2B) - builder src2A) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vshufpd ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src1, src2, imm = getFourOprs ins - let imm = transOprToExpr ins insAddr insLen ctxt imm - let cond1 = extractLow 1 imm - let cond2 = extract imm 1 1 - let cond3 = extract imm 1 2 - let cond4 = extract imm 1 3 - startMark insAddr insLen builder - match getOperationSize ins with - | 128 -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - builder -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ins insAddr insLen ctxt src1 - let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ins insAddr insLen ctxt src2 - builder raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vshufps ins insAddr insLen ctxt = - let builder = new StmtBuilder (32) - let dst, src1, src2, imm = getFourOprs ins - let imm = transOprToExpr ins insAddr insLen ctxt imm - let cond1 = extractLow 2 imm - let cond2 = extract imm 2 2 - let cond3 = extract imm 2 4 - let cond4 = extract imm 2 6 - let doShuf cond dst e1 e2 = - builder ) - builder ) (extractLow 32 e1) dst) - builder ) (extractHigh 32 e1) dst) - builder ) (extractLow 32 e2) dst) - builder ) (extractHigh 32 e2) dst) - startMark insAddr insLen builder - match getOperationSize ins with - | 128 -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let sr1B, sr1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let sr2B, sr2A = transOprToExpr128 ins insAddr insLen ctxt src2 - doShuf cond1 (extractLow 32 dstA) sr1A sr1B - doShuf cond2 (extractHigh 32 dstA) sr1A sr1B - doShuf cond3 (extractLow 32 dstB) sr2A sr2B - doShuf cond4 (extractHigh 32 dstB) sr2A sr2B - fillZeroHigh128 ctxt dst builder - | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ins insAddr insLen ctxt src1 - let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ins insAddr insLen ctxt src2 - doShuf cond1 (extractLow 32 dstA) sr1A sr1B - doShuf cond2 (extractHigh 32 dstA) sr1A sr1B - doShuf cond3 (extractLow 32 dstB) sr2A sr2B - doShuf cond4 (extractHigh 32 dstB) sr2A sr2B - doShuf cond1 (extractLow 32 dstC) sr1C sr1D - doShuf cond2 (extractHigh 32 dstC) sr1C sr1D - doShuf cond3 (extractLow 32 dstD) sr2C sr2D - doShuf cond4 (extractHigh 32 dstD) sr2C sr2D - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vsqrtpd ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let dst, src = getTwoOprs ins - let oprSz = getOperationSize ins - startMark insAddr insLen builder - match oprSz with - | 128 -> - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insAddr insLen ctxt src - builder -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insAddr insLen ctxt dst - let sr4, sr3, sr2, sr1 = transOprToExpr256 ins insAddr insLen ctxt src - builder raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vsqrtps ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let dst, src = getTwoOprs ins - let oprSz = getOperationSize ins - let do32PackedSqrt dst64 src builder = - let dstA, dstB = extractLow 32 dst64, extractHigh 32 dst64 - let srcA, srcB = extractLow 32 src, extractHigh 32 src - builder -> - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insAddr insLen ctxt src - do32PackedSqrt dst1 srcA builder - do32PackedSqrt dst2 srcB builder - fillZeroHigh128 ctxt dst builder - | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insAddr insLen ctxt dst - let srD, srC, srB, srA = transOprToExpr256 ins insAddr insLen ctxt src - do32PackedSqrt dst1 srA builder - do32PackedSqrt dst2 srB builder - do32PackedSqrt dst3 srC builder - do32PackedSqrt dst4 srD builder - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vsqrts ins insAddr insLen ctxt sz = - let builder = new StmtBuilder (16) - let dst, src1, src2 = getThreeOprs ins - let dst2, dst1 = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - startMark insAddr insLen builder - match sz with - | 32 -> - let src2 = transOprToExpr32 ins insAddr insLen ctxt src2 - builder dst1 := fSqrt src2) - builder dst1 := extractHigh 32 src1A) - | 64 -> - let src2 = transOprToExpr64 ins insAddr insLen ctxt src2 - builder raise InvalidOperandSizeException - builder - -let vsqrtss ins insAddr insLen ctxt = - vsqrts ins insAddr insLen ctxt 32 - -let vsubpd ins insAddr insLen ctxt = - vexedPackedFPBinOp64 ins insAddr insLen ctxt fsub - -let vsubps ins insAddr insLen ctxt = - vexedPackedFPBinOp32 ins insAddr insLen ctxt fsub - -let vsubsd ins insAddr insLen ctxt = - vexedScalarFPBinOp ins insAddr insLen ctxt 64 fsub - -let vsubss ins insAddr insLen ctxt = - vexedScalarFPBinOp ins insAddr insLen ctxt 32 fsub - -let vunpckhpd ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src1, src2 = getThreeOprs ins - startMark insAddr insLen builder - match getOperationSize ins with - | 128 -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, _src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let src2B, _src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - builder -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let sr1D, _, sr1B, _ = transOprToExpr256 ins insAddr insLen ctxt src1 - let sr2D, _, sr2B, _ = transOprToExpr256 ins insAddr insLen ctxt src2 - builder raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vunpckhps ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let dst, src1, src2 = getThreeOprs ins - startMark insAddr insLen builder - match getOperationSize ins with - | 128 -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let src1B, _src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let src2B, _src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - builder dstA := extractLow 32 src1B) - builder dstA := extractLow 32 src2B) - builder dstB := extractHigh 32 src1B) - builder dstB := extractHigh 32 src2B) - fillZeroHigh128 ctxt dst builder - | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let sr1D, _, sr1B, _ = transOprToExpr256 ins insAddr insLen ctxt src1 - let sr2D, _, sr2B, _ = transOprToExpr256 ins insAddr insLen ctxt src2 - builder dstA := extractLow 32 sr1B) - builder dstA := extractLow 32 sr2B) - builder dstB := extractHigh 32 sr1B) - builder dstB := extractHigh 32 sr2B) - builder dstC := extractLow 32 sr1D) - builder dstC := extractLow 32 sr2D) - builder dstD := extractHigh 32 sr1D) - builder dstD := extractHigh 32 sr2D) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vunpcklpd ins insAddr insLen ctxt = - let builder = new StmtBuilder (8) - let dst, src1, src2 = getThreeOprs ins - startMark insAddr insLen builder - match getOperationSize ins with - | 128 -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let _src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let _src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - builder -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let _, src1C, _, src1A = transOprToExpr256 ins insAddr insLen ctxt src1 - let _, src2C, _, src2A = transOprToExpr256 ins insAddr insLen ctxt src2 - builder raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vunpcklps ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let dst, src1, src2 = getThreeOprs ins - startMark insAddr insLen builder - match getOperationSize ins with - | 128 -> - let dstB, dstA = transOprToExpr128 ins insAddr insLen ctxt dst - let _src1B, src1A = transOprToExpr128 ins insAddr insLen ctxt src1 - let _src2B, src2A = transOprToExpr128 ins insAddr insLen ctxt src2 - builder dstA := extractLow 32 src1A) - builder dstA := extractLow 32 src2A) - builder dstB := extractHigh 32 src1A) - builder dstB := extractHigh 32 src2A) - fillZeroHigh128 ctxt dst builder - | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insAddr insLen ctxt dst - let _, src1C, _, src1A = transOprToExpr256 ins insAddr insLen ctxt src1 - let _, src2C, _, src2A = transOprToExpr256 ins insAddr insLen ctxt src2 - builder dstA := extractLow 32 src1A) - builder dstA := extractLow 32 src2A) - builder dstB := extractHigh 32 src1A) - builder dstB := extractHigh 32 src2A) - builder dstC := extractLow 32 src1C) - builder dstC := extractLow 32 src2C) - builder dstD := extractHigh 32 src1C) - builder dstD := extractHigh 32 src2C) - | _ -> raise InvalidOperandSizeException - endMark insAddr insLen builder - -let vxorpd ins insAddr insLen ctxt = - vexedPackedFPBinOp64 ins insAddr insLen ctxt (<+>) - -let vxorps ins insAddr insLen ctxt = - vexedPackedFPBinOp32 ins insAddr insLen ctxt (<+>) - -let vzeroupper ins insAddr insLen ctxt = - let builder = new StmtBuilder (32) - startMark insAddr insLen builder - let n0 = num0 64 - builder transOneOpr ins insAddr insLen ctxt - startMark insAddr insLen builder - builder transOneOpr ins insAddr insLen ctxt - startMark insAddr insLen builder - builder "#GP(0) error" - let lblSucc = lblSymbol "Succ" - let oprSize = getOperationSize ins - let ecxIsZero = getRegVar ctxt R.ECX == num0 oprSize - let edxIsZero = getRegVar ctxt R.EDX == num0 oprSize - let cond = ecxIsZero .& edxIsZero - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t = tmpVar oprSize - startMark insAddr insLen builder - builder transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let t = tmpVar oprSize - startMark insAddr insLen builder - builder (al .+ bx)) - endMark insAddr insLen builder - -let xor ins insAddr insLen ctxt = - let builder = new StmtBuilder (16) - let dst, src = getTwoOprs ins |> transTwoOprs ins insAddr insLen ctxt - let oprSize = getOperationSize ins - let r = tmpVar oprSize - startMark insAddr insLen builder - builder sExt oprSize src) - builder r) - builder opPxor 16 - -let xorps ins insAddr insLen ctxt = - buildPackedInstr ins insAddr insLen ctxt 32 opPxor 16 - -/// Translate IR. -let translate (ins: InsInfo) insAddr insLen ctxt = - match ins.Opcode with - | Opcode.AAA -> aaa ins insAddr insLen ctxt - | Opcode.AAD -> aad ins insAddr insLen ctxt - | Opcode.AAM -> aam ins insAddr insLen ctxt - | Opcode.AAS -> aas ins insAddr insLen ctxt - | Opcode.ADC -> adc ins insAddr insLen ctxt - | Opcode.ADD -> add ins insAddr insLen ctxt - | Opcode.ADDPD -> addpd ins insAddr insLen ctxt - | Opcode.AND -> logAnd ins insAddr insLen ctxt - | Opcode.ANDNPD -> andnpd ins insAddr insLen ctxt - | Opcode.ANDPS -> andps ins insAddr insLen ctxt - | Opcode.ARPL -> arpl ins insAddr insLen ctxt - | Opcode.BNDMOV -> bndmov ins insAddr insLen ctxt - | Opcode.BOUND -> nop insAddr insLen - | Opcode.BSF -> bsf ins insAddr insLen ctxt - | Opcode.BSR -> bsr ins insAddr insLen ctxt - | Opcode.BSWAP -> bswap ins insAddr insLen ctxt - | Opcode.BT -> bt ins insAddr insLen ctxt - | Opcode.BTC -> btc ins insAddr insLen ctxt - | Opcode.BTR -> btr ins insAddr insLen ctxt - | Opcode.BTS -> bts ins insAddr insLen ctxt - | Opcode.CALLNear -> call ins insAddr insLen ctxt false - | Opcode.CALLFar -> call ins insAddr insLen ctxt true - | Opcode.CBW | Opcode.CWDE | Opcode.CDQE -> convBWQ ins insAddr insLen ctxt - | Opcode.CLC -> clearFlag insAddr insLen ctxt R.CF - | Opcode.CLD -> clearFlag insAddr insLen ctxt R.DF - | Opcode.CLFLUSH -> nop insAddr insLen - | Opcode.CLI -> clearFlag insAddr insLen ctxt R.IF - | Opcode.CLRSSBSY -> nop insAddr insLen - | Opcode.CMC -> cmc ins insAddr insLen ctxt - | Opcode.CMOVO | Opcode.CMOVNO | Opcode.CMOVB | Opcode.CMOVAE - | Opcode.CMOVZ | Opcode.CMOVNZ | Opcode.CMOVBE | Opcode.CMOVA - | Opcode.CMOVS | Opcode.CMOVNS | Opcode.CMOVP | Opcode.CMOVNP - | Opcode.CMOVL | Opcode.CMOVGE | Opcode.CMOVLE | Opcode.CMOVG -> - cmovcc ins insAddr insLen ctxt - | Opcode.CMP -> cmp ins insAddr insLen ctxt - | Opcode.CMPSB | Opcode.CMPSW | Opcode.CMPSQ -> cmps ins insAddr insLen ctxt - | Opcode.CMPXCHG -> cmpxchg ins insAddr insLen ctxt - | Opcode.CMPXCHG8B | Opcode.CMPXCHG16B -> - compareExchangeBytes ins insAddr insLen ctxt - | Opcode.CPUID -> sideEffects insAddr insLen ProcessorID - | Opcode.CRC32 -> nop insAddr insLen - | Opcode.CWD | Opcode.CDQ | Opcode.CQO -> convWDQ ins insAddr insLen ctxt - | Opcode.DAA -> daa ins insAddr insLen ctxt - | Opcode.DAS -> das ins insAddr insLen ctxt - | Opcode.DEC -> dec ins insAddr insLen ctxt - | Opcode.DIV | Opcode.IDIV -> div ins insAddr insLen ctxt - | Opcode.ENDBR32 | Opcode.ENDBR64 -> nop insAddr insLen - | Opcode.ENTER -> enter ins insAddr insLen ctxt - | Opcode.FXRSTOR | Opcode.FXRSTOR64 -> fxrstor ins insAddr insLen ctxt - | Opcode.FXSAVE | Opcode.FXSAVE64 -> fxsave ins insAddr insLen ctxt - | Opcode.HLT -> sideEffects insAddr insLen Halt - | Opcode.IMUL -> imul ins insAddr insLen ctxt - | Opcode.INC -> inc ins insAddr insLen ctxt - | Opcode.INCSSPD | Opcode.INCSSPQ -> nop insAddr insLen - | Opcode.INSB | Opcode.INSW | Opcode.INSD -> insinstr ins insAddr insLen ctxt - | Opcode.INT -> interrupt ins insAddr insLen ctxt - | Opcode.INT3 -> sideEffects insAddr insLen Breakpoint - | Opcode.JMPFar | Opcode.JMPNear -> jmp ins insAddr insLen ctxt - | Opcode.JO | Opcode.JNO | Opcode.JB | Opcode.JNB - | Opcode.JZ | Opcode.JNZ | Opcode.JBE | Opcode.JA - | Opcode.JS | Opcode.JNS | Opcode.JP | Opcode.JNP - | Opcode.JL | Opcode.JNL | Opcode.JLE | Opcode.JG - | Opcode.JECXZ | Opcode.JRCXZ -> jcc ins insAddr insLen ctxt - | Opcode.LAHF -> sideEffects insAddr insLen ProcessorID - | Opcode.LDDQU -> lddqu ins insAddr insLen ctxt - | Opcode.LDMXCSR -> ldmxcsr ins insAddr insLen ctxt - | Opcode.LEA -> lea ins insAddr insLen ctxt - | Opcode.LEAVE -> leave ins insAddr insLen ctxt - | Opcode.LFENCE -> sideEffects insAddr insLen Fence - | Opcode.LODSB | Opcode.LODSW | Opcode.LODSD | Opcode.LODSQ -> - lods ins insAddr insLen ctxt - | Opcode.LOOP | Opcode.LOOPE | Opcode.LOOPNE -> loop ins insAddr insLen ctxt - | Opcode.LZCNT -> lzcnt ins insAddr insLen ctxt - | Opcode.LDS | Opcode.LES | Opcode.LFS | Opcode.LGS | Opcode.LSS -> - sideEffects insAddr insLen UnsupportedFAR - | Opcode.MFENCE -> sideEffects insAddr insLen Fence - | Opcode.MOV -> mov ins insAddr insLen ctxt - | Opcode.MOVAPD -> movapd ins insAddr insLen ctxt - | Opcode.MOVAPS -> movaps ins insAddr insLen ctxt - | Opcode.MOVBE -> movbe ins insAddr insLen ctxt - | Opcode.MOVD -> movd ins insAddr insLen ctxt - | Opcode.MOVDQ2Q -> movdq2q ins insAddr insLen ctxt - | Opcode.MOVDQA -> movdqa ins insAddr insLen ctxt - | Opcode.MOVDQU -> movdqu ins insAddr insLen ctxt - | Opcode.MOVHPD -> movhpd ins insAddr insLen ctxt - | Opcode.MOVLPD -> movlpd ins insAddr insLen ctxt - | Opcode.MOVMSKPD -> movmskpd ins insAddr insLen ctxt - | Opcode.MOVMSKPS -> movmskps ins insAddr insLen ctxt - | Opcode.MOVNTDQ -> movntdq ins insAddr insLen ctxt - | Opcode.MOVNTI -> movnti ins insAddr insLen ctxt - | Opcode.MOVQ -> movq ins insAddr insLen ctxt - | Opcode.MOVQ2DQ -> movq2dq ins insAddr insLen ctxt - | Opcode.MOVSB | Opcode.MOVSW | Opcode.MOVSQ -> movs ins insAddr insLen ctxt - | Opcode.MOVSD -> movsd ins insAddr insLen ctxt - | Opcode.MOVSX | Opcode.MOVSXD -> movsx ins insAddr insLen ctxt - | Opcode.MOVUPS -> movups ins insAddr insLen ctxt - | Opcode.MOVZX -> movzx ins insAddr insLen ctxt - | Opcode.MUL -> mul ins insAddr insLen ctxt - | Opcode.NEG -> neg ins insAddr insLen ctxt - | Opcode.NOP -> nop insAddr insLen - | Opcode.NOT -> not ins insAddr insLen ctxt - | Opcode.OR -> logOr ins insAddr insLen ctxt - | Opcode.OUTSB | Opcode.OUTSW | Opcode.OUTSD -> outs ins insAddr insLen ctxt - | Opcode.PACKSSDW -> packssdw ins insAddr insLen ctxt - | Opcode.PACKSSWB -> packsswb ins insAddr insLen ctxt - | Opcode.PACKUSWB -> packuswb ins insAddr insLen ctxt - | Opcode.PADDB -> paddb ins insAddr insLen ctxt - | Opcode.PADDD -> paddd ins insAddr insLen ctxt - | Opcode.PADDQ -> paddq ins insAddr insLen ctxt - | Opcode.PADDSB -> paddsb ins insAddr insLen ctxt - | Opcode.PADDSW -> paddsw ins insAddr insLen ctxt - | Opcode.PADDUSB -> paddusb ins insAddr insLen ctxt - | Opcode.PADDUSW -> paddusw ins insAddr insLen ctxt - | Opcode.PADDW -> paddw ins insAddr insLen ctxt - | Opcode.PALIGNR -> palignr ins insAddr insLen ctxt - | Opcode.PAND -> pand ins insAddr insLen ctxt - | Opcode.PANDN -> pandn ins insAddr insLen ctxt - | Opcode.PAUSE -> sideEffects insAddr insLen Pause - | Opcode.PAVGB -> pavgb ins insAddr insLen ctxt - | Opcode.PAVGW -> pavgw ins insAddr insLen ctxt - | Opcode.PCMPEQB -> pcmpeqb ins insAddr insLen ctxt - | Opcode.PCMPEQD -> pcmpeqd ins insAddr insLen ctxt - | Opcode.PCMPEQQ -> pcmpeqq ins insAddr insLen ctxt - | Opcode.PCMPEQW -> pcmpeqw ins insAddr insLen ctxt - | Opcode.PCMPGTB -> pcmpgtb ins insAddr insLen ctxt - | Opcode.PCMPGTD -> pcmpgtd ins insAddr insLen ctxt - | Opcode.PCMPGTW -> pcmpgtw ins insAddr insLen ctxt - | Opcode.PCMPESTRI | Opcode.PCMPESTRM | Opcode.PCMPISTRI | Opcode.PCMPISTRM -> - pcmpstr ins insAddr insLen ctxt - | Opcode.PEXTRW -> pextrw ins insAddr insLen ctxt - | Opcode.PINSRB -> pinsrb ins insAddr insLen ctxt - | Opcode.PINSRW -> pinsrw ins insAddr insLen ctxt - | Opcode.PMADDWD -> pmaddwd ins insAddr insLen ctxt - | Opcode.PMAXSB -> pmaxsb ins insAddr insLen ctxt - | Opcode.PMAXSW -> pmaxsw ins insAddr insLen ctxt - | Opcode.PMAXUB -> pmaxub ins insAddr insLen ctxt - | Opcode.PMINSB -> pminsb ins insAddr insLen ctxt - | Opcode.PMINSW -> pminsw ins insAddr insLen ctxt - | Opcode.PMINUB -> pminub ins insAddr insLen ctxt - | Opcode.PMINUD -> pminud ins insAddr insLen ctxt - | Opcode.PMOVMSKB -> pmovmskb ins insAddr insLen ctxt - | Opcode.PMULHW -> pmulhw ins insAddr insLen ctxt - | Opcode.PMULHUW -> pmulhuw ins insAddr insLen ctxt - | Opcode.PMULLW -> pmullw ins insAddr insLen ctxt - | Opcode.PMULUDQ -> pmuludq ins insAddr insLen ctxt - | Opcode.POP -> pop ins insAddr insLen ctxt - | Opcode.POPA -> popa ins insAddr insLen ctxt 16 - | Opcode.POPAD -> popa ins insAddr insLen ctxt 32 - | Opcode.POPCNT -> popcnt ins insAddr insLen ctxt - | Opcode.POPF | Opcode.POPFD | Opcode.POPFQ -> popf ins insAddr insLen ctxt - | Opcode.POR -> por ins insAddr insLen ctxt - | Opcode.PREFETCHNTA - | Opcode.PREFETCHT0 | Opcode.PREFETCHT1 - | Opcode.PREFETCHW | Opcode.PREFETCHT2 -> nop insAddr insLen - | Opcode.PSADBW -> psadbw ins insAddr insLen ctxt - | Opcode.PSHUFB -> pshufb ins insAddr insLen ctxt - | Opcode.PSHUFD -> pshufd ins insAddr insLen ctxt - | Opcode.PSHUFHW -> pshufhw ins insAddr insLen ctxt - | Opcode.PSHUFLW -> pshuflw ins insAddr insLen ctxt - | Opcode.PSHUFW -> pshufw ins insAddr insLen ctxt - | Opcode.PSLLD -> pslld ins insAddr insLen ctxt - | Opcode.PSLLDQ -> pslldq ins insAddr insLen ctxt - | Opcode.PSLLQ -> psllq ins insAddr insLen ctxt - | Opcode.PSLLW -> psllw ins insAddr insLen ctxt - | Opcode.PSRAD -> psrad ins insAddr insLen ctxt - | Opcode.PSRAW -> psraw ins insAddr insLen ctxt - | Opcode.PSRLD -> psrld ins insAddr insLen ctxt - | Opcode.PSRLDQ -> psrldq ins insAddr insLen ctxt - | Opcode.PSRLQ -> psrlq ins insAddr insLen ctxt - | Opcode.PSRLW -> psrlw ins insAddr insLen ctxt - | Opcode.PSUBB -> psubb ins insAddr insLen ctxt - | Opcode.PSUBD -> psubd ins insAddr insLen ctxt - | Opcode.PSUBQ -> psubq ins insAddr insLen ctxt - | Opcode.PSUBSB -> psubsb ins insAddr insLen ctxt - | Opcode.PSUBSW -> psubsw ins insAddr insLen ctxt - | Opcode.PSUBUSB -> psubusb ins insAddr insLen ctxt - | Opcode.PSUBUSW -> psubusw ins insAddr insLen ctxt - | Opcode.PSUBW -> psubw ins insAddr insLen ctxt - | Opcode.PTEST -> ptest ins insAddr insLen ctxt - | Opcode.PUNPCKHBW -> punpckhbw ins insAddr insLen ctxt - | Opcode.PUNPCKHDQ -> punpckhdq ins insAddr insLen ctxt - | Opcode.PUNPCKHQDQ -> punpckhqdq ins insAddr insLen ctxt - | Opcode.PUNPCKHWD -> punpckhwd ins insAddr insLen ctxt - | Opcode.PUNPCKLBW -> punpcklbw ins insAddr insLen ctxt - | Opcode.PUNPCKLDQ -> punpckldq ins insAddr insLen ctxt - | Opcode.PUNPCKLQDQ -> punpcklqdq ins insAddr insLen ctxt - | Opcode.PUNPCKLWD -> punpcklwd ins insAddr insLen ctxt - | Opcode.PUSH -> push ins insAddr insLen ctxt - | Opcode.PUSHA -> pusha ins insAddr insLen ctxt 16 - | Opcode.PUSHAD -> pusha ins insAddr insLen ctxt 32 - | Opcode.PUSHF | Opcode.PUSHFD | Opcode.PUSHFQ -> pushf ins insAddr insLen ctxt - | Opcode.PXOR -> pxor ins insAddr insLen ctxt - | Opcode.RCL -> rcl ins insAddr insLen ctxt - | Opcode.RCR -> rcr ins insAddr insLen ctxt - | Opcode.RDMSR | Opcode.RSM -> sideEffects insAddr insLen UnsupportedExtension - | Opcode.RDPKRU -> rdpkru ins insAddr insLen ctxt - | Opcode.RDPMC -> sideEffects insAddr insLen UnsupportedExtension - | Opcode.RDRAND -> sideEffects insAddr insLen UnsupportedExtension - | Opcode.RDSSPD | Opcode.RDSSPQ -> nop insAddr insLen - | Opcode.RDTSC -> sideEffects insAddr insLen ClockCounter - | Opcode.RDTSCP -> sideEffects insAddr insLen ClockCounter - | Opcode.RETNear -> ret ins insAddr insLen ctxt false false - | Opcode.RETNearImm -> ret ins insAddr insLen ctxt false true - | Opcode.RETFar -> ret ins insAddr insLen ctxt true false - | Opcode.RETFarImm -> ret ins insAddr insLen ctxt true true - | Opcode.ROL -> rol ins insAddr insLen ctxt - | Opcode.ROR -> ror ins insAddr insLen ctxt - | Opcode.RSTORSSP -> nop insAddr insLen - | Opcode.SAHF -> sahf ins insAddr insLen ctxt - | Opcode.SAR | Opcode.SHR | Opcode.SHL -> shift ins insAddr insLen ctxt - | Opcode.SAVEPREVSSP -> nop insAddr insLen - | Opcode.SBB -> sbb ins insAddr insLen ctxt - | Opcode.SCASB | Opcode.SCASW | Opcode.SCASD | Opcode.SCASQ -> - scas ins insAddr insLen ctxt - | Opcode.SETO | Opcode.SETNO | Opcode.SETB | Opcode.SETNB - | Opcode.SETZ | Opcode.SETNZ | Opcode.SETBE | Opcode.SETA - | Opcode.SETS | Opcode.SETNS | Opcode.SETP | Opcode.SETNP - | Opcode.SETL | Opcode.SETNL | Opcode.SETLE | Opcode.SETG -> - setcc ins insAddr insLen ctxt - | Opcode.SETSSBSY -> nop insAddr insLen - | Opcode.SFENCE -> sideEffects insAddr insLen Fence - | Opcode.SHLD -> shld ins insAddr insLen ctxt - | Opcode.SHRD -> shrd ins insAddr insLen ctxt - | Opcode.STC -> stc insAddr insLen ctxt - | Opcode.STD -> std insAddr insLen ctxt - | Opcode.STI -> sti insAddr insLen ctxt - | Opcode.STMXCSR -> stmxcsr ins insAddr insLen ctxt - | Opcode.STOSB | Opcode.STOSW | Opcode.STOSD | Opcode.STOSQ -> - stos ins insAddr insLen ctxt - | Opcode.SUB -> sub ins insAddr insLen ctxt - | Opcode.SUBPD -> subpd ins insAddr insLen ctxt - | Opcode.SYSCALL | Opcode.SYSENTER -> sideEffects insAddr insLen SysCall - | Opcode.TEST -> test ins insAddr insLen ctxt - | Opcode.TZCNT -> tzcnt ins insAddr insLen ctxt - | Opcode.UD2 -> sideEffects insAddr insLen UndefinedInstr - | Opcode.VBROADCASTI128 -> vbroadcasti128 ins insAddr insLen ctxt - | Opcode.VINSERTI128 -> vinserti128 ins insAddr insLen ctxt - | Opcode.VMOVD -> vmovd ins insAddr insLen ctxt - | Opcode.VMOVDQA -> vmovdqa ins insAddr insLen ctxt - | Opcode.VMOVDQU -> vmovdqu ins insAddr insLen ctxt - | Opcode.VMOVDQU64 -> vmovdqu64 ins insAddr insLen ctxt - | Opcode.VMOVNTDQ -> vmovntdq ins insAddr insLen ctxt - | Opcode.VMOVQ -> vmovq ins insAddr insLen ctxt - | Opcode.VMOVUPS -> vmovups ins insAddr insLen ctxt - | Opcode.VMPTRLD -> sideEffects insAddr insLen UnsupportedExtension - | Opcode.VPADDB -> vpaddb ins insAddr insLen ctxt - | Opcode.VPADDD -> vpaddd ins insAddr insLen ctxt - | Opcode.VPADDQ -> vpaddq ins insAddr insLen ctxt - | Opcode.VPALIGNR -> vpalignr ins insAddr insLen ctxt - | Opcode.VPAND -> vpand ins insAddr insLen ctxt - | Opcode.VPANDN -> vpandn ins insAddr insLen ctxt - | Opcode.VPBROADCASTB -> vpbroadcastb ins insAddr insLen ctxt - | Opcode.VPCMPEQB -> vpcmpeqb ins insAddr insLen ctxt - | Opcode.VPCMPEQD -> vpcmpeqd ins insAddr insLen ctxt - | Opcode.VPCMPEQQ -> vpcmpeqq ins insAddr insLen ctxt - | Opcode.VPCMPESTRI | Opcode.VPCMPESTRM | Opcode.VPCMPISTRI - | Opcode.VPCMPISTRM -> pcmpstr ins insAddr insLen ctxt - | Opcode.VPCMPGTB -> vpcmpgtb ins insAddr insLen ctxt - | Opcode.VPMINUB -> vpminub ins insAddr insLen ctxt - | Opcode.VPMINUD -> vpminud ins insAddr insLen ctxt - | Opcode.VPMOVMSKB -> pmovmskb ins insAddr insLen ctxt - | Opcode.VPMULUDQ -> vpmuludq ins insAddr insLen ctxt - | Opcode.VPOR -> vpor ins insAddr insLen ctxt - | Opcode.VPSHUFB -> vpshufb ins insAddr insLen ctxt - | Opcode.VPSHUFD -> vpshufd ins insAddr insLen ctxt - | Opcode.VPSLLD -> vpslld ins insAddr insLen ctxt - | Opcode.VPSLLDQ -> vpslldq ins insAddr insLen ctxt - | Opcode.VPSLLQ -> vpsllq ins insAddr insLen ctxt - | Opcode.VPSRLD -> vpsrld ins insAddr insLen ctxt - | Opcode.VPSRLDQ -> vpsrldq ins insAddr insLen ctxt - | Opcode.VPSRLQ -> vpsrlq ins insAddr insLen ctxt - | Opcode.VPSUBB -> vpsubb ins insAddr insLen ctxt - | Opcode.VPTEST -> vptest ins insAddr insLen ctxt - | Opcode.VPUNPCKHDQ -> vpunpckhdq ins insAddr insLen ctxt - | Opcode.VPUNPCKHQDQ -> vpunpckhqdq ins insAddr insLen ctxt - | Opcode.VPUNPCKLDQ -> vpunpckldq ins insAddr insLen ctxt - | Opcode.VPUNPCKLQDQ -> vpunpcklqdq ins insAddr insLen ctxt - | Opcode.VPXOR -> vpxor ins insAddr insLen ctxt - | Opcode.VZEROUPPER -> vzeroupper ins insAddr insLen ctxt - | Opcode.WRFSBASE -> wrfsbase ins insAddr insLen ctxt - | Opcode.WRGSBASE -> wrgsbase ins insAddr insLen ctxt - | Opcode.WRPKRU -> wrpkru ins insAddr insLen ctxt - | Opcode.WRSSD | Opcode.WRSSQ -> nop insAddr insLen - | Opcode.WRUSSD | Opcode.WRUSSQ -> nop insAddr insLen - | Opcode.XABORT -> sideEffects insAddr insLen UnsupportedExtension - | Opcode.XADD -> xadd ins insAddr insLen ctxt - | Opcode.XBEGIN -> sideEffects insAddr insLen UnsupportedExtension - | Opcode.XCHG -> xchg ins insAddr insLen ctxt - | Opcode.XEND -> sideEffects insAddr insLen UnsupportedExtension - | Opcode.XGETBV -> sideEffects insAddr insLen UnsupportedExtension - | Opcode.XLATB -> xlatb ins insAddr insLen ctxt - | Opcode.XOR -> xor ins insAddr insLen ctxt - | Opcode.XRSTOR | Opcode.XRSTORS | Opcode.XSAVE | Opcode.XSAVEC - | Opcode.XSAVEC64 | Opcode.XSAVEOPT | Opcode.XSAVES | Opcode.XSAVES64 -> - sideEffects insAddr insLen UnsupportedExtension - | Opcode.XTEST -> sideEffects insAddr insLen UnsupportedExtension - | Opcode.IN | Opcode.INTO | Opcode.INVD | Opcode.INVLPG | Opcode.IRETD - | Opcode.IRETQ | Opcode.IRETW | Opcode.LAR | Opcode.LGDT | Opcode.LLDT - | Opcode.LMSW | Opcode.LSL | Opcode.LTR | Opcode.OUT | Opcode.SGDT - | Opcode.SIDT | Opcode.SLDT | Opcode.SMSW | Opcode.STR | Opcode.VERR - | Opcode.VERW -> sideEffects insAddr insLen UnsupportedPrivInstr - | Opcode.ADDPS -> addps ins insAddr insLen ctxt - | Opcode.ADDSD -> addsd ins insAddr insLen ctxt - | Opcode.ADDSS -> addss ins insAddr insLen ctxt - | Opcode.ANDNPS -> andnps ins insAddr insLen ctxt - | Opcode.ANDPD -> andpd ins insAddr insLen ctxt - | Opcode.CMPPD -> cmppd ins insAddr insLen ctxt - | Opcode.CMPPS -> cmpps ins insAddr insLen ctxt - | Opcode.COMISD | Opcode.VCOMISD -> comisd ins insAddr insLen ctxt - | Opcode.COMISS | Opcode.VCOMISS -> comiss ins insAddr insLen ctxt - | Opcode.CMPSD -> cmpsd ins insAddr insLen ctxt - | Opcode.CMPSS -> cmpss ins insAddr insLen ctxt - | Opcode.CVTDQ2PD -> cvtdq2pd ins insAddr insLen ctxt - | Opcode.CVTDQ2PS -> cvtdq2ps ins insAddr insLen ctxt - | Opcode.CVTPD2DQ -> cvtpd2dq ins insAddr insLen ctxt true - | Opcode.CVTPD2PI -> cvtpd2pi ins insAddr insLen ctxt true - | Opcode.CVTPD2PS -> cvtpd2ps ins insAddr insLen ctxt - | Opcode.CVTPI2PD -> cvtpi2pd ins insAddr insLen ctxt - | Opcode.CVTPI2PS -> cvtpi2ps ins insAddr insLen ctxt - | Opcode.CVTPS2DQ -> cvtps2dq ins insAddr insLen ctxt true - | Opcode.CVTPS2PD -> cvtps2pd ins insAddr insLen ctxt - | Opcode.CVTPS2PI -> cvtps2pi ins insAddr insLen ctxt true - | Opcode.CVTSD2SI | Opcode.VCVTSD2SI -> cvtsd2si ins insAddr insLen ctxt true - | Opcode.CVTSD2SS -> cvtsd2ss ins insAddr insLen ctxt - | Opcode.CVTSI2SD -> cvtsi2sd ins insAddr insLen ctxt - | Opcode.CVTSI2SS -> cvtsi2ss ins insAddr insLen ctxt - | Opcode.CVTSS2SD -> cvtss2sd ins insAddr insLen ctxt - | Opcode.CVTSS2SI | Opcode.VCVTSS2SI -> cvtss2si ins insAddr insLen ctxt true - | Opcode.CVTTPD2DQ -> cvtpd2dq ins insAddr insLen ctxt false - | Opcode.CVTTPD2PI -> cvtpd2pi ins insAddr insLen ctxt false - | Opcode.CVTTPS2DQ -> cvtps2dq ins insAddr insLen ctxt false - | Opcode.CVTTPS2PI -> cvtps2pi ins insAddr insLen ctxt false - | Opcode.CVTTSD2SI | Opcode.VCVTTSD2SI -> - cvtsd2si ins insAddr insLen ctxt false - | Opcode.CVTTSS2SI | Opcode.VCVTTSS2SI -> - cvtss2si ins insAddr insLen ctxt false - | Opcode.DIVPD -> divpd ins insAddr insLen ctxt - | Opcode.DIVPS -> divps ins insAddr insLen ctxt - | Opcode.DIVSD -> divsd ins insAddr insLen ctxt - | Opcode.DIVSS -> divss ins insAddr insLen ctxt - | Opcode.EMMS -> emms ins insAddr insLen ctxt - | Opcode.F2XM1 -> f2xm1 ins insAddr insLen ctxt - | Opcode.FABS -> fabs ins insAddr insLen ctxt - | Opcode.FADD -> fpuadd ins insAddr insLen ctxt false - | Opcode.FADDP -> fpuadd ins insAddr insLen ctxt true - | Opcode.FBLD -> fbld ins insAddr insLen ctxt - | Opcode.FBSTP -> fbstp ins insAddr insLen ctxt - | Opcode.FCHS -> fchs ins insAddr insLen ctxt - | Opcode.FCLEX -> fclex ins insAddr insLen ctxt - | Opcode.FCMOVB -> fcmovb ins insAddr insLen ctxt - | Opcode.FCMOVBE -> fcmovbe ins insAddr insLen ctxt - | Opcode.FCMOVE -> fcmove ins insAddr insLen ctxt - | Opcode.FCMOVNB -> fcmovnb ins insAddr insLen ctxt - | Opcode.FCMOVNBE -> fcmovnbe ins insAddr insLen ctxt - | Opcode.FCMOVNE -> fcmovne ins insAddr insLen ctxt - | Opcode.FCMOVNU -> fcmovnu ins insAddr insLen ctxt - | Opcode.FCMOVU -> fcmovu ins insAddr insLen ctxt - | Opcode.FDIV -> fpudiv ins insAddr insLen ctxt false - | Opcode.FDIVP -> fpudiv ins insAddr insLen ctxt true - | Opcode.FIADD -> fiadd ins insAddr insLen ctxt - | Opcode.FIDIV -> fidiv ins insAddr insLen ctxt - | Opcode.FIMUL -> fimul ins insAddr insLen ctxt - | Opcode.FISUB -> fisub ins insAddr insLen ctxt - | Opcode.FLD -> fld ins insAddr insLen ctxt - | Opcode.FLD1 -> fld1 ins insAddr insLen ctxt - | Opcode.FLDENV -> fldenv ins insAddr insLen ctxt - | Opcode.FLDL2E -> fldl2e ins insAddr insLen ctxt - | Opcode.FLDL2T -> fldl2t ins insAddr insLen ctxt - | Opcode.FLDPI -> fldpi ins insAddr insLen ctxt - | Opcode.FLDZ -> fldz ins insAddr insLen ctxt - | Opcode.FLDLG2 -> fldlg2 ins insAddr insLen ctxt - | Opcode.FLDLN2 -> fldln2 ins insAddr insLen ctxt - | Opcode.FLDCW -> fldcw ins insAddr insLen ctxt - | Opcode.FMUL -> fpumul ins insAddr insLen ctxt false - | Opcode.FMULP -> fpumul ins insAddr insLen ctxt true - | Opcode.FPREM -> fprem ins insAddr insLen ctxt false - | Opcode.FPREM1 -> fprem ins insAddr insLen ctxt true - | Opcode.FSQRT -> fsqrt ins insAddr insLen ctxt - | Opcode.FSUB -> fpusub ins insAddr insLen ctxt false - | Opcode.FSUBP -> fpusub ins insAddr insLen ctxt true - | Opcode.FCOM -> fcom ins insAddr insLen ctxt 0 false - | Opcode.FCOMP -> fcom ins insAddr insLen ctxt 1 false - | Opcode.FCOMPP -> fcom ins insAddr insLen ctxt 2 false - | Opcode.FCOMI -> fcomi ins insAddr insLen ctxt false - | Opcode.FCOMIP -> fcomi ins insAddr insLen ctxt true - | Opcode.FUCOMI -> fcomi ins insAddr insLen ctxt false - | Opcode.FUCOMIP -> fcomi ins insAddr insLen ctxt true - | Opcode.FCOS -> fcos ins insAddr insLen ctxt - | Opcode.FSIN -> fsin ins insAddr insLen ctxt - | Opcode.FDECSTP -> fdecstp ins insAddr insLen ctxt - | Opcode.FDIVR -> fdivr ins insAddr insLen ctxt false - | Opcode.FDIVRP -> fdivr ins insAddr insLen ctxt true - | Opcode.FSUBR -> fsubr ins insAddr insLen ctxt false - | Opcode.FSUBRP -> fsubr ins insAddr insLen ctxt true - | Opcode.FIDIVR -> fidivr ins insAddr insLen ctxt - | Opcode.FISUBR -> fisubr ins insAddr insLen ctxt - | Opcode.FFREE -> ffree ins insAddr insLen ctxt - | Opcode.FICOM -> ficom ins insAddr insLen ctxt false - | Opcode.FICOMP -> ficom ins insAddr insLen ctxt true - | Opcode.FILD -> fild ins insAddr insLen ctxt - | Opcode.FINCSTP -> fincstp ins insAddr insLen ctxt - | Opcode.FINIT -> finit ins insAddr insLen ctxt - | Opcode.FIST -> fist ins insAddr insLen ctxt false - | Opcode.FISTP -> fist ins insAddr insLen ctxt true - | Opcode.FISTTP -> fisttp ins insAddr insLen ctxt - | Opcode.FNOP -> fnop ins insAddr insLen ctxt - | Opcode.FNSTCW -> fnstcw ins insAddr insLen ctxt - | Opcode.FNSTSW -> fnstsw ins insAddr insLen ctxt - | Opcode.FPATAN -> fpatan ins insAddr insLen ctxt - | Opcode.FPTAN -> fptan ins insAddr insLen ctxt - | Opcode.FRNDINT -> frndint ins insAddr insLen ctxt - | Opcode.FRSTOR -> frstor ins insAddr insLen ctxt - | Opcode.FSAVE -> fsave ins insAddr insLen ctxt - | Opcode.FSCALE -> fscale ins insAddr insLen ctxt - | Opcode.FSINCOS -> fsincos ins insAddr insLen ctxt - | Opcode.FST -> ffst ins insAddr insLen ctxt false - | Opcode.FSTP -> ffst ins insAddr insLen ctxt true - | Opcode.FSTENV -> fstenv ins insAddr insLen ctxt - | Opcode.FSTCW -> fstcw ins insAddr insLen ctxt - | Opcode.FSTSW -> fstsw ins insAddr insLen ctxt - | Opcode.FTST -> ftst ins insAddr insLen ctxt - | Opcode.FUCOM -> fcom ins insAddr insLen ctxt 0 true - | Opcode.FUCOMP -> fcom ins insAddr insLen ctxt 1 true - | Opcode.FUCOMPP -> fcom ins insAddr insLen ctxt 2 true - | Opcode.FXCH -> fxch ins insAddr insLen ctxt - | Opcode.FXAM -> fxam ins insAddr insLen ctxt - | Opcode.FXTRACT -> fxtract ins insAddr insLen ctxt - | Opcode.FYL2X -> fyl2x ins insAddr insLen ctxt - | Opcode.FYL2XP1 -> fyl2xp1 ins insAddr insLen ctxt - | Opcode.MOVDDUP -> movddup ins insAddr insLen ctxt - | Opcode.MOVHLPS -> movhlps ins insAddr insLen ctxt - | Opcode.MOVHPS -> movhps ins insAddr insLen ctxt - | Opcode.MOVLHPS -> movlhps ins insAddr insLen ctxt - | Opcode.MOVLPS -> movlps ins insAddr insLen ctxt - | Opcode.MOVNTPD -> movntpd ins insAddr insLen ctxt - | Opcode.MOVNTPS -> movntps ins insAddr insLen ctxt - | Opcode.MOVNTQ -> movntq ins insAddr insLen ctxt - | Opcode.MOVSHDUP -> movshdup ins insAddr insLen ctxt - | Opcode.MOVSLDUP -> movsldup ins insAddr insLen ctxt - | Opcode.MOVSS -> movss ins insAddr insLen ctxt - | Opcode.MOVUPD -> movupd ins insAddr insLen ctxt - | Opcode.MULPD -> mulpd ins insAddr insLen ctxt - | Opcode.MULPS -> mulps ins insAddr insLen ctxt - | Opcode.MULSD -> mulsd ins insAddr insLen ctxt - | Opcode.MULSS -> mulss ins insAddr insLen ctxt - | Opcode.ORPD -> orpd ins insAddr insLen ctxt - | Opcode.ORPS -> orps ins insAddr insLen ctxt - | Opcode.SUBPS -> subps ins insAddr insLen ctxt - | Opcode.SUBSD -> subsd ins insAddr insLen ctxt - | Opcode.SUBSS -> subss ins insAddr insLen ctxt - | Opcode.SQRTPD -> sqrtpd ins insAddr insLen ctxt - | Opcode.SQRTPS -> sqrtps ins insAddr insLen ctxt - | Opcode.SQRTSD -> sqrtsd ins insAddr insLen ctxt - | Opcode.SQRTSS -> sqrtss ins insAddr insLen ctxt - | Opcode.XORPD -> xorpd ins insAddr insLen ctxt - | Opcode.XORPS -> xorps ins insAddr insLen ctxt - | Opcode.MAXPD -> maxpd ins insAddr insLen ctxt - | Opcode.MAXPS -> maxps ins insAddr insLen ctxt - | Opcode.MAXSD -> maxsd ins insAddr insLen ctxt - | Opcode.MAXSS -> maxss ins insAddr insLen ctxt - | Opcode.MINPD -> minpd ins insAddr insLen ctxt - | Opcode.MINPS -> minps ins insAddr insLen ctxt - | Opcode.MINSD -> minsd ins insAddr insLen ctxt - | Opcode.MINSS -> minss ins insAddr insLen ctxt - | Opcode.ROUNDSD -> roundsd ins insAddr insLen ctxt - | Opcode.SHUFPD -> shufpd ins insAddr insLen ctxt - | Opcode.SHUFPS -> shufps ins insAddr insLen ctxt - | Opcode.UCOMISD | Opcode.VUCOMISD -> ucomisd ins insAddr insLen ctxt - | Opcode.UCOMISS | Opcode.VUCOMISS -> ucomiss ins insAddr insLen ctxt - | Opcode.UNPCKHPD -> unpckhpd ins insAddr insLen ctxt - | Opcode.UNPCKHPS -> unpckhps ins insAddr insLen ctxt - | Opcode.UNPCKLPD -> unpcklpd ins insAddr insLen ctxt - | Opcode.UNPCKLPS -> unpcklps ins insAddr insLen ctxt - | Opcode.VADDPD -> vaddpd ins insAddr insLen ctxt - | Opcode.VADDPS -> vaddps ins insAddr insLen ctxt - | Opcode.VADDSD -> vaddsd ins insAddr insLen ctxt - | Opcode.VADDSS -> vaddss ins insAddr insLen ctxt - | Opcode.VANDNPD -> vandnpd ins insAddr insLen ctxt - | Opcode.VANDNPS -> vandnps ins insAddr insLen ctxt - | Opcode.VANDPD -> vandpd ins insAddr insLen ctxt - | Opcode.VANDPS -> vandps ins insAddr insLen ctxt - | Opcode.VBROADCASTSS -> vbroadcastss ins insAddr insLen ctxt - | Opcode.VCVTSI2SD -> vcvtsi2sd ins insAddr insLen ctxt - | Opcode.VCVTSI2SS -> vcvtsi2ss ins insAddr insLen ctxt - | Opcode.VDIVSD -> vdivsd ins insAddr insLen ctxt - | Opcode.VDIVSS -> vdivss ins insAddr insLen ctxt - | Opcode.VDIVPD -> vdivpd ins insAddr insLen ctxt - | Opcode.VDIVPS -> vdivps ins insAddr insLen ctxt - | Opcode.VCVTSD2SS -> vcvtsd2ss ins insAddr insLen ctxt - | Opcode.VCVTSS2SD -> vcvtss2sd ins insAddr insLen ctxt - | Opcode.VFMADD132SD -> vfmadd132sd ins insAddr insLen ctxt - | Opcode.VFMADD213SD -> vfmadd213sd ins insAddr insLen ctxt - | Opcode.VFMADD231SD -> vfmadd231sd ins insAddr insLen ctxt - | Opcode.VMOVAPS -> vmovdqu ins insAddr insLen ctxt - | Opcode.VMOVAPD -> vmovdqu ins insAddr insLen ctxt - | Opcode.VMOVDDUP -> vmovddup ins insAddr insLen ctxt - | Opcode.VMOVHLPS -> vmovhlps ins insAddr insLen ctxt - | Opcode.VMOVHPD | Opcode.VMOVHPS-> vmovhpd ins insAddr insLen ctxt - | Opcode.VMOVLHPS -> vmovlhps ins insAddr insLen ctxt - | Opcode.VMOVLPD | Opcode.VMOVLPS -> vmovlpd ins insAddr insLen ctxt - | Opcode.VMOVMSKPD -> vmovmskpd ins insAddr insLen ctxt - | Opcode.VMOVMSKPS -> vmovmskps ins insAddr insLen ctxt - | Opcode.VMOVNTPD -> vmovntpd ins insAddr insLen ctxt - | Opcode.VMOVNTPS -> vmovntps ins insAddr insLen ctxt - | Opcode.VMOVSD -> vmovsd ins insAddr insLen ctxt - | Opcode.VMOVSHDUP -> vmovshdup ins insAddr insLen ctxt - | Opcode.VMOVSLDUP -> vmovsldup ins insAddr insLen ctxt - | Opcode.VMOVSS -> vmovss ins insAddr insLen ctxt - | Opcode.VMOVUPD -> vmovupd ins insAddr insLen ctxt - | Opcode.VMULSD -> vmulsd ins insAddr insLen ctxt - | Opcode.VMULSS -> vmulss ins insAddr insLen ctxt - | Opcode.VMULPD -> vmulpd ins insAddr insLen ctxt - | Opcode.VMULPS -> vmulps ins insAddr insLen ctxt - | Opcode.VORPD -> vorpd ins insAddr insLen ctxt - | Opcode.VORPS -> vorps ins insAddr insLen ctxt - | Opcode.VSHUFPD -> vshufpd ins insAddr insLen ctxt - | Opcode.VSHUFPS -> vshufps ins insAddr insLen ctxt - | Opcode.VSQRTSD -> vsqrtsd ins insAddr insLen ctxt - | Opcode.VSQRTSS -> vsqrtss ins insAddr insLen ctxt - | Opcode.VSUBSD -> vsubsd ins insAddr insLen ctxt - | Opcode.VSUBSS -> vsubss ins insAddr insLen ctxt - | Opcode.VSUBPD -> vsubpd ins insAddr insLen ctxt - | Opcode.VSUBPS -> vsubps ins insAddr insLen ctxt - | Opcode.VSQRTPD -> vsqrtpd ins insAddr insLen ctxt - | Opcode.VSQRTPS -> vsqrtps ins insAddr insLen ctxt - | Opcode.VUNPCKHPD -> vunpckhpd ins insAddr insLen ctxt - | Opcode.VUNPCKHPS -> vunpckhps ins insAddr insLen ctxt - | Opcode.VUNPCKLPD -> vunpcklpd ins insAddr insLen ctxt - | Opcode.VUNPCKLPS -> vunpcklps ins insAddr insLen ctxt - | Opcode.VXORPD -> vxorpd ins insAddr insLen ctxt - | Opcode.VXORPS -> vxorps ins insAddr insLen ctxt - | Opcode.WAIT -> wait ins insAddr insLen ctxt - | o -> -#if DEBUG - eprintfn "%A" o - eprintfn "%A" ins -#endif - raise <| NotImplementedIRException (Disasm.opCodeToString o) - |> fun builder -> builder.ToStmts () - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/Intel/IntelParser.fs b/src/FrontEnd/Intel/IntelParser.fs deleted file mode 100644 index be803a44..00000000 --- a/src/FrontEnd/Intel/IntelParser.fs +++ /dev/null @@ -1,2528 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.FrontEnd.Intel.Parser - -open B2R2 -open B2R2.FrontEnd -open B2R2.FrontEnd.Intel -open B2R2.FrontEnd.Intel.RegGroup -open B2R2.FrontEnd.Intel.Helper -open B2R2.FrontEnd.Intel.Constants - -let emptyArr = Array.empty - -let private dsNor0F1A = [| emptyArr; BNDRbndBNDRMbnd; emptyArr; emptyArr |] -let private dsNor0F1B = [| emptyArr; BNDRMbndBNDRbnd; emptyArr; emptyArr |] -let private dsNor0F10 = [| VdqWdq; VdqWdq; VdqWdqd; VdqWdqq |] -let private dsVex0F10Mem = [| VpsWps; VpdWpd; VxWssd; VxWssq |] -let private dsVex0F10Reg = [| VpsWps; VpdWpd; VxHxWss; VxHxWsd |] -let private dsNor0F11 = [| WdqVdq; WdqVdq; WdqdVdq; WdqqVdq |] -let private dsVex0F11Mem = [| WpsVps; WpdVpd; WssdVx; WssqVx |] -let private dsVex0F11Reg = [| WpsVps; WpdVpd; WssHxVss; WsdHxVsd |] -let private dsNor0F12Mem = [| VdqMq; VdqMq; VdqWdq; VdqWdqq |] -let private dsNor0F12Reg = [| VdqUdq; VdqMq; VdqWdq; VdqWdqq |] -let private dsVex0F12Mem = [| VdqHdqMq; VdqHdqMdqd; VxWx; VxWx |] -let private dsVex0F12Reg = [| VdqHdqUdq; VdqHdqMdqd; VxWx; VxWx |] -let private dsNor0F13 = [| MqVdq; MqVdq; emptyArr; emptyArr |] -let private dsVex0F13 = [| MqVdq; MqVdq; emptyArr; emptyArr |] -let private dsNor0F14 = [| VdqWdq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F14 = [| VxHxWx; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F15 = [| VdqWdq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F15 = [| VxHxWx; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F16Mem = [| VdqMq; VdqMq; VdqWdq; emptyArr |] -let private dsNor0F16Reg = [| VdqUdq; VdqMq; VdqWdq; emptyArr |] -let private dsVex0F16Mem = [| VdqHdqMq; VdqHdqMq; VxWx; emptyArr |] -let private dsVex0F16Reg = [| VdqHdqUdq; VdqHdqMq; VxWx; emptyArr |] -let private dsNor0F17 = [| MqVdq; MqVdq; emptyArr; emptyArr |] -let private dsVex0F17 = [| MqVdq; MqVdq; emptyArr; emptyArr |] -let private dsNor0F28 = [| VdqWdq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F28 = [| VpsWps; VpdWpd ; emptyArr; emptyArr |] -let private dsNor0F29 = [| WdqVdq; WdqVdq; emptyArr; emptyArr |] -let private dsVex0F29 = [| WpsVps; WpdVpd; emptyArr; emptyArr |] -let private dsNor0F2A = [| VdqQq; VdqQq; VdqEy; VdqEy |] -let private dsVex0F2A = [| emptyArr; emptyArr; VssHssEy; VsdHsdEy |] -let private dsNor0F2B = [| MdqVdq; MdqVdq; emptyArr; emptyArr |] -let private dsVex0F2B = [| MpsVps; MpdVpd; emptyArr; emptyArr |] -let private dsNor0F2C = [| PpiWdqq; PpiWdq; GyWssd; GyWsdq |] -let private dsVex0F2C = [| emptyArr; emptyArr; GyWssd; GyWsdq |] -let private dsNor0F2D = [| PpiWdqq; PpiWdq; GyWssd; GyWsdq |] -let private dsVex0F2D = [| emptyArr; emptyArr; GyWssd; GyWsdq |] -let private dsNor0F2E = [| VssWssd; VsdWsdq; emptyArr; emptyArr |] -let private dsVex0F2E = [| VssWssd; VsdWsdq; emptyArr; emptyArr |] -let private dsNor0F2F = [| VssWssd; VsdWsdq; emptyArr; emptyArr |] -let private dsVex0F2F = [| VssWssd; VsdWsdq; emptyArr; emptyArr |] -let private dsNor0F50 = [| GyUdq; GyUdq; emptyArr; emptyArr |] -let private dsVex0F50 = [| GyUps; GyUpd; emptyArr; emptyArr |] -let private dsNor0F51 = [| VdqWdq; VdqWdq; VdqWdqd; VdqWdqq |] -let private dsVex0F51 = [| VpsWps; VpdWpd; VssHssWss; VsdHsdWsd |] -let private dsNor0F54 = [| VdqWdq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F54 = [| VpsHpsWps; VpdHpdWpd; emptyArr; emptyArr |] -let private dsNor0F55 = [| VdqWdq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F55 = [| VpsHpsWps; VpdHpdWpd; emptyArr; emptyArr |] -let private dsNor0F56 = [| VdqWdq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F56 = [| VpsHpsWps; VpdHpdWpd; emptyArr; emptyArr |] -let private dsNor0F57 = [| VdqWdq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F57 = [| VpsHpsWps; VpdHpdWpd; emptyArr; emptyArr |] -let private dsNor0F58 = [| VdqWdq; VdqWdq; VdqWdqd; VdqWdqq |] -let private dsVex0F58 = [| VpsHpsWps; VpdHpdWpd; VssHssWssd; VsdHsdWsdq |] -let private dsNor0F59 = [| VdqWdq; VdqWdq; VdqWdqd; VdqWdqq |] -let private dsVex0F59 = [| VpsHpsWps; VpdHpdWpd; VssHssWssd; VsdHsdWsdq |] -let private dsNor0F5A = [| VdqWdqq; VdqWdq; VdqWdqd; VdqWdqq |] -let private dsVex0F5A = [| emptyArr; emptyArr; VssHssWssd; VssHssWsdq |] -let private dsNor0F5B = [| VdqWdq; VdqWdq; VdqWdq; emptyArr |] -let private dsVex0F5B = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsNor0F5C = [| VdqWdq; VdqWdq; VdqWdqd; VdqWdqq |] -let private dsVex0F5C = [| VpsHpsWps; VpdHpdWpd; VssHssWssd; VsdHsdWsdq |] -let private dsNor0F5D = [| VdqWdq; VdqWdq; VdqWdqd; VdqWdqq |] -let private dsVex0F5D = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsNor0F5E = [| VdqWdq; VdqWdq; VdqWdqd; VdqWdqq |] -let private dsVex0F5E = [| VpsHpsWps; VpdHpdWpd; VssHssWssd; VsdHsdWsdq |] -let private dsNor0F5F = [| VdqWdq; VdqWdq; VdqWdqd; VdqWdqq |] -let private dsVex0F5F = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsNor0F60 = [| PqQd; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F60 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F61 = [| PqQd; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F61 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F62 = [| PqQd; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F62 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F63 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F63 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F64 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F64 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F65 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F65 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F66 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F66 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F67 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F67 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F68 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F68 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F69 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F69 = [| emptyArr; VxHxWx; emptyArr; emptyArr|] -let private dsNor0F6A = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F6A = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F6B = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F6B = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F6C = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F6C = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F6D = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F6D = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F6EB64 = [| PdEy; VdqEy; emptyArr; emptyArr |] -let private dsNor0F6EB32 = [| PdEy; VdqEy; emptyArr; emptyArr |] -let private dsVex0F6EB64 = [| emptyArr; VdqEy; emptyArr; emptyArr |] -let private dsVex0F6EB32 = [| emptyArr; VdqEy; emptyArr; emptyArr |] -let private dsNor0F6F = [| PqQq; VdqWdq; VdqWdq; emptyArr |] -let private dsVex0F6F = [| emptyArr; VxWx; VxWx; emptyArr |] -let private dsEVex0F6FB64 = [| emptyArr; VZxzWZxz; VZxzWZxz; emptyArr |] -let private dsEVex0F6FB32 = [| emptyArr; VZxzWZxz; VZxzWZxz; emptyArr |] -let private dsNor0F70 = [| PqQqIb; VdqWdqIb; VdqWdqIb; VdqWdqIb |] -let private dsVex0F70 = [| emptyArr; VxWxIb; VxWxIb; VxWxIb |] -let private dsNor0F74 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F74 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F75 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F75 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F76 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F76 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F77 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F77 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsNor0F7EB64 = [| EyPq; EyVdq; VdqWdqq; emptyArr |] -let private dsNor0F7EB32 = [| EyPq; EyVdq; VdqWdqq; emptyArr |] -let private dsVex0F7EB64 = [| emptyArr; EyVdq; VdqWdqq; emptyArr |] -let private dsVex0F7EB32 = [| emptyArr; EyVdq; VdqWdqq; emptyArr |] -let private dsNor0F7F = [| QqPq; WdqVdq; WdqVdq; emptyArr |] -let private dsVex0F7F = [| emptyArr; WxVx; WxVx; emptyArr |] -let private dsEVex0F7FB64 = [| emptyArr; WZxzVZxz; emptyArr; emptyArr |] -let private dsEVex0F7FB32 = [| emptyArr; WZxzVZxz; emptyArr; emptyArr |] -let private dsNor0FC2 = [| VdqWdqIb; VdqWdqIb; VssWssdIb; VsdWsdqIb |] -let private dsVex0FC2 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsNor0FC4 = [| PqEdwIb; VdqEdwIb; emptyArr; emptyArr |] -let private dsVex0FC4 = [| emptyArr; VdqHdqEdwIb; emptyArr; emptyArr |] -let private dsNor0FC5 = [| GdNqIb; GdUdqIb; emptyArr; emptyArr |] -let private dsVex0FC5 = [| emptyArr; GdUdqIb; emptyArr; emptyArr |] -let private dsNor0FC6 = [| VdqWdqIb; VdqWdqIb; emptyArr; emptyArr |] -let private dsVex0FC6 = [| VpsHpsWpsIb; VpsHpsWpsIb; emptyArr; emptyArr |] -let private dsNor0FD1 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FD1 = [| emptyArr; VxHxWdq; emptyArr; emptyArr |] -let private dsNor0FD2 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FD2 = [| emptyArr; VxHxWdq; emptyArr; emptyArr |] -let private dsNor0FD3 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FD3 = [| emptyArr; VxHxWdq; emptyArr; emptyArr |] -let private dsNor0FD4 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FD4 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FD5 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FD5 = [| emptyArr; VxHxWx; emptyArr; emptyArr|] -let private dsNor0FD6 = [| emptyArr; WdqqVdq; VdqNq; PqUdq |] -let private dsVex0FD6 = [| emptyArr; WdqqVdq; emptyArr; emptyArr |] -let private dsNor0FD7 = [| GdNq; GdUdq; emptyArr; emptyArr |] -let private dsVex0FD7 = [| emptyArr; GyUx; emptyArr; emptyArr |] -let private dsNor0FD8 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FD8 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FD9 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FD9 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FDA = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FDA = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FDB = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FDB = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FDC = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FDC = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FDD = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FDD = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FDE = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FDE = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FDF = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FDF = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FE0 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FE0 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FE1 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FE1 = [| emptyArr; VxHxWdq; emptyArr; emptyArr |] -let private dsNor0FE2 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FE2 = [| emptyArr; VxHxWdq; emptyArr; emptyArr |] -let private dsNor0FE3 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FE3 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FE4 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FE4 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FE5 = [| PqQq; VdqWdq; emptyArr; emptyArr|] -let private dsVex0FE5 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FE6 = [| emptyArr; VdqWdq; VdqWdqq; VdqWdq |] -let private dsVex0FE6 = [| emptyArr; emptyArr; emptyArr; emptyArr|] -let private dsNor0FE7 = [| MqPq; MdqVdq; emptyArr; emptyArr |] -let private dsVex0FE7 = [| emptyArr; MxVx; emptyArr; emptyArr|] -let private dsEVex0FE7B64 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsEVex0FE7B32 = [| emptyArr; MZxzVZxz; emptyArr; emptyArr |] -let private dsNor0FE8 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FE8 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FE9 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FE9 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FEA = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FEA = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FEB = [| PqQq; VdqWdq; emptyArr; emptyArr; emptyArr |] -let private dsVex0FEB = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FEC = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FEC = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FED = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FED = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FEE = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FEE = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FEF = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FEF = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FF0 = [| emptyArr; emptyArr; emptyArr; VdqMdq |] -let private dsVex0FF0 = [| emptyArr; emptyArr; emptyArr; VxMx |] -let private dsNor0FF1 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FF1 = [| emptyArr; VxHxWdq; emptyArr; emptyArr |] -let private dsNor0FF2 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FF2 = [| emptyArr; VxHxWdq; emptyArr; emptyArr |] -let private dsNor0FF3 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FF3 = [| emptyArr; VxHxWdq; emptyArr; emptyArr |] -let private dsNor0FF4 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FF4 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FF5 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FF5 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FF6 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FF6 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FF8 = [| PqQq; VdqWdq; emptyArr; emptyArr|] -let private dsVex0FF8 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FF9 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FF9 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FFA = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FFA = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FFB = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FFB = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FFC = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FFC = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FFD = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FFD = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0FFE = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0FFE = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3800 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3800 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3801 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3801 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3802 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3802 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3803 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3803 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3805 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3805 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3806 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3806 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3807 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3807 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3808 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3808 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3809 = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3809 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F380A = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F380A = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F380B = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F380B = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3817 = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3817 = [| emptyArr; VxWx; emptyArr; emptyArr |] -let private dsNor0F3818 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F3818 = [| emptyArr; VxMd; emptyArr; emptyArr |] -let private dsEVex0F3818 = [| emptyArr; VZxzWdqd; emptyArr; emptyArr |] -let private dsNor0F381C = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F381C = [| emptyArr; VxWx; emptyArr; emptyArr |] -let private dsNor0F381D = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F381D = [| emptyArr; VxWx; emptyArr; emptyArr |] -let private dsNor0F381E = [| PqQq; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F381E = [| emptyArr; VxWx; emptyArr; emptyArr |] -let private dsNor0F3820 = [| emptyArr; VdqWdqq; emptyArr; emptyArr |] -let private dsVex0F3820 = [| emptyArr; VxWdqqdq; emptyArr; emptyArr |] -let private dsNor0F3821 = [| emptyArr; VdqWdqd; emptyArr; emptyArr |] -let private dsVex0F3821 = [| emptyArr; VxWdqdq; emptyArr; emptyArr |] -let private dsNor0F3822 = [| emptyArr; VdqWdqw; emptyArr; emptyArr |] -let private dsVex0F3822 = [| emptyArr; VxWdqwd; emptyArr; emptyArr |] -let private dsNor0F3823 = [| emptyArr; VdqWdqq; emptyArr; emptyArr |] -let private dsVex0F3823 = [| emptyArr; VxWdqqdq; emptyArr; emptyArr |] -let private dsNor0F3824 = [| emptyArr; VdqWdqd; emptyArr; emptyArr |] -let private dsVex0F3824 = [| emptyArr; VxWdqdq; emptyArr; emptyArr |] -let private dsNor0F3825 = [| emptyArr; VdqWdqq; emptyArr; emptyArr |] -let private dsVex0F3825 = [| emptyArr; VxWdqqdq; emptyArr; emptyArr |] -let private dsNor0F3828 = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3828 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3829 = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3829 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F382B = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F382B = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3830 = [| emptyArr; VdqWdqq; emptyArr; emptyArr |] -let private dsVex0F3830 = [| emptyArr; VxWdqqdq; emptyArr; emptyArr |] -let private dsNor0F3831 = [| emptyArr; VdqWdqd; emptyArr; emptyArr |] -let private dsVex0F3831 = [| emptyArr; VxWdqdq; emptyArr; emptyArr |] -let private dsNor0F3832 = [| emptyArr; VdqWdqw; emptyArr; emptyArr |] -let private dsVex0F3832 = [| emptyArr; VxWdqwd; emptyArr; emptyArr |] -let private dsNor0F3833 = [| emptyArr; VdqWdqq; emptyArr; emptyArr |] -let private dsVex0F3833 = [| emptyArr; VxWdqqdq; emptyArr; emptyArr |] -let private dsNor0F3834 = [| emptyArr; VdqWdqd; emptyArr; emptyArr |] -let private dsVex0F3834 = [| emptyArr; VxWdqdq; emptyArr; emptyArr |] -let private dsNor0F3835 = [| emptyArr; VdqWdqq; emptyArr; emptyArr |] -let private dsVex0F3835 = [| emptyArr; VxWdqqdq; emptyArr; emptyArr |] -let private dsNor0F3837 = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3837 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3838 = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3838 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3839 = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3839 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F383A = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F383A = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F383B = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F383B = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F383C = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F383C = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F383D = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F383D = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F383E = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F383E = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F383F = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F383F = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3840 = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3840 = [| emptyArr; VxHxWx; emptyArr; emptyArr |] -let private dsNor0F3841 = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsVex0F3841 = [| emptyArr; VdqWdq; emptyArr; emptyArr |] -let private dsNor0F385A = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F385A = [| emptyArr; VqqMdq; emptyArr; emptyArr |] -let private dsNor0F3878 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F3878 = [| emptyArr; VxWx; emptyArr; emptyArr |] -let private dsNor0F3899W0 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F3899W0 = [| emptyArr; VxHxWdqd; emptyArr; emptyArr |] -let private dsNor0F3899W1 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F3899W1 = [| emptyArr; VxHxWdqq; emptyArr; emptyArr |] -let private dsNor0F38A9W0 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F38A9W0 = [| emptyArr; VxHxWdqd; emptyArr; emptyArr |] -let private dsNor0F38A9W1 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F38A9W1 = [| emptyArr; VxHxWdqq; emptyArr; emptyArr |] -let private dsNor0F38B9W0 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F38B9W0 = [| emptyArr; VxHxWdqd; emptyArr; emptyArr |] -let private dsNor0F38B9W1 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F38B9W1 = [| emptyArr; VxHxWdqq; emptyArr; emptyArr |] -let private dsNor0F38F0 = [| GyMy; GwMw; emptyArr; GvEb; GdEb |] -let private dsNor0F38F1 = [| MyGy; MwGw; emptyArr; GvEy; GdEw |] -let private dsNor0F38F5W0 = [| emptyArr; EvGv; emptyArr; emptyArr |] -let private dsNor0F38F5W1 = [| emptyArr; EvGv; emptyArr; emptyArr |] -let private dsVex0F38F5W0 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F38F5W1 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsNor0F38F6W0 = [| EvGv; emptyArr; emptyArr; emptyArr |] -let private dsNor0F38F6W1 = [| EvGv; emptyArr; emptyArr; emptyArr |] -let private dsVex0F38F6W0 = [| emptyArr; emptyArr; emptyArr; GyByEy |] -let private dsVex0F38F6W1 = [| emptyArr; emptyArr; emptyArr; GyByEy |] -let private dsNor0F38F7 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F38F7 = [| emptyArr; GyEyBy; GyEyBy; GyEyBy |] -let private dsNor0F3A0F = [| PqQqIb; VdqWdqIb; emptyArr; emptyArr |] -let private dsVex0F3A0F = [| emptyArr; VxHxWxIb; emptyArr; emptyArr |] -let private dsNor0F3A15 = [| emptyArr; EdwVdqIb; emptyArr; emptyArr |] -let private dsVex0F3A15 = [| emptyArr; EdwVdqIb; emptyArr; emptyArr |] -let private dsNor0F3A20 = [| emptyArr; VdqEdbIb; emptyArr; emptyArr |] -let private dsVex0F3A20 = [| emptyArr; VdqHdqEdbIb; emptyArr; emptyArr |] -let private dsNor0F3A38 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F3A38 = [| emptyArr; VqqHqqWdqIb; emptyArr; emptyArr |] -let private dsNor0F3A60 = [| emptyArr; VdqWdqIb; emptyArr; emptyArr |] -let private dsVex0F3A60 = [| emptyArr; VdqWdqIb; emptyArr; emptyArr |] -let private dsNor0F3A61 = [| emptyArr; VdqWdqIb; emptyArr; emptyArr |] -let private dsVex0F3A61 = [| emptyArr; VdqWdqIb; emptyArr; emptyArr |] -let private dsNor0F3A62 = [| emptyArr; VdqWdqIb; emptyArr; emptyArr |] -let private dsVex0F3A62 = [| emptyArr; VdqWdqIb; emptyArr; emptyArr |] -let private dsNor0F3A63 = [| emptyArr; VdqWdqIb; emptyArr; emptyArr |] -let private dsVex0F3A63 = [| emptyArr; VdqWdqIb; emptyArr; emptyArr |] -let private dsNor0F3A0B = [| emptyArr; VsdWsdqIb; emptyArr; emptyArr |] -let private dsVex0F3A0B = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsNor0F3AF0 = [| emptyArr; emptyArr; emptyArr; emptyArr |] -let private dsVex0F3AF0 = [| emptyArr; emptyArr; emptyArr; GyEyIb |] -let private dsEmpty = [| emptyArr; emptyArr; emptyArr; emptyArr |] - -let parsePrefix (reader: BinReader) pos = - let rec loop pos acc = - let nextPos = pos + 1 - match reader.PeekByte pos with - | 0xF0uy -> loop nextPos (Prefix.PrxLOCK ||| (clearGrp1PrefMask &&& acc)) - | 0xF2uy -> loop nextPos (Prefix.PrxREPNZ ||| (clearGrp1PrefMask &&& acc)) - | 0xF3uy -> loop nextPos (Prefix.PrxREPZ ||| (clearGrp1PrefMask &&& acc)) - | 0x2Euy -> loop nextPos (Prefix.PrxCS ||| (clearSegMask &&& acc)) - | 0x36uy -> loop nextPos (Prefix.PrxSS ||| (clearSegMask &&& acc)) - | 0x3Euy -> loop nextPos (Prefix.PrxDS ||| (clearSegMask &&& acc)) - | 0x26uy -> loop nextPos (Prefix.PrxES ||| (clearSegMask &&& acc)) - | 0x64uy -> loop nextPos (Prefix.PrxFS ||| (clearSegMask &&& acc)) - | 0x65uy -> loop nextPos (Prefix.PrxGS ||| (clearSegMask &&& acc)) - | 0x66uy -> loop nextPos (Prefix.PrxOPSIZE ||| acc) - | 0x67uy -> loop nextPos (Prefix.PrxADDRSIZE ||| acc) - | _opcode -> struct (acc, pos) - loop pos Prefix.PrxNone - -let inline private pBNDPref t = - if Helper.hasREPNZ t.TPrefixes then - { t with TPrefixes = Prefix.PrxBND ||| (clearGrp1PrefMask &&& t.TPrefixes) } - else t - -let inline private getREX (reader: BinReader) pos = - let rb = reader.PeekByte pos |> int |> LanguagePrimitives.EnumOfValue - if rb >= REXPrefix.REX && rb <= REXPrefix.REXWRXB then - struct (rb, pos + 1) - else struct (REXPrefix.NOREX, pos) - -let parseREX wordSize reader pos = - if wordSize = WordSize.Bit32 then struct (REXPrefix.NOREX, pos) - else getREX reader pos - -let inline private isRegOpr oprDesc = - match oprDesc with - | ODReg _ - | ODRegGrp _ - | ODModeSize (struct(OprMode.G, _)) - | ODModeSize (struct(OprMode.N, _)) - | ODModeSize (struct(OprMode.P, _)) - | ODModeSize (struct(OprMode.R, _)) - | ODModeSize (struct(OprMode.V, _)) - | ODModeSize (struct(OprMode.VZ, _)) -> true - | _ -> false - -let private getOperationSize regSize oprSize opCode (oprDescs: OperandDesc []) = - match opCode with - | Opcode.PUSH | Opcode.POP -> oprSize - | Opcode.MOVSB | Opcode.INSB - | Opcode.STOSB | Opcode.LODSB - | Opcode.OUTSB | Opcode.SCASB -> 8 - | Opcode.OUTSW -> 16 - | Opcode.OUTSD -> 32 - | _ -> if Array.isEmpty oprDescs then oprSize - else if isRegOpr (oprDescs.[0]) then regSize else oprSize - -let inline private selectREX vexInfo rexPref = - match vexInfo with - | None -> rexPref // t.TREXPrefix - | Some v -> v.VREXPrefix - -let inline private getVecLen t = (Option.get t.TVEXInfo).VectorLength -let inline private is32bit t = t.TWordSize = WordSize.Bit32 -let inline private is64bit t = t.TWordSize = WordSize.Bit64 -let inline private is64bitWithOprSz t = is64bit t && hasOprSz t.TPrefixes -let inline private is64bitWithAddrSz t = is64bit t && hasAddrSz t.TPrefixes -let inline private hasNoPref t = (int t.TPrefixes) = 0 -let inline private hasNoREX t = t.TREXPrefix = REXPrefix.NOREX -let inline private hasNoPrefNoREX t = hasNoPref t && hasNoREX t - -/// Returns a tuple (regSize, effOprSize) -let private getSizeBySzDesc t effOprSz szKind = - match szKind with - | OprSize.B -> struct (8, 8) - | OprSize.Bnd -> - struct (effOprSz, if is32bit t then 64 else 128) - | OprSize.W -> struct (16, 16) - | OprSize.D -> struct (32, 32) - | OprSize.DB -> struct (32, 8) - | OprSize.DW -> struct (32, 16) - | OprSize.P -> - if effOprSz = 16 then struct (16, 32) - elif effOprSz = 32 then struct (32, 48) - else struct (64, 80) - | OprSize.PI | OprSize.Q -> struct (64, 64) - | OprSize.DQW -> struct (128, 16) - | OprSize.DQD | OprSize.SSD -> struct (128, 32) - | OprSize.DQQDQ -> - if getVecLen t = 128 then struct (128, 64) - else struct (128, 128) - | OprSize.DQDQ -> - if getVecLen t = 128 then struct (128, 32) - else struct (128, 64) - | OprSize.DQWD -> - if getVecLen t = 128 then struct (128, 16) - else struct (128, 32) - | OprSize.DQQ | OprSize.SDQ | OprSize.SSQ -> struct (128, 64) - | OprSize.DQ | OprSize.SD | OprSize.SS -> struct (128, 128) - | OprSize.PSQ -> struct (getVecLen t, 64) - | OprSize.PD | OprSize.PS | OprSize.X | OprSize.XZ -> - struct (getVecLen t, getVecLen t) - | OprSize.QQ -> struct (256, 256) - | OprSize.Y -> - if is64bit t && hasREXW (selectREX t.TVEXInfo t.TREXPrefix) - then struct (64, 64) - else struct (32, 32) - | OprSize.Z -> - if effOprSz = 64 || effOprSz = 32 then struct (32, effOprSz) - else struct (effOprSz, effOprSz) - | _ -> struct (effOprSz, effOprSz) - -let isODRegGrp = function - | ODRegGrp _ -> true - | _ -> false - -let private convRegSize t effOprSz oprDesc oprDescs = - match oprDesc with - | ODModeSize (OprMode.G, sz) | ODModeSize (OprMode.N , sz) - | ODModeSize (OprMode.P, sz) | ODModeSize (OprMode.R , sz) - | ODModeSize (OprMode.V, sz) | ODModeSize (OprMode.VZ, sz) -> - let (struct (x, _)) = getSizeBySzDesc t effOprSz sz in x - | ODReg _ when (Array.length oprDescs > 1 && isODRegGrp (oprDescs.[1])) -> - 0 - | ODReg reg -> Register.toRegType reg - | ODRegGrp (_, sz, _) -> - let (struct (x, _)) = getSizeBySzDesc t effOprSz sz in x - | _ -> 0 - -let rec private findRegSize idx (oprDescs: OperandDesc []) t effOprSz ret = - let v = convRegSize t effOprSz oprDescs.[idx] oprDescs - if v <> 0 then v - elif idx = (Array.length oprDescs) - 1 then ret - else findRegSize (idx + 1) oprDescs t effOprSz ret - -(* defined in Table 3-4 of the manual Vol. 1. *) -let inline private getRegSize t oprDescs effOprSz = - if Array.isEmpty oprDescs then effOprSz - else findRegSize 0 oprDescs t effOprSz effOprSz - -let inline convMemSize descs = - match descs with - | ODModeSize (struct (OprMode.BndM, sz)) - | ODModeSize (struct (OprMode.E, sz)) - | ODModeSize (struct (OprMode.M, sz)) - | ODModeSize (struct (OprMode.MZ, sz)) - | ODModeSize (struct (OprMode.O, sz)) - | ODModeSize (struct (OprMode.Q, sz)) - | ODModeSize (struct (OprMode.U, sz)) - | ODModeSize (struct (OprMode.W, sz)) - | ODModeSize (struct (OprMode.WZ, sz)) - | ODModeSize (struct (OprMode.X, sz)) - | ODModeSize (struct (OprMode.Y, sz)) -> Some sz - | _ -> None - -(* Obtain both the effective operand size and the effective address size - using the rule defined in Table 3-4 of the manual Vol. 1. *) -let getMemSize t oprDescs effOprSz effAddrSz = - match Array.tryPick convMemSize oprDescs with - | None -> - { EffOprSize = effOprSz; EffAddrSize = effAddrSz; EffRegSize = effOprSz } - | Some sz -> - let struct (rSz, oprSz) = getSizeBySzDesc t effOprSz sz - { EffOprSize = oprSz; EffAddrSize = effAddrSz; EffRegSize = rSz } - -let inline getOprSize size sizeCond = - if sizeCond = Sz64 then 64 - elif size = 32 && sizeCond = SzDef64 then 64 - else size - -let inline getSize32 prefs = - if hasOprSz prefs then - if hasAddrSz prefs then struct (16, 16) else struct (16, 32) - else - if hasAddrSz prefs then struct (32, 16) else struct (32, 32) - -let inline getSize64 prefs rexPref sizeCond = - if hasREXW rexPref then - if hasAddrSz prefs then struct (64, 32) - else struct (64, 64) - else - if hasOprSz prefs then - if hasAddrSz prefs then struct (getOprSize 16 sizeCond, 32) - else struct (getOprSize 16 sizeCond, 64) - else - if hasAddrSz prefs then - struct (getOprSize 32 sizeCond, 32) - else struct (getOprSize 32 sizeCond, 64) - -let getSize t sizeCond = - if t.TWordSize = WordSize.Bit32 then getSize32 t.TPrefixes - else getSize64 t.TPrefixes (selectREX t.TVEXInfo t.TREXPrefix) sizeCond - -let newInsSize t sizeCond opCode oprDescs = - let struct (effOprSize, effAddrSize) = getSize t sizeCond - let rSize = getRegSize t oprDescs effOprSize - let mSize = getMemSize t oprDescs effOprSize effAddrSize - let opSize = getOperationSize rSize mSize.EffOprSize opCode oprDescs - { - MemSize = mSize - RegSize = rSize - OperationSize = opSize - SizeCond = sizeCond - } - -let private processOpDescExn oprDescs = function - | Opcode.CMPSD when Array.isEmpty oprDescs |> not -> oprDescs - | Opcode.CMPSB | Opcode.CMPSW | Opcode.CMPSD | Opcode.CMPSQ -> [||] - | _ -> oprDescs - -let parseOp (t: TemporaryInfo) opCode szCond oprDescs = - let insSize = newInsSize t szCond opCode oprDescs - let oprDescs = processOpDescExn oprDescs opCode - Some (struct (newTemporaryIns opCode NoOperand t insSize, oprDescs)) - -let private getVLen = function - | 0b00uy -> 128 - | 0b01uy -> 256 - | 0b10uy -> 512 - | 0b11uy -> raise ParsingFailureException - | _ -> raise ParsingFailureException - -let private getVPrefs b = - match b &&& 0b00000011uy with - | 0b01uy -> Prefix.PrxOPSIZE - | 0b10uy -> Prefix.PrxREPZ - | 0b11uy -> Prefix.PrxREPNZ - | _ -> Prefix.PrxNone - -let private getVVVV b = (b >>> 3) &&& 0b01111uy - -let private getVREXPref (b1: byte) b2 = - let wmask = if b2 >>> 7 = 0uy then 0b1110111uy else 0b1111111uy - let mask = (~~~ (b1 >>> 5)) &&& wmask - |> int |> LanguagePrimitives.EnumOfValue - match REXPrefix.REXWRXB &&& mask with - | REXPrefix.REX -> REXPrefix.NOREX - | v -> v - -let private getTwoVEXInfo (reader: BinReader) pos = - let b = reader.PeekByte pos - let rexPref = if (b >>> 7) = 0uy then REXPrefix.REXR else REXPrefix.NOREX - let vLen = if ((b >>> 2) &&& 0b000001uy) = 0uy then 128 else 256 - { VVVV = getVVVV b; VectorLength = vLen; VEXType = VEXType.VEXTwoByteOp - VPrefixes = getVPrefs b; VREXPrefix = rexPref; EVEXPrx = None } - -let inline private pickVEXType b1 = - match b1 &&& 0b00011uy with - | 0b01uy -> VEXType.VEXTwoByteOp - | 0b10uy -> VEXType.VEXThreeByteOpOne - | 0b11uy -> VEXType.VEXThreeByteOpTwo - | _ -> raise ParsingFailureException - -let private getThreeVEXInfo (reader: BinReader) pos = - let b1 = reader.PeekByte pos - let b2 = reader.PeekByte (pos + 1) - let vLen = if ((b2 >>> 2) &&& 0b000001uy) = 0uy then 128 else 256 - { VVVV = getVVVV b2; VectorLength = vLen; VEXType = pickVEXType b1 - VPrefixes = getVPrefs b2; VREXPrefix = getVREXPref b1 b2; EVEXPrx = None } - -let private getEVEXInfo (reader: BinReader) pos = - let b1 = reader.PeekByte pos - let b2 = reader.PeekByte (pos + 1) - let l'l = reader.PeekByte (pos + 2) >>> 5 &&& 0b011uy - let vLen = getVLen l'l - let z = if (reader.PeekByte (pos + 2) >>> 7 &&& 0b1uy) = 0uy then Zeroing - else Merging - let aaa = reader.PeekByte (pos + 2) &&& 0b111uy - let e = Some { Z = z; AAA = aaa } - { VVVV = getVVVV b2; VectorLength = vLen; - VEXType = pickVEXType b1 ||| VEXType.EVEX - VPrefixes = getVPrefs b2; VREXPrefix = getVREXPref b1 b2; EVEXPrx = e } - -let inline private isVEX (reader: BinReader) wordSize pos = - not (wordSize = WordSize.Bit32 && reader.PeekByte pos < 0xC0uy) - -/// Parse the VEX prefix (VEXInfo). -let parseVEXInfo wordSize (reader: BinReader) pos = - let nextPos = pos + 1 - match reader.PeekByte pos with - | 0xC5uy when isVEX reader wordSize nextPos -> - struct (Some <| getTwoVEXInfo reader nextPos, nextPos + 1) - | 0xC4uy when isVEX reader wordSize nextPos -> - struct (Some <| getThreeVEXInfo reader nextPos, nextPos + 2) - | 0x62uy when isVEX reader wordSize nextPos -> - struct (Some <| getEVEXInfo reader nextPos, nextPos + 3) - | _ -> struct (None, pos) - -/// Select based on the prefix: None, 66, F3, or F2. -let private selectOpInfo prefs (opc: Opcode []) (opr: OperandDesc [][]) = - if hasOprSz prefs then opc.[1], opr.[1] - elif hasREPZ prefs then opc.[2], opr.[2] - elif hasREPNZ prefs then opc.[3], opr.[3] - else opc.[0], opr.[0] - -let inline private filterPrefs (prefs: Prefix) = prefs &&& clearVEXPrefMask - -let inline private selectVEXOpInfo opNorArr opVEXArr dsNorArr dsVEXArr t = - (* Some instructions use 66/F2/F3 prefix as a mandatory prefix. When both - VEX.pp and old-style prefix are used, the VEX.pp is used to select the - opcodes. But if VEX.pp does not exist, then we have to use the old-style - prefix, and we have to filter out the prefixes because they are not going - to be used as a normal prefixes. They will only be used as a mandatory - prefix that decides the opcode. *) - match t.TVEXInfo with - | None -> selectOpInfo t.TPrefixes opNorArr dsNorArr, - { t with TPrefixes = filterPrefs t.TPrefixes } - | Some vInfo -> selectOpInfo vInfo.VPrefixes opVEXArr dsVEXArr, t - -/// Parse VEX instructions. -let private parseVEX t sizeCond opNorArr opVEXArr dsNorArr dsVEXArr = - let (opCode, descs), t = - selectVEXOpInfo opNorArr opVEXArr dsNorArr dsVEXArr t - parseOp t opCode sizeCond descs - -let inline private selectNonVEXOt prefs (oc: Opcode []) (od: OperandDesc [][]) = - if hasOprSz prefs && hasREPNZ prefs then oc.[4], od.[4] - else selectOpInfo prefs oc od - -/// Parse non-VEX instructions. -let private parseNonVEX t sizeCond opNorArr dsNorArr = - let opCode, descs = selectNonVEXOt t.TPrefixes opNorArr dsNorArr - parseOp t opCode sizeCond descs - -/// Parse EVEX instructions. -let private parseEVEX t sizeCond opNorArr opVEXArr opEVEXArr - dsNorArr dsVEXArr dsEVEXArr = - let opVEXArr, dsVEXArr = - match t.TVEXInfo with - | None -> opEmpty, dsEmpty - | Some { VEXType = vt } -> if VEXType.isOriginal vt then opVEXArr, dsVEXArr - else opEVEXArr, dsEVEXArr - parseVEX t sizeCond opNorArr opVEXArr dsNorArr dsVEXArr - -/// Parse BND-related instructions. -let private parseBND t sizeCond opBNDArr dsBNDArr = - let opCode, oprDescs = selectOpInfo t.TPrefixes opBNDArr dsBNDArr - let t = { t with TPrefixes = filterPrefs t.TPrefixes } - parseOp t opCode sizeCond oprDescs - -let private assertVEX128 = function - | { TVEXInfo = Some vInfo } -> - if vInfo.VectorLength = 256 then raise ParsingFailureException else () - | _ -> () - -let getMod (byte: byte) = (int byte >>> 6) &&& 0b11 -let getReg (byte: byte) = (int byte >>> 3) &&& 0b111 -let getRM (byte: byte) = (int byte) &&& 0b111 - -let private getSTReg n = - Register.make n Register.Kind.FPU |> OprReg - -(* Table A-7/15 of Volume 2 - (D8/DC Opcode Map When ModR/M Byte is within 00H to BFH) *) -let private getD8OpWithin00toBF b = - match getReg b with - | 0b000 -> Opcode.FADD - | 0b001 -> Opcode.FMUL - | 0b010 -> Opcode.FCOM - | 0b011 -> Opcode.FCOMP - | 0b100 -> Opcode.FSUB - | 0b101 -> Opcode.FSUBR - | 0b110 -> Opcode.FDIV - | 0b111 -> Opcode.FDIVR - | _ -> raise ParsingFailureException // failwith "Not a D8/DC Opcode" -let inline private getDCOpWithin00toBF b = getD8OpWithin00toBF b - -(* Table A-8 of Volume 2 - (D8 Opcode Map When ModR/M Byte is Outside 00H to BFH) *) -let private getD8OpcodeOutside00toBF = function - | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FADD - | b when b >= 0xC8uy && b <= 0xCFuy -> Opcode.FMUL - | b when b >= 0xD0uy && b <= 0xD7uy -> Opcode.FCOM - | b when b >= 0xD8uy && b <= 0xDFuy -> Opcode.FCOMP - | b when b >= 0xE0uy && b <= 0xE7uy -> Opcode.FSUB - | b when b >= 0xE8uy && b <= 0xEFuy -> Opcode.FSUBR - | b when b >= 0xF0uy && b <= 0xF7uy -> Opcode.FDIV - | b when b >= 0xF8uy && b <= 0xFFuy -> Opcode.FDIVR - | _ -> raise ParsingFailureException // failwith "Not a D8 Opcode" - -(* Table A-9 of Volume 2 - (D9 Opcode Map When ModR/M Byte is Within 00H to BFH) *) -let private getD9OpWithin00toBF b = - match getReg b with - | 0b000 -> Opcode.FLD - | 0b010 -> Opcode.FST - | 0b011 -> Opcode.FSTP - | 0b100 -> Opcode.FLDENV - | 0b101 -> Opcode.FLDCW - | 0b110 -> Opcode.FSTENV - | 0b111 -> Opcode.FNSTCW - | _ -> raise ParsingFailureException // failwith "Not a D9 Opcode" - -(* Table A-10 of Volume 2 - (D9 Opcode Map When ModR/M Byte is Outside 00H to BFH) *) -let private getD9OpcodeOutside00toBF = function - | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FLD - | b when b >= 0xC8uy && b <= 0xCFuy -> Opcode.FXCH - | 0xD0uy -> Opcode.FNOP - | 0xE0uy -> Opcode.FCHS - | 0xE1uy -> Opcode.FABS - | 0xE5uy -> Opcode.FXAM - | 0xE8uy -> Opcode.FLD1 - | 0xE9uy -> Opcode.FLDL2T - | 0xEAuy -> Opcode.FLDL2E - | 0xEBuy -> Opcode.FLDPI - | 0xECuy -> Opcode.FLDLG2 - | 0xEDuy -> Opcode.FLDLN2 - | 0xEEuy -> Opcode.FLDZ - | 0xF0uy -> Opcode.F2XM1 - | 0xF1uy -> Opcode.FYL2X - | 0xF2uy -> Opcode.FPTAN - | 0xF3uy -> Opcode.FPATAN - | 0xF4uy -> Opcode.FXTRACT - | 0xF5uy -> Opcode.FPREM1 - | 0xF6uy -> Opcode.FDECSTP - | 0xF7uy -> Opcode.FINCSTP - | 0xF8uy -> Opcode.FPREM - | 0xF9uy -> Opcode.FYL2XP1 - | 0xFAuy -> Opcode.FSQRT - | 0xFBuy -> Opcode.FSINCOS - | 0xFCuy -> Opcode.FRNDINT - | 0xFDuy -> Opcode.FSCALE - | 0xFEuy -> Opcode.FSIN - | 0xFFuy -> Opcode.FCOS - | _ -> raise ParsingFailureException // failwith "Not a D9 Opcode" - -(* Table A-11/19 of Volume 2 - (DA/DE Opcode Map When ModR/M Byte is Within 00H to BFH) *) -let private getDAOpWithin00toBF b = - match getReg b with - | 0b000 -> Opcode.FIADD - | 0b001 -> Opcode.FIMUL - | 0b010 -> Opcode.FICOM - | 0b011 -> Opcode.FICOMP - | 0b100 -> Opcode.FISUB - | 0b101 -> Opcode.FISUBR - | 0b110 -> Opcode.FIDIV - | 0b111 -> Opcode.FIDIVR - | _ -> raise ParsingFailureException // failwith "Not a DA/DE Opcode" -let private getDEOpWithin00toBF b = getDAOpWithin00toBF b - -(* Table A-12 of Volume 2 - (DA Opcode Map When ModR/M Byte is Outside 00H to BFH) *) -let private getDAOpcodeOutside00toBF = function - | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FCMOVB - | b when b >= 0xC8uy && b <= 0xCFuy -> Opcode.FCMOVE - | b when b >= 0xD0uy && b <= 0xD7uy -> Opcode.FCMOVBE - | b when b >= 0xD8uy && b <= 0xDFuy -> Opcode.FCMOVU - | 0xE9uy -> Opcode.FUCOMPP - | _ -> raise ParsingFailureException // failwith "Not a DA Opcode" - -(* Table A-13 of Volume 2 - (DB Opcode Map When ModR/M Byte is Within 00H to BFH) *) -let private getDBOpWithin00toBF b = - match getReg b with - | 0b000 -> Opcode.FILD - | 0b001 -> Opcode.FISTTP - | 0b010 -> Opcode.FIST - | 0b011 -> Opcode.FISTP - | 0b101 -> Opcode.FLD - | 0b111 -> Opcode.FSTP - | _ -> raise ParsingFailureException // failwith "Not a DB Opcode" - -(* Table A-14 of Volume 2 - (DB Opcode Map When ModR/M Byte is Outside 00H to BFH) *) -let private getDBOpcodeOutside00toBF = function - | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FCMOVNB - | b when b >= 0xC8uy && b <= 0xCFuy -> Opcode.FCMOVNE - | b when b >= 0xD0uy && b <= 0xD7uy -> Opcode.FCMOVNBE - | b when b >= 0xD8uy && b <= 0xDFuy -> Opcode.FCMOVNU - | b when b >= 0xE8uy && b <= 0xEFuy -> Opcode.FUCOMI - | b when b >= 0xF0uy && b <= 0xF7uy -> Opcode.FCOMI - | 0xE2uy -> Opcode.FCLEX - | 0xE3uy -> Opcode.FINIT - | _ -> raise ParsingFailureException // failwith "Not a DB Opcode" - -(* Table A-16 of Volume 2 - (DC Opcode Map When ModR/M Byte is Outside 00H to BFH) *) -let private getDCOpcodeOutside00toBF = function - | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FADD - | b when b >= 0xC8uy && b <= 0xCFuy -> Opcode.FMUL - | b when b >= 0xE0uy && b <= 0xE7uy -> Opcode.FSUBR - | b when b >= 0xE8uy && b <= 0xEFuy -> Opcode.FSUB - | b when b >= 0xF0uy && b <= 0xF7uy -> Opcode.FDIVR - | b when b >= 0xF8uy && b <= 0xFFuy -> Opcode.FDIV - | _ -> raise ParsingFailureException // failwith "Not a DC Opcode" - -(* Table A-17 of Volume 2 - (DD Opcode Map When ModR/M Byte is Within 00H to BFH) *) -let private getDDOpWithin00toBF b = - match getReg b with - | 0b000 -> Opcode.FLD - | 0b001 -> Opcode.FISTTP - | 0b010 -> Opcode.FST - | 0b011 -> Opcode.FSTP - | 0b100 -> Opcode.FRSTOR - | 0b110 -> Opcode.FSAVE - | 0b111 -> Opcode.FNSTSW - | _ -> raise ParsingFailureException // failwith "Not a DD Opcode" - -(* Table A-18 of Volume 2 - (DD Opcode Map When ModR/M Byte is Outside 00H to BFH) *) -let private getDDOpcodeOutside00toBF b = - match b with - | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FFREE - | b when b >= 0xD0uy && b <= 0xD7uy -> Opcode.FST - | b when b >= 0xD8uy && b <= 0xDFuy -> Opcode.FSTP - | b when b >= 0xE0uy && b <= 0xE7uy -> Opcode.FUCOM - | b when b >= 0xE8uy && b <= 0xEFuy -> Opcode.FUCOMP - | _ -> raise ParsingFailureException // failwith "Not a DD Opcode" - -(* Table A-20 of Volume 2 - (DE Opcode Map When ModR/M Byte is Outside 00H to BFH) *) -let private getDEOpcodeOutside00toBF = function - | b when b >= 0xC0uy && b <= 0xC7uy -> Opcode.FADDP - | b when b >= 0xC8uy && b <= 0xCFuy -> Opcode.FMULP - | 0xD9uy -> Opcode.FCOMPP - | b when b >= 0xE0uy && b <= 0xE7uy -> Opcode.FSUBRP - | b when b >= 0xE8uy && b <= 0xEFuy -> Opcode.FSUBP - | b when b >= 0xF0uy && b <= 0xF7uy -> Opcode.FDIVRP - | b when b >= 0xF8uy && b <= 0xFFuy -> Opcode.FDIVP - | _ -> raise ParsingFailureException // failwith "Not a DE Opcode" - -(* Table A-21 of Volume 2 - (DF Opcode Map When ModR/M Byte is Within 00H to BFH) *) -let private getDFOpWithin00toBF b = - match getReg b with - | 0b000 -> Opcode.FILD - | 0b001 -> Opcode.FISTTP - | 0b010 -> Opcode.FIST - | 0b011 -> Opcode.FISTP - | 0b100 -> Opcode.FBLD - | 0b101 -> Opcode.FILD - | 0b110 -> Opcode.FBSTP - | 0b111 -> Opcode.FISTP - | _ -> raise ParsingFailureException // failwith "Not a DF Opcode" - -(* Table A-22 of Volume 2 - (DF Opcode Map When ModR/M Byte is Outside 00H to BFH) *) -let private getDFOpcodeOutside00toBF = function - | 0xE0uy -> Opcode.FNSTSW - | b when b >= 0xE8uy && b <= 0xEFuy -> Opcode.FUCOMIP - | b when b >= 0xF0uy && b <= 0xF7uy -> Opcode.FCOMIP - | _ -> raise ParsingFailureException // failwith "Not a DF Opcode" - -let private getD8OverBF b = - getD8OpcodeOutside00toBF b, TwoOperands (OprReg R.ST0, getRM b |> getSTReg) - -let private getD9OverBF b = - getD9OpcodeOutside00toBF b, - if b < 0xC0uy || b >= 0xD0uy then NoOperand - else OneOperand (getRM b |> getSTReg) - -let private getDAOverBF b = - getDAOpcodeOutside00toBF b, - if b = 0xE9uy then NoOperand - else TwoOperands (OprReg R.ST0, getRM b |> getSTReg) - -let private getDBOverBF b = - getDBOpcodeOutside00toBF b, - if b = 0xE2uy || b = 0xE3uy then NoOperand - else TwoOperands (OprReg R.ST0, getRM b |> getSTReg) - -let private getDCOverBF b = - getDCOpcodeOutside00toBF b, TwoOperands (getRM b |> getSTReg, OprReg R.ST0) - -let private getDDOverBF b = - getDDOpcodeOutside00toBF b, - if b < 0xE0uy || b >= 0xE8uy then getRM b |> getSTReg |> OneOperand - else TwoOperands (getRM b |> getSTReg, OprReg R.ST0) - -let private getDEOverBF b = - getDEOpcodeOutside00toBF b, - if b = 0xD9uy then NoOperand - else TwoOperands (getRM b |> getSTReg, OprReg R.ST0) - -let private getDFOverBF b = - getDFOpcodeOutside00toBF b, - if b = 0xE0uy then OprReg R.AX |> OneOperand - else TwoOperands (OprReg R.ST0, getRM b |> getSTReg) - -let private getD9EscEffOprSizeByModRM = function - | 0b000 | 0b010 | 0b011 -> 32 (* single-real *) - | 0b100 | 0b110 -> 224 (* FIXME: 14/28 bytes (Vol.1 8-11 8.1.10) *) - | 0b101 | 0b111 -> 16 (* 2 bytes *) - | _ -> raise ParsingFailureException - -let private getDBEscEffOprSizeByModRM = function - | 0b101 | 0b111 -> 80 (* extended-real *) - | 0b000 | 0b001 | 0b010 | 0b011 -> 32 (* dword-integer *) - | _ -> raise ParsingFailureException - -let private getDDEscEffOprSizeByModRM = function - | 0b000 | 0b010 | 0b011 -> 64 (* double-real *) - | 0b001 -> 64 (* integer64 *) - | 0b100 | 0b110 -> 864 (* FIXME: 94/108 bytes *) - | 0b111 -> 16 (* 2 bytes *) - | _ -> raise ParsingFailureException - -let private getDFEscEffOprSizeByModRM = function - | 0b000 | 0b001 | 0b010 | 0b011 -> 16 (* word-integer *) - | 0b100 | 0b110 -> 80 (* packed-BCD *) - | 0b101 | 0b111 -> 64 (* qword-integer *) - | _ -> raise ParsingFailureException - -let private getEscEffOprSizeByESCOp = function - | 0xD8uy -> 32 (* single-real *) - | 0xDAuy -> 32 (* dword-integer *) - | 0xDCuy -> 64 (* double-real *) - | 0xDEuy -> 16 (* word-integer *) - | _ -> raise ParsingFailureException - -let private parseESCOp t (reader: BinReader) pos escFlag getOpIn getOpOut = - let b = reader.PeekByte pos // XXX we can optimize this - if b <= 0xBFuy then - let opCode = getOpIn b - let insSize = newInsSize t SzDef32 opCode Mz - let effOprSize = - match escFlag with - | 0xD9uy -> getReg b |> getD9EscEffOprSizeByModRM - | 0xDBuy -> getReg b |> getDBEscEffOprSizeByModRM - | 0xDDuy -> getReg b |> getDDEscEffOprSizeByModRM - | 0xDFuy -> getReg b |> getDFEscEffOprSizeByModRM - | _ -> escFlag |> getEscEffOprSizeByESCOp (* FIXME *) - let memSize = { insSize.MemSize with EffOprSize = effOprSize } - let insSize = { insSize with MemSize = memSize } - Some (struct (newTemporaryIns opCode NoOperand t insSize, Mz)), pos - else - let opCode, oprs = getOpOut b - let insSize = newInsSize t SzDef32 opCode Mz - Some (struct (newTemporaryIns opCode oprs t insSize, [||])), pos + 1 - -// Group Opcodes -let grp1Op = [| Opcode.ADD; Opcode.OR; Opcode.ADC; Opcode.SBB; - Opcode.AND; Opcode.SUB; Opcode.XOR; Opcode.CMP |] -let grp1aOp = [| Opcode.POP |] -let grp2Op = [| Opcode.ROL; Opcode.ROR; Opcode.RCL; Opcode.RCR; - Opcode.SHL; Opcode.SHR; Opcode.InvalOP; Opcode.SAR |] -let grp4Op = [| Opcode.INC; Opcode.DEC |] -let grp5Op = [| Opcode.INC; Opcode.DEC; Opcode.CALLNear; Opcode.CALLFar; - Opcode.JMPNear; Opcode.JMPFar; Opcode.PUSH |] -let grp5Desc = [| Ev; Ev; Ev; Ep; Ev; Mp; Ev |] -let grp5SCnd = [| SzDef32; SzDef32; Sz64; SzDef32; Sz64; SzDef32; SzDef64 |] -let grp7Op = [| Opcode.SGDT; Opcode.SIDT; Opcode.LGDT; Opcode.LIDT; - Opcode.SMSW; Opcode.RSTORSSP; Opcode.LMSW; Opcode.INVLPG |] -let grp7Desc = [| Ms; Ms; Ms; Ms; Mw; Mq; Ew; Ew |] -let grp8Op = [| Opcode.InvalOP; Opcode.InvalOP; Opcode.InvalOP; - Opcode.InvalOP; Opcode.BT; Opcode.BTS; Opcode.BTR; - Opcode.BTC |] -let grp16Op = [| Opcode.PREFETCHNTA; Opcode.PREFETCHT0; - Opcode.PREFETCHT1; Opcode.PREFETCHT2 |] - -let getOpAndOprKindByOpGrp3 kindFlag regBits oprDesc = - match regBits, oprDesc with - | 0b000, [| k |] -> Opcode.TEST, [| k; kindFlag |], SzDef32 - | 0b010, _ -> Opcode.NOT, oprDesc, SzDef32 - | 0b011, _ -> Opcode.NEG, oprDesc, SzDef32 - | 0b100, _ -> Opcode.MUL, oprDesc, SzDef32 - | 0b101, _ -> Opcode.IMUL, oprDesc, SzDef32 - | 0b110, _ -> Opcode.DIV, oprDesc, SzDef32 - | 0b111, _ -> Opcode.IDIV, oprDesc, SzDef32 - | _ -> raise ParsingFailureException - -let private modIsMemory b = (getMod b) <> 0b11 - -let getOpAndOprKindByOpGrp6 b regBits = - match modIsMemory b, regBits with - | true, 0b000 -> Opcode.SLDT, Mv, SzDef32 - | false, 0b000 -> Opcode.SLDT, Rv, SzDef32 - | true, 0b001 -> Opcode.STR, Mv, SzDef32 - | false, 0b001 -> Opcode.STR, Rv, SzDef32 - | _, 0b010 -> Opcode.LLDT, Ew, SzDef32 - | _, 0b011 -> Opcode.LTR, Ew, SzDef32 - | _, 0b100 -> Opcode.VERR, Ew, SzDef32 - | _, 0b101 -> Opcode.VERW, Ew, SzDef32 - | _ -> raise ParsingFailureException - -let parseOpAndOprKindByOpGrp7 t pos b regBits = - let notMemory = function - | 0b000, 0b001 -> (Opcode.VMCALL, [||], SzDef32), pos + 1 - | 0b000, 0b010 -> (Opcode.VMLAUNCH, [||], SzDef32), pos + 1 - | 0b000, 0b011 -> (Opcode.VMRESUME, [||], SzDef32), pos + 1 - | 0b000, 0b100 -> (Opcode.VMXOFF, [||], SzDef32), pos + 1 - | 0b001, 0b000 -> (Opcode.MONITOR, [||], SzDef32), pos + 1 - | 0b001, 0b001 -> (Opcode.MWAIT, [||], SzDef32), pos + 1 - | 0b001, 0b010 -> (Opcode.CLAC, [||], SzDef32), pos + 1 - | 0b001, 0b011 -> (Opcode.STAC, [||], SzDef32), pos + 1 - | 0b010, 0b000 -> (Opcode.XGETBV, [||], SzDef32), pos + 1 - | 0b010, 0b001 -> (Opcode.XSETBV, [||], SzDef32), pos + 1 - | 0b010, 0b100 -> (Opcode.VMFUNC, [||], SzDef32), pos + 1 - | 0b010, 0b101 -> (Opcode.XEND, [||], SzDef32), pos + 1 - | 0b010, 0b110 -> (Opcode.XTEST, [||], SzDef32), pos + 1 - | 0b100, _ -> (Opcode.SMSW, Rv, SzDef32), pos - | 0b101, 0b000 -> (Opcode.SETSSBSY, [||], SzDef32), pos + 1 - | 0b101, 0b010 -> (Opcode.SAVEPREVSSP, [||], SzDef32), pos + 1 - | 0b101, 0b110 -> (Opcode.RDPKRU, [||], SzDef32), pos + 1 - | 0b101, 0b111 -> (Opcode.WRPKRU, [||], SzDef32), pos + 1 - | 0b110, _ -> (Opcode.LMSW, Ew, SzDef32), pos - | 0b111, 0b000 -> ensure32 t; (Opcode.SWAPGS, [||], SzOnly64), pos + 1 - | 0b111, 0b001 -> (Opcode.RDTSCP, [||], SzDef32), pos + 1 - | _ -> raise ParsingFailureException - if modIsMemory b then (grp7Op.[regBits], grp7Desc.[regBits], SzDef32), pos - else notMemory (regBits, getRM b) - -let getOpAndPorKindByOpGrp9 t b regBits = - let hasOprSzPref = hasOprSz t.TPrefixes - let hasREPZPref = hasREPZ t.TPrefixes - let hasREXWPref = hasREXW t.TREXPrefix - match modIsMemory b, regBits, hasOprSzPref, hasREPZPref, hasREXWPref with - | true, 0b001, false, false, false -> Opcode.CMPXCHG8B, Mq, SzDef32 - | true, 0b001, false, false, true -> Opcode.CMPXCHG16B, Mdq, SzDef32 - | true, 0b011, false, false, false -> Opcode.XRSTORS, Mq, SzDef32 - | true, 0b011, false, false, true -> Opcode.XRSTORS64, Mq, SzDef32 - | true, 0b100, false, false, false -> Opcode.XSAVEC, Mq, SzDef32 - | true, 0b100, false, false, true -> Opcode.XSAVEC64, Mq, SzDef32 - | true, 0b101, false, false, false -> Opcode.XSAVES, Mq, SzDef32 - | true, 0b101, false, false, true -> Opcode.XSAVES64, Mq, SzDef32 - | true, 0b110, false, false, _ -> Opcode.VMPTRLD, Mq, SzDef32 - | true, 0b111, false, false, _ -> Opcode.VMPTRST, Mq, SzDef32 - | true, 0b110, true, false, _ -> Opcode.VMCLEAR, Mq, SzDef32 - | true, 0b110, false, true, _ -> Opcode.VMXON, Mq, SzDef32 - | true, 0b111, false, true, _ -> Opcode.VMPTRST, Mq, SzDef32 - | false, 0b110, false, false, _ -> Opcode.RDRAND, Rv, SzDef32 - | false, 0b111, false, false, _ -> Opcode.RDSEED, Rv, SzDef32 - | _ -> raise ParsingFailureException - -let getOpAndOprKindByOpGrp11 opFlag kFlag b reg descs (reader: BinReader) pos = - match reg with - | 0b000 -> (Opcode.MOV, descs, SzDef32), pos - | 0b111 when modIsMemory b -> raise ParsingFailureException - | 0b111 -> if reader.PeekByte pos <> 0xF8uy then raise ParsingFailureException - else (opFlag, kFlag, SzDef32), pos + 1 - | _ -> raise ParsingFailureException - -let inline private selectPrefix t = - match t.TVEXInfo with - | None -> t.TPrefixes - | Some v -> v.VPrefixes - -let getOpAndOprKindByOpGrp12 t b regBits = - match modIsMemory b, regBits, hasOprSz (selectPrefix t) with - | false, 0b010, false -> Opcode.PSRLW, NqIb, SzDef32 - | false, 0b010, true -> - if t.TVEXInfo = None then Opcode.PSRLW, UdqIb, SzDef32 - else Opcode.VPSRLW, HxUxIb, SzDef32 - | false, 0b100, false -> Opcode.PSRAW, NqIb, SzDef32 - | false, 0b100, true -> - if t.TVEXInfo = None then Opcode.PSRAW, UdqIb, SzDef32 - else Opcode.VPSRAW, HxUxIb, SzDef32 - | false, 0b110, false -> Opcode.PSLLW, NqIb, SzDef32 - | false, 0b110, true -> - if t.TVEXInfo = None then Opcode.PSLLW, UdqIb, SzDef32 - else Opcode.VPSLLW, HxUxIb, SzDef32 - | _ -> raise ParsingFailureException - -let getOpAndOprKindByOpGrp13 t b regBits = - match modIsMemory b, regBits, hasOprSz (selectPrefix t) with - | false, 0b010, false -> Opcode.PSRLD, NqIb, SzDef32 - | false, 0b010, true -> - if t.TVEXInfo = None then Opcode.PSRLD, UdqIb, SzDef32 - else Opcode.VPSRLD, HxUxIb, SzDef32 - | false, 0b100, false -> Opcode.PSRAD, NqIb, SzDef32 - | false, 0b100, true -> - if t.TVEXInfo = None then Opcode.PSRAD, UdqIb, SzDef32 - else Opcode.VPSRAD, HxUxIb, SzDef32 - | false, 0b110, false -> Opcode.PSLLD, NqIb, SzDef32 - | false, 0b110, true -> - if t.TVEXInfo = None then Opcode.PSLLD, UdqIb, SzDef32 - else Opcode.VPSLLD, HxUxIb, SzDef32 - | _ -> raise ParsingFailureException - -let getOpAndOprKindByOpGrp14 t b regBits = - match modIsMemory b, regBits, hasOprSz (selectPrefix t) with - | false, 0b010, false -> Opcode.PSRLQ, NqIb, SzDef32 - | false, 0b010, true -> - if t.TVEXInfo = None then Opcode.PSRLQ, UdqIb, SzDef32 - else Opcode.VPSRLQ, HxUxIb, SzDef32 - | false, 0b011, true -> - if t.TVEXInfo = None then Opcode.PSRLDQ, UdqIb, SzDef32 - else Opcode.VPSRLDQ, HxUxIb, SzDef32 - | false, 0b110, false -> Opcode.PSLLQ, NqIb, SzDef32 - | false, 0b110, true -> - if t.TVEXInfo = None then Opcode.PSLLQ, UdqIb, SzDef32 - else Opcode.VPSLLQ, HxUxIb, SzDef32 - | false, 0b111, true -> - if t.TVEXInfo = None then Opcode.PSLLDQ, UdqIb, SzDef32 - else Opcode.VPSLLDQ, HxUxIb, SzDef32 - | _ -> raise ParsingFailureException - -let parseOpAndOprKindByOpGrp15 t pos b regBits = - match modIsMemory b, regBits, hasREPZ t.TPrefixes with - | true, 0b110, true -> (Opcode.CLRSSBSY, Mq, SzDef32), pos - | true, 0b000, false -> - let op = if hasREXW t.TREXPrefix then Opcode.FXSAVE64 else Opcode.FXSAVE - (op, Ev, SzDef32), pos - | true, 0b001, false -> - let op = if hasREXW t.TREXPrefix then Opcode.FXRSTOR64 else Opcode.FXRSTOR - (op, Ev, SzDef32), pos - | true, 0b010, false -> (Opcode.LDMXCSR, Ev, SzDef32), pos - | true, 0b011, false -> (Opcode.STMXCSR, Ev, SzDef32), pos - | true, 0b100, false -> (Opcode.XSAVE, Ev, SzDef32), pos - | true, 0b101, false -> (Opcode.XRSTOR, Ev, SzDef32), pos - | true, 0b110, false -> (Opcode.XSAVEOPT, Ev, SzDef32), pos - | true, 0b111, false -> (Opcode.CLFLUSH, Eb, SzDef32), pos - | false, 0b101, false -> (Opcode.LFENCE, [||], SzDef32), pos + 1 - | false, 0b110, false -> (Opcode.MFENCE, [||], SzDef32), pos + 1 - | false, 0b111, false -> (Opcode.SFENCE, [||], SzDef32), pos + 1 - | false, 0b000, true -> (Opcode.RDFSBASE, Ry, SzDef32), pos - | false, 0b001, true -> (Opcode.RDGSBASE, Ry, SzDef32), pos - | false, 0b010, true -> (Opcode.WRFSBASE, Ry, SzDef32), pos - | false, 0b011, true -> (Opcode.WRGSBASE, Ry, SzDef32), pos - | false, 0b101, true -> - let op = if hasREXW t.TREXPrefix then Opcode.INCSSPQ else Opcode.INCSSPD - (op, Ry, SzDef32), pos - | _ -> raise ParsingFailureException - -let parseOpAndOprKindByGrp t reader pos b oprDescs oprGrp = - let r = getReg b - match oprGrp with - | OpGroup.G1 -> (grp1Op.[r], oprDescs, SzDef32), pos - | OpGroup.G1Inv64 -> ensure32 t; (grp1Op.[r], oprDescs, SzInv64), pos - | OpGroup.G1A -> (grp1aOp.[r], oprDescs, SzDef64), pos - | OpGroup.G2 when r = 0b110 -> raise ParsingFailureException - | OpGroup.G2 -> (grp2Op.[r], oprDescs, SzDef32), pos - | OpGroup.G3A -> getOpAndOprKindByOpGrp3 _SIb r oprDescs, pos - | OpGroup.G3B -> getOpAndOprKindByOpGrp3 _SIz r oprDescs, pos - | OpGroup.G4 -> (grp4Op.[r], Eb, SzDef32), pos - | OpGroup.G5 -> (grp5Op.[r], grp5Desc.[r], grp5SCnd.[r]), pos - | OpGroup.G6 -> getOpAndOprKindByOpGrp6 b r, pos - | OpGroup.G7 -> parseOpAndOprKindByOpGrp7 t pos b r - | OpGroup.G8 -> (grp8Op.[r], oprDescs, SzDef32), pos - | OpGroup.G9 -> getOpAndPorKindByOpGrp9 t b r, pos - | OpGroup.G11A -> - getOpAndOprKindByOpGrp11 Opcode.XABORT Ib b r oprDescs reader pos - | OpGroup.G11B -> - getOpAndOprKindByOpGrp11 Opcode.XBEGIN Jz b r oprDescs reader pos - | OpGroup.G12 -> getOpAndOprKindByOpGrp12 t b r, pos - | OpGroup.G13 -> getOpAndOprKindByOpGrp13 t b r, pos - | OpGroup.G14 -> getOpAndOprKindByOpGrp14 t b r, pos - | OpGroup.G15 -> parseOpAndOprKindByOpGrp15 t pos b r - | OpGroup.G16 -> (grp16Op.[r], oprDescs, SzDef32), pos - | OpGroup.G10 | OpGroup.G17 | _ -> - raise ParsingFailureException (* Not implemented yet *) - -let parseOpGrpInfo t (reader: BinReader) pos grp oprDescs = - parseOpAndOprKindByGrp t reader pos (reader.PeekByte pos) oprDescs grp - -let parseGrpOpcode t reader pos grp oprDescs = - let (op, oprDescs, szCond), pos = parseOpGrpInfo t reader pos grp oprDescs - let t = - if Helper.isBranch op then pBNDPref t - elif Helper.isCETInstr op then - { t with TPrefixes = Helper.clearGrp1PrefMask &&& t.TPrefixes } - else t - parseOp t op szCond oprDescs, pos - -let private rexb = - RGrpAttr.ARegInOpREX - ||| RGrpAttr.ABaseRM - ||| RGrpAttr.AMod11 - ||| RGrpAttr.ASIBBase - -let private rexxb = - RGrpAttr.ARegInOpREX - ||| RGrpAttr.ABaseRM - ||| RGrpAttr.AMod11 - ||| RGrpAttr.ASIBIdx - ||| RGrpAttr.ASIBBase - -let private rexrb = - RGrpAttr.ARegInOpREX - ||| RGrpAttr.ABaseRM - ||| RGrpAttr.AMod11 - ||| RGrpAttr.ARegBits - ||| RGrpAttr.ASIBBase - -let private rexrx = RGrpAttr.ARegBits ||| RGrpAttr.ASIBIdx - -let private rexrxb = - RGrpAttr.ARegInOpREX - ||| RGrpAttr.ABaseRM - ||| RGrpAttr.AMod11 - ||| RGrpAttr.ARegBits - ||| RGrpAttr.ASIBIdx - ||| RGrpAttr.ASIBBase - -let inline private selectRGrp attr g1 g2 rex = - match rex with - | REXPrefix.REX -> g2 - | REXPrefix.REXB | REXPrefix.REXWB -> - if (rexb &&& attr) <> RGrpAttr.ANone then g1 else g2 - | REXPrefix.REXX | REXPrefix.REXWX -> - if RGrpAttr.ASIBIdx = attr then g1 else g2 - | REXPrefix.REXXB | REXPrefix.REXWXB -> - if (rexxb &&& attr) <> RGrpAttr.ANone then g1 else g2 - | REXPrefix.REXR | REXPrefix.REXWR -> - if RGrpAttr.ARegBits = attr then g1 else g2 - | REXPrefix.REXRB | REXPrefix.REXWRB -> - if (rexrb &&& attr) <> RGrpAttr.ANone then g1 else g2 - | REXPrefix.REXRX | REXPrefix.REXWRX -> - if (rexrx &&& attr) <> RGrpAttr.ANone then g1 else g2 - | REXPrefix.REXRXB | REXPrefix.REXWRXB -> - if (rexrxb &&& attr) <> RGrpAttr.ANone then g1 else g2 - | REXPrefix.REXW -> g2 - | _ -> raise ParsingFailureException - -let inline private pickReg sz (grp: Register []) = - match sz with - | 512 -> grp.[6] - | 256 -> grp.[5] - | 128 -> grp.[4] - | 64 -> grp.[3] - | 32 -> grp.[2] - | 16 -> grp.[1] - | 8 -> grp.[0] - | _ -> raise ParsingFailureException - -let private tblGrpNOREX = - [| GrpEAX; GrpECX; GrpEDX; GrpEBX; GrpAH; GrpCH; GrpDH; GrpBH |] - -let private tblGrp1 = - [| GrpR8; GrpR9; GrpR10; GrpR11; GrpR12; GrpR13; GrpR14; GrpR15 |] - -let private tblGrp2 = - [| GrpEAX; GrpECX; GrpEDX; GrpEBX; GrpESP; GrpEBP; GrpESI; GrpEDI |] - -/// Find an appropriate register symbol from the given RegType, RGrpAttribute, -/// REXPrefix, and RegGrp (int). -let findReg sz oprAttr rex (grp: int) = - if rex = REXPrefix.NOREX then pickReg sz tblGrpNOREX.[grp] - else pickReg sz (selectRGrp oprAttr tblGrp1.[grp] tblGrp2.[grp] rex) - -let private selectOpInfoByMem (reader: BinReader) pos opNorM opNorR opVEXM - opVEXR dsNorM dsNorR dsVEXM dsVEXR = - if reader.PeekByte pos |> modIsMemory then opNorM, opVEXM, dsNorM, dsVEXM - else opNorR, opVEXR, dsNorR, dsVEXR - -let inline private selectOpInfoByRex t opNorB64 opNorB32 opVEXB64 opVEXB32 - dsNorB64 dsNorB32 dsVEXB64 dsVEXB32 = - if hasREXW (selectREX t.TVEXInfo t.TREXPrefix) then - opNorB64, opVEXB64, dsNorB64, dsVEXB64 - else opNorB32, opVEXB32, dsNorB32, dsVEXB32 - -let inline private selectOpInfoByRexEVEX t opB64 opB32 dsB64 dsB32 = - if hasREXW (selectREX t.TVEXInfo t.TREXPrefix) then opB64, dsB64 - else opB32, dsB32 - -let private getOpCode0F0D (reader: BinReader) pos = - let b = reader.PeekByte pos - match modIsMemory b, getReg b with - | true, 0b001 -> Opcode.PREFETCHW - | true, 0b010 -> Opcode.PREFETCHWT1 - | _ -> raise ParsingFailureException - -let private ignOpSz t = - { t with - TPrefixes = t.TPrefixes &&& LanguagePrimitives.EnumOfValue 0xFDFF } - -let inline private parseEVEXByRex t pos opNor opVEX opE64 opE32 - dsNor dsVEX dsE64 dsE32 = - let opEVEX, dsEVEX = selectOpInfoByRexEVEX t opE64 opE32 dsE64 dsE32 - parseEVEX t SzDef32 opNor opVEX opEVEX dsNor dsVEX dsEVEX, pos - -let inline private pVEXByMem t reader pos opNorMem opNorReg opVEXMem - opVEXReg dsNorMem dsNorReg dsVEXMem dsVEXReg = - let opNor, opVEX, dsNor, dsVEX = - selectOpInfoByMem reader pos opNorMem opNorReg opVEXMem opVEXReg - dsNorMem dsNorReg dsVEXMem dsVEXReg - parseVEX t SzDef32 opNor opVEX dsNor dsVEX, pos - -let inline private parseVEXByRex t pos opNorB64 opNorB32 opVEXB64 opVEXB32 - dsNorB64 dsNorB32 dsVEXB64 dsVEXB32 = - let opNor, opVEX, dsNor, dsVEX = - selectOpInfoByRex t opNorB64 opNorB32 opVEXB64 opVEXB32 - dsNorB64 dsNorB32 dsVEXB64 dsVEXB32 - parseVEX t SzDef32 opNor opVEX dsNor dsVEX, pos - -/// When the first two bytes are 0F38. -/// Table A-4 of Volume 2 (Three-byte Opcode Map : First Two Bytes are 0F 38H) -let private parseThreeByteOp1 t (reader: BinReader) pos = - match reader.PeekByte pos with - | 0x00uy -> parseVEX t SzDef32 opNor0F3800 opVex0F3800 - dsNor0F3800 dsVex0F3800, pos + 1 - | 0x01uy -> parseVEX t SzDef32 opNor0F3801 opVex0F3801 - dsNor0F3801 dsVex0F3801, pos + 1 - | 0x02uy -> parseVEX t SzDef32 opNor0F3802 opVex0F3802 - dsNor0F3802 dsVex0F3802, pos + 1 - | 0x03uy -> parseVEX t SzDef32 opNor0F3803 opVex0F3803 - dsNor0F3803 dsVex0F3803, pos + 1 - | 0x05uy -> parseVEX t SzDef32 opNor0F3805 opVex0F3805 - dsNor0F3805 dsVex0F3805, pos + 1 - | 0x06uy -> parseVEX t SzDef32 opNor0F3806 opVex0F3806 - dsNor0F3806 dsVex0F3806, pos + 1 - | 0x07uy -> parseVEX t SzDef32 opNor0F3807 opVex0F3807 - dsNor0F3807 dsVex0F3807, pos + 1 - | 0x08uy -> parseVEX t SzDef32 opNor0F3808 opVex0F3808 - dsNor0F3808 dsVex0F3808, pos + 1 - | 0x09uy -> parseVEX t SzDef32 opNor0F3809 opVex0F3809 - dsNor0F3809 dsVex0F3809, pos + 1 - | 0x0auy -> parseVEX t SzDef32 opNor0F380A opVex0F380A - dsNor0F380A dsVex0F380A, pos + 1 - | 0x0buy -> parseVEX t SzDef32 opNor0F380B opVex0F380B - dsNor0F380B dsVex0F380B, pos + 1 - | 0x17uy -> parseVEX t SzDef32 opNor0F3817 opVex0F3817 - dsNor0F3817 dsVex0F3817, pos + 1 - | 0x18uy -> parseEVEXByRex t (pos + 1) opNor0F3818 opVex0F3818 opEmpty - opEVex0F3818 dsNor0F3818 - dsVex0F3818 dsEmpty dsEVex0F3818 - | 0x1cuy -> parseVEX t SzDef32 opNor0F381C opVex0F381C - dsNor0F381C dsVex0F381C, pos + 1 - | 0x1duy -> parseVEX t SzDef32 opNor0F381D opVex0F381D - dsNor0F381D dsVex0F381D, pos + 1 - | 0x1euy -> parseVEX t SzDef32 opNor0F381E opVex0F381E - dsNor0F381E dsVex0F381E, pos + 1 - | 0x20uy -> parseVEX t SzDef32 opNor0F3820 opVex0F3820 - dsNor0F3820 dsVex0F3820, pos + 1 - | 0x21uy -> parseVEX t SzDef32 opNor0F3821 opVex0F3821 - dsNor0F3821 dsVex0F3821, pos + 1 - | 0x22uy -> parseVEX t SzDef32 opNor0F3822 opVex0F3822 - dsNor0F3822 dsVex0F3822, pos + 1 - | 0x23uy -> parseVEX t SzDef32 opNor0F3823 opVex0F3823 - dsNor0F3823 dsVex0F3823, pos + 1 - | 0x24uy -> parseVEX t SzDef32 opNor0F3824 opVex0F3824 - dsNor0F3824 dsVex0F3824, pos + 1 - | 0x25uy -> parseVEX t SzDef32 opNor0F3825 opVex0F3825 - dsNor0F3825 dsVex0F3825, pos + 1 - | 0x28uy -> parseVEX t SzDef32 opNor0F3828 opVex0F3828 - dsNor0F3828 dsVex0F3828, pos + 1 - | 0x29uy -> parseVEX t SzDef32 opNor0F3829 opVex0F3829 - dsNor0F3829 dsVex0F3829, pos + 1 - | 0x2buy -> parseVEX t SzDef32 opNor0F382B opVex0F382B - dsNor0F382B dsVex0F382B, pos + 1 - | 0x30uy -> parseVEX t SzDef32 opNor0F3830 opVex0F3830 - dsNor0F3830 dsVex0F3830, pos + 1 - | 0x31uy -> parseVEX t SzDef32 opNor0F3831 opVex0F3831 - dsNor0F3831 dsVex0F3831, pos + 1 - | 0x32uy -> parseVEX t SzDef32 opNor0F3832 opVex0F3832 - dsNor0F3832 dsVex0F3832, pos + 1 - | 0x33uy -> parseVEX t SzDef32 opNor0F3833 opVex0F3833 - dsNor0F3833 dsVex0F3833, pos + 1 - | 0x34uy -> parseVEX t SzDef32 opNor0F3834 opVex0F3834 - dsNor0F3834 dsVex0F3834, pos + 1 - | 0x35uy -> parseVEX t SzDef32 opNor0F3835 opVex0F3835 - dsNor0F3835 dsVex0F3835, pos + 1 - | 0x37uy -> parseVEX t SzDef32 opNor0F3837 opVex0F3837 - dsNor0F3837 dsVex0F3837, pos + 1 - | 0x38uy -> parseVEX t SzDef32 opNor0F3838 opVex0F3838 - dsNor0F3838 dsVex0F3838, pos + 1 - | 0x39uy -> parseVEX t SzDef32 opNor0F3839 opVex0F3839 - dsNor0F3839 dsVex0F3839, pos + 1 - | 0x3auy -> parseVEX t SzDef32 opNor0F383A opVex0F383A - dsNor0F383A dsVex0F383A, pos + 1 - | 0x3buy -> parseVEX t SzDef32 opNor0F383B opVex0F383B - dsNor0F383B dsVex0F383B, pos + 1 - | 0x3cuy -> parseVEX t SzDef32 opNor0F383C opVex0F383C - dsNor0F383C dsVex0F383C, pos + 1 - | 0x3duy -> parseVEX t SzDef32 opNor0F383D opVex0F383D - dsNor0F383D dsVex0F383D, pos + 1 - | 0x3euy -> parseVEX t SzDef32 opNor0F383E opVex0F383E - dsNor0F383E dsVex0F383E, pos + 1 - | 0x3fuy -> parseVEX t SzDef32 opNor0F383F opVex0F383F - dsNor0F383F dsVex0F383F, pos + 1 - | 0x40uy -> parseVEX t SzDef32 opNor0F3840 opVex0F3840 - dsNor0F3840 dsVex0F3840, pos + 1 - | 0x41uy -> parseVEX t SzDef32 opNor0F3841 opVex0F3841 - dsNor0F3841 dsVex0F3841, pos + 1 - | 0x5Auy -> parseVEX t SzDef32 opNor0F385A opVex0F385A - dsNor0F385A dsVex0F385A, pos + 1 - | 0x78uy -> parseVEX t SzDef32 opNor0F3878 opVex0F3878 - dsNor0F3878 dsVex0F3878, pos + 1 - | 0x99uy -> parseVEXByRex t (pos + 1) opNor0F3899W1 opNor0F3899W0 - opVex0F3899W1 opVex0F3899W0 - dsNor0F3899W1 dsNor0F3899W0 - dsVex0F3899W1 dsVex0F3899W0 - | 0xA9uy -> parseVEXByRex t (pos + 1) opNor0F38A9W1 opNor0F38A9W0 - opVex0F38A9W1 opVex0F38A9W0 - dsNor0F38A9W1 dsNor0F38A9W0 - dsVex0F38A9W1 dsVex0F38A9W0 - | 0xB9uy -> parseVEXByRex t (pos + 1) opNor0F38B9W1 opNor0F38B9W0 - opVex0F38B9W1 opVex0F38B9W0 - dsNor0F38B9W1 dsNor0F38B9W0 - dsVex0F38B9W1 dsVex0F38B9W0 - | 0xF0uy -> parseNonVEX t SzDef32 opNor0F38F0 dsNor0F38F0, pos + 1 - | 0xF1uy -> parseNonVEX t SzDef32 opNor0F38F1 dsNor0F38F1, pos + 1 - | 0xF5uy -> parseVEXByRex t (pos + 1) opNor0F38F5W1 opNor0F38F5W0 - opVex0F38F5W1 opVex0F38F5W0 - dsNor0F38F5W1 dsNor0F38F5W0 - dsVex0F38F5W1 dsVex0F38F5W0 - | 0xF6uy -> parseVEXByRex t (pos + 1) opNor0F38F6W1 opNor0F38F6W0 - opVex0F38F6W1 opVex0F38F6W0 - dsNor0F38F6W1 dsNor0F38F6W0 - dsVex0F38F6W1 dsVex0F38F6W0 - | 0xF7uy -> parseVEX t SzDef32 opNor0F38F7 opVex0F38F7 - dsNor0F38F7 dsVex0F38F7, pos + 1 - | _ -> raise ParsingFailureException - -/// When the first two bytes are 0F3A. -/// Table A-5 of Volume 2 (Three-byte Opcode Map : First Two Bytes are 0F 3AH) -let private parseThreeByteOp2 t (reader: BinReader) pos = - match reader.PeekByte pos with - | 0x0Fuy -> parseVEX t SzDef32 opNor0F3A0F opVex0F3A0F - dsNor0F3A0F dsVex0F3A0F, pos + 1 - | 0x15uy -> parseVEX t SzDef32 opNor0F3A15 opVex0F3A15 - dsNor0F3A15 dsVex0F3A15, pos + 1 - | 0x20uy -> parseVEX t SzDef32 opNor0F3A20 opVex0F3A20 - dsNor0F3A20 dsVex0F3A20, pos + 1 - | 0x38uy -> parseVEX t SzDef32 opNor0F3A38 opVex0F3A38 - dsNor0F3A38 dsVex0F3A38, pos + 1 - | 0x60uy -> parseVEX t SzDef32 opNor0F3A60 opVex0F3A60 - dsNor0F3A60 dsVex0F3A60, pos + 1 - | 0x61uy -> parseVEX t SzDef32 opNor0F3A61 opVex0F3A61 - dsNor0F3A61 dsVex0F3A61, pos + 1 - | 0x62uy -> parseVEX t SzDef32 opNor0F3A62 opVex0F3A62 - dsNor0F3A62 dsVex0F3A62, pos + 1 - | 0x63uy -> parseVEX t SzDef32 opNor0F3A63 opVex0F3A63 - dsNor0F3A63 dsVex0F3A63, pos + 1 - | 0x0Buy -> parseVEX t SzDef32 opNor0F3A0B opVex0F3A0B - dsNor0F3A0B dsVex0F3A0B, pos + 1 - | 0xF0uy -> parseVEX t SzDef32 opNor0F3AF0 opVex0F3AF0 - dsNor0F3AF0 dsVex0F3AF0, pos + 1 - | _ -> raise ParsingFailureException - -let private parseCETInstr t (reader: BinReader) pos = - let opcode, oprs, pos = - match reader.PeekByte pos with - | 0xFAuy -> Opcode.ENDBR64, [||], pos + 1 - | 0xFBuy -> Opcode.ENDBR32, [||], pos + 1 - | b when getReg b = 0b001 && getMod b = 0b11 -> - let op = if hasREXW t.TREXPrefix then Opcode.RDSSPQ else Opcode.RDSSPD - op, Ry, pos - | _ -> raise InvalidOpcodeException - let t = { t with TPrefixes = Helper.clearGrp1PrefMask &&& t.TPrefixes } - parseOp t opcode SzDef32 oprs, pos - -let private pTwoByteOp t reader pos byte = - match byte with - | 0x02uy -> parseOp t Opcode.LAR SzDef32 GvEw, pos - | 0x03uy -> parseOp t Opcode.LSL SzDef32 GvEw, pos - | 0x05uy -> ensure64 t; parseOp t Opcode.SYSCALL SzOnly64 [||], pos - | 0x06uy -> parseOp t Opcode.CLTS SzDef32 [||], pos - | 0x07uy -> ensure64 t; parseOp t Opcode.SYSRET SzOnly64 [||], pos - | 0x08uy -> parseOp t Opcode.INVD SzDef32 [||], pos - | 0x09uy -> parseOp t Opcode.WBINVD SzDef32 [||], pos - | 0x0Buy -> parseOp t Opcode.UD2 SzDef32 [||], pos - | 0x0Duy -> parseOp t (getOpCode0F0D reader pos) SzDef32 Ev, pos - | 0x10uy -> pVEXByMem t reader pos opNor0F10 opNor0F10 - opVex0F10Mem opVex0F10Reg - dsNor0F10 dsNor0F10 - dsVex0F10Mem dsVex0F10Reg - | 0x11uy -> pVEXByMem t reader pos opNor0F11 opNor0F11 - opVex0F11Mem opVex0F11Reg - dsNor0F11 dsNor0F11 - dsVex0F11Mem dsVex0F11Reg - | 0x12uy -> pVEXByMem t reader pos opNor0F12Mem opNor0F12Reg - opVex0F12Mem opVex0F12Reg - dsNor0F12Mem dsNor0F12Reg - dsVex0F12Mem dsVex0F12Reg - | 0x13uy -> parseVEX t SzDef32 opNor0F13 opVex0F13 dsNor0F13 dsVex0F13, pos - | 0x14uy -> parseVEX t SzDef32 opNor0F14 opVex0F14 dsNor0F14 dsVex0F14, pos - | 0x15uy -> parseVEX t SzDef32 opNor0F15 opVex0F15 dsNor0F15 dsVex0F15, pos - | 0x16uy -> pVEXByMem t reader pos opNor0F16Mem opNor0F16Reg - opVex0F16Mem opVex0F16Reg - dsNor0F16Mem dsNor0F16Reg - dsVex0F16Mem dsVex0F16Reg - | 0x17uy -> parseVEX t SzDef32 opNor0F17 opVex0F17 dsNor0F17 dsVex0F17, pos - | 0x1Auy -> parseBND t SzDef32 opNor0F1A dsNor0F1A, pos - | 0x1Buy -> parseBND t SzDef32 opNor0F1B dsNor0F1B, pos - | 0x1Euy -> if Helper.hasREPZ t.TPrefixes then parseCETInstr t reader pos - else raise InvalidOpcodeException - | 0x1Fuy -> parseOp t Opcode.NOP SzDef32 E0v, pos - | 0x20uy -> parseOp t Opcode.MOV Sz64 RdCd, pos - | 0x21uy -> parseOp t Opcode.MOV SzDef32 RdDd, pos - | 0x22uy -> parseOp t Opcode.MOV SzDef32 CdRd, pos - | 0x23uy -> parseOp t Opcode.MOV SzDef32 DdRd, pos - | 0x28uy -> parseVEX t SzDef32 opNor0F28 opVex0F28 dsNor0F28 dsVex0F28, pos - | 0x29uy -> parseVEX t SzDef32 opNor0F29 opVex0F29 dsNor0F29 dsVex0F29, pos - | 0x2Auy -> parseVEX t SzDef32 opNor0F2A opVex0F2A dsNor0F2A dsVex0F2A, pos - | 0x2Buy -> parseVEX t SzDef32 opNor0F2B opVex0F2B dsNor0F2B dsVex0F2B, pos - | 0x2Cuy -> parseVEX t SzDef32 opNor0F2C opVex0F2C dsNor0F2C dsVex0F2C, pos - | 0x2Duy -> parseVEX t SzDef32 opNor0F2D opVex0F2D dsNor0F2D dsVex0F2D, pos - | 0x2Euy -> parseVEX t SzDef32 opNor0F2E opVex0F2E dsNor0F2E dsVex0F2E, pos - | 0x2Fuy -> parseVEX t SzDef32 opNor0F2F opVex0F2F dsNor0F2F dsVex0F2F, pos - | 0x30uy -> parseOp t Opcode.WRMSR SzDef32 [||], pos - | 0x31uy -> parseOp t Opcode.RDTSC SzDef32 [||], pos - | 0x32uy -> parseOp t Opcode.RDMSR SzDef32 [||], pos - | 0x33uy -> parseOp t Opcode.RDPMC SzDef32 [||], pos - | 0x34uy -> parseOp t Opcode.SYSENTER SzDef32 [||], pos - | 0x35uy -> parseOp t Opcode.SYSEXIT SzDef32 [||], pos - | 0x37uy -> parseOp t Opcode.GETSEC SzDef32 [||], pos - | 0x40uy -> parseOp t Opcode.CMOVO SzDef32 GvEv, pos - | 0x41uy -> parseOp t Opcode.CMOVNO SzDef32 GvEv, pos - | 0x42uy -> parseOp t Opcode.CMOVB SzDef32 GvEv, pos - | 0x43uy -> parseOp t Opcode.CMOVAE SzDef32 GvEv, pos - | 0x44uy -> parseOp t Opcode.CMOVZ SzDef32 GvEv, pos - | 0x45uy -> parseOp t Opcode.CMOVNZ SzDef32 GvEv, pos - | 0x46uy -> parseOp t Opcode.CMOVBE SzDef32 GvEv, pos - | 0x47uy -> parseOp t Opcode.CMOVA SzDef32 GvEv, pos - | 0x48uy -> parseOp t Opcode.CMOVS SzDef32 GvEv, pos - | 0x49uy -> parseOp t Opcode.CMOVNS SzDef32 GvEv, pos - | 0x4Auy -> parseOp t Opcode.CMOVP SzDef32 GvEv, pos - | 0x4Buy -> parseOp t Opcode.CMOVNP SzDef32 GvEv, pos - | 0x4Cuy -> parseOp t Opcode.CMOVL SzDef32 GvEv, pos - | 0x4Duy -> parseOp t Opcode.CMOVGE SzDef32 GvEv, pos - | 0x4Euy -> parseOp t Opcode.CMOVLE SzDef32 GvEv, pos - | 0x4Fuy -> parseOp t Opcode.CMOVG SzDef32 GvEv, pos - | 0x50uy -> parseVEX t SzDef32 opNor0F50 opVex0F50 dsNor0F50 dsVex0F50, pos - | 0x51uy -> parseVEX t SzDef32 opNor0F51 opVex0F51 dsNor0F51 dsVex0F51, pos - | 0x54uy -> parseVEX t SzDef32 opNor0F54 opVex0F54 dsNor0F54 dsVex0F54, pos - | 0x55uy -> parseVEX t SzDef32 opNor0F55 opVex0F55 dsNor0F55 dsVex0F55, pos - | 0x56uy -> parseVEX t SzDef32 opNor0F56 opVex0F56 dsNor0F56 dsVex0F56, pos - | 0x57uy -> parseVEX t SzDef32 opNor0F57 opVex0F57 dsNor0F57 dsVex0F57, pos - | 0x58uy -> parseVEX t SzDef32 opNor0F58 opVex0F58 dsNor0F58 dsVex0F58, pos - | 0x59uy -> parseVEX t SzDef32 opNor0F59 opVex0F59 dsNor0F59 dsVex0F59, pos - | 0x5Auy -> parseVEX t SzDef32 opNor0F5A opVex0F5A dsNor0F5A dsVex0F5A, pos - | 0x5Buy -> parseVEX t SzDef32 opNor0F5B opVex0F5B dsNor0F5B dsVex0F5B, pos - | 0x5Cuy -> parseVEX t SzDef32 opNor0F5C opVex0F5C dsNor0F5C dsVex0F5C, pos - | 0x5Duy -> parseVEX t SzDef32 opNor0F5D opVex0F5D dsNor0F5D dsVex0F5D, pos - | 0x5Euy -> parseVEX t SzDef32 opNor0F5E opVex0F5E dsNor0F5E dsVex0F5E, pos - | 0x5Fuy -> parseVEX t SzDef32 opNor0F5F opVex0F5F dsNor0F5F dsVex0F5F, pos - | 0x60uy -> parseVEX t SzDef32 opNor0F60 opVex0F60 dsNor0F60 dsVex0F60, pos - | 0x61uy -> parseVEX t SzDef32 opNor0F61 opVex0F61 dsNor0F61 dsVex0F61, pos - | 0x62uy -> parseVEX t SzDef32 opNor0F62 opVex0F62 dsNor0F62 dsVex0F62, pos - | 0x63uy -> parseVEX t SzDef32 opNor0F63 opVex0F63 dsNor0F63 dsVex0F63, pos - | 0x64uy -> parseVEX t SzDef32 opNor0F64 opVex0F64 dsNor0F64 dsVex0F64, pos - | 0x65uy -> parseVEX t SzDef32 opNor0F65 opVex0F65 dsNor0F65 dsVex0F65, pos - | 0x66uy -> parseVEX t SzDef32 opNor0F66 opVex0F66 dsNor0F66 dsVex0F66, pos - | 0x67uy -> parseVEX t SzDef32 opNor0F67 opVex0F67 dsNor0F67 dsVex0F67, pos - | 0x68uy -> parseVEX t SzDef32 opNor0F68 opVex0F68 dsNor0F68 dsVex0F68, pos - | 0x69uy -> parseVEX t SzDef32 opNor0F69 opVex0F69 dsNor0F69 dsVex0F69, pos - | 0x6Auy -> parseVEX t SzDef32 opNor0F6A opVex0F6A dsNor0F6A dsVex0F6A, pos - | 0x6Buy -> parseVEX t SzDef32 opNor0F6B opVex0F6B dsNor0F6B dsVex0F6B, pos - | 0x6Cuy -> parseVEX t SzDef32 opNor0F6C opVex0F6C dsNor0F6C dsVex0F6C, pos - | 0x6Duy -> parseVEX t SzDef32 opNor0F6D opVex0F6D dsNor0F6D dsVex0F6D, pos - | 0x6Euy -> parseVEXByRex t pos opNor0F6EB64 opNor0F6EB32 - opVex0F6EB64 opVex0F6EB32 - dsNor0F6EB64 dsNor0F6EB32 - dsVex0F6EB64 dsVex0F6EB32 - | 0x6Fuy -> parseEVEXByRex t pos opNor0F6F opVex0F6F - opEVex0F6FB64 opEVex0F6FB32 - dsNor0F6F dsVex0F6F - dsEVex0F6FB64 dsEVex0F6FB32 - | 0x70uy -> parseVEX t SzDef32 opNor0F70 opVex0F70 dsNor0F70 dsVex0F70, pos - | 0x74uy -> parseVEX t SzDef32 opNor0F74 opVex0F74 dsNor0F74 dsVex0F74, pos - | 0x75uy -> parseVEX t SzDef32 opNor0F75 opVex0F75 dsNor0F75 dsVex0F75, pos - | 0x76uy -> parseVEX t SzDef32 opNor0F76 opVex0F76 dsNor0F76 dsVex0F76, pos - | 0x77uy -> parseVEX t SzDef32 opNor0F77 opVex0F77 dsNor0F77 dsVex0F77, pos - | 0x7Euy -> parseVEXByRex t pos opNor0F7EB64 opNor0F7EB32 - opVex0F7EB64 opVex0F7EB32 - dsNor0F7EB64 dsNor0F7EB32 - dsVex0F7EB64 dsVex0F7EB32 - | 0x7Fuy -> parseEVEXByRex t pos opNor0F7F opVex0F7F - opEVex0F7FB64 opEVex0F7FB32 - dsNor0F7F dsVex0F7F - dsEVex0F7FB64 dsEVex0F7FB32 - | 0x80uy -> parseOp (pBNDPref t) Opcode.JO Sz64 Jz, pos - | 0x81uy -> parseOp (pBNDPref t) Opcode.JNO Sz64 Jz, pos - | 0x82uy -> parseOp (pBNDPref t) Opcode.JB Sz64 Jz, pos - | 0x83uy -> parseOp (pBNDPref t) Opcode.JNB Sz64 Jz, pos - | 0x84uy -> parseOp (pBNDPref t) Opcode.JZ Sz64 Jz, pos - | 0x85uy -> parseOp (pBNDPref t) Opcode.JNZ Sz64 Jz, pos - | 0x86uy -> parseOp (pBNDPref t) Opcode.JBE Sz64 Jz, pos - | 0x87uy -> parseOp (pBNDPref t) Opcode.JA Sz64 Jz, pos - | 0x88uy -> parseOp (pBNDPref t) Opcode.JS Sz64 Jz, pos - | 0x89uy -> parseOp (pBNDPref t) Opcode.JNS Sz64 Jz, pos - | 0x8Auy -> parseOp (pBNDPref t) Opcode.JP Sz64 Jz, pos - | 0x8Buy -> parseOp (pBNDPref t) Opcode.JNP Sz64 Jz, pos - | 0x8Cuy -> parseOp (pBNDPref t) Opcode.JL Sz64 Jz, pos - | 0x8Duy -> parseOp (pBNDPref t) Opcode.JNL Sz64 Jz, pos - | 0x8Euy -> parseOp (pBNDPref t) Opcode.JLE Sz64 Jz, pos - | 0x8Fuy -> parseOp (pBNDPref t) Opcode.JG Sz64 Jz, pos - | 0x90uy -> parseOp t Opcode.SETO SzDef32 Eb, pos - | 0x91uy -> parseOp t Opcode.SETNO SzDef32 Eb, pos - | 0x92uy -> parseOp t Opcode.SETB SzDef32 Eb, pos - | 0x93uy -> parseOp t Opcode.SETNB SzDef32 Eb, pos - | 0x94uy -> parseOp t Opcode.SETZ SzDef32 Eb, pos - | 0x95uy -> parseOp t Opcode.SETNZ SzDef32 Eb, pos - | 0x96uy -> parseOp t Opcode.SETBE SzDef32 Eb, pos - | 0x97uy -> parseOp t Opcode.SETA SzDef32 Eb, pos - | 0x98uy -> parseOp t Opcode.SETS SzDef32 Eb, pos - | 0x99uy -> parseOp t Opcode.SETNS SzDef32 Eb, pos - | 0x9Auy -> parseOp t Opcode.SETP SzDef32 Eb, pos - | 0x9Buy -> parseOp t Opcode.SETNP SzDef32 Eb, pos - | 0x9Cuy -> parseOp t Opcode.SETL SzDef32 Eb, pos - | 0x9Duy -> parseOp t Opcode.SETNL SzDef32 Eb, pos - | 0x9Euy -> parseOp t Opcode.SETLE SzDef32 Eb, pos - | 0x9Fuy -> parseOp t Opcode.SETG SzDef32 Eb, pos - | 0xA0uy -> parseOp t Opcode.PUSH SzDef64 (ORSR R.FS), pos - | 0xA1uy -> parseOp t Opcode.POP SzDef64 (ORSR R.FS), pos - | 0xA2uy -> parseOp t Opcode.CPUID SzDef32 [||], pos - | 0xA3uy -> parseOp t Opcode.BT SzDef32 EvGv, pos - | 0xA4uy -> parseOp t Opcode.SHLD SzDef32 EvGvIb, pos - | 0xA5uy -> parseOp t Opcode.SHLD SzDef32 EvGvCL, pos - | 0xA8uy -> parseOp t Opcode.PUSH SzDef64 (ORSR R.GS), pos - | 0xA9uy -> parseOp t Opcode.POP SzDef64 (ORSR R.GS), pos - | 0xAAuy -> parseOp t Opcode.RSM SzDef32 [||], pos - | 0xABuy -> parseOp t Opcode.BTS SzDef32 EvGv, pos - | 0xACuy -> parseOp t Opcode.SHRD SzDef32 EvGvIb, pos - | 0xADuy -> parseOp t Opcode.SHRD SzDef32 EvGvCL, pos - | 0xAFuy -> parseOp t Opcode.IMUL SzDef32 GvEv, pos - | 0xB0uy -> parseOp t Opcode.CMPXCHG SzDef32 EbGb, pos - | 0xB1uy -> parseOp t Opcode.CMPXCHG SzDef32 EvGv, pos - | 0xB2uy -> parseOp t Opcode.LSS SzDef32 GvMp, pos - | 0xB3uy -> parseOp t Opcode.BTR SzDef32 EvGv, pos - | 0xB4uy -> parseOp t Opcode.LFS SzDef32 GvMp, pos - | 0xB5uy -> parseOp t Opcode.LGS SzDef32 GvMp, pos - | 0xB6uy -> parseOp t Opcode.MOVZX SzDef32 GvEb, pos - | 0xB7uy -> parseOp t Opcode.MOVZX SzDef32 GvEw, pos - | 0xB8uy when not <| hasREPZ t.TPrefixes -> raise ParsingFailureException - | 0xB8uy -> parseOp t Opcode.POPCNT SzDef32 GvEv, pos - | 0xBBuy when hasREPZ t.TPrefixes -> raise ParsingFailureException - | 0xBBuy -> parseOp t Opcode.BTC SzDef32 EvGv, pos - | 0xBCuy when hasREPZ t.TPrefixes -> parseOp t Opcode.TZCNT SzDef32 GvEv, pos - | 0xBCuy -> parseOp t Opcode.BSF SzDef32 GvEv, pos - | 0xBDuy when hasREPZ t.TPrefixes -> parseOp t Opcode.LZCNT SzDef32 GvEv, pos - | 0xBDuy -> parseOp t Opcode.BSR SzDef32 GvEv, pos - | 0xBEuy -> parseOp t Opcode.MOVSX SzDef32 GvEb, pos - | 0xBFuy -> parseOp t Opcode.MOVSX SzDef32 GvEw, pos - | 0xC0uy -> parseOp t Opcode.XADD SzDef32 EbGb, pos - | 0xC1uy -> parseOp t Opcode.XADD SzDef32 EvGv, pos - | 0xC2uy -> parseVEX t SzDef32 opNor0FC2 opVex0FC2 dsNor0FC2 dsVex0FC2, pos - | 0xC3uy -> parseOp t Opcode.MOVNTI SzDef32 MyGy, pos - | 0xC4uy -> parseVEX t SzDef32 opNor0FC4 opVex0FC4 dsNor0FC4 dsVex0FC4, pos - | 0xC5uy -> parseVEX t SzDef32 opNor0FC5 opVex0FC5 dsNor0FC5 dsVex0FC5, pos - | 0xC6uy -> parseVEX t SzDef32 opNor0FC6 opVex0FC6 dsNor0FC6 dsVex0FC6, pos - | 0xC8uy -> - parseOp (ignOpSz t) Opcode.BSWAP SzDef32 (RGz RegGrp.RG0 true), pos - | 0xC9uy -> - parseOp (ignOpSz t) Opcode.BSWAP SzDef32 (RGz RegGrp.RG1 true), pos - | 0xCAuy -> - parseOp (ignOpSz t) Opcode.BSWAP SzDef32 (RGz RegGrp.RG2 true), pos - | 0xCBuy -> - parseOp (ignOpSz t) Opcode.BSWAP SzDef32 (RGz RegGrp.RG3 true), pos - | 0xCCuy -> - parseOp (ignOpSz t) Opcode.BSWAP SzDef32 (RGz RegGrp.RG4 true), pos - | 0xCDuy -> - parseOp (ignOpSz t) Opcode.BSWAP SzDef32 (RGz RegGrp.RG5 true), pos - | 0xCEuy -> - parseOp (ignOpSz t) Opcode.BSWAP SzDef32 (RGz RegGrp.RG6 true), pos - | 0xCFuy -> - parseOp (ignOpSz t) Opcode.BSWAP SzDef32 (RGz RegGrp.RG7 true), pos - | 0xD1uy -> parseVEX t SzDef32 opNor0FD1 opVex0FD1 dsNor0FD1 dsVex0FD1, pos - | 0xD2uy -> parseVEX t SzDef32 opNor0FD2 opVex0FD2 dsNor0FD2 dsVex0FD2, pos - | 0xD3uy -> parseVEX t SzDef32 opNor0FD3 opVex0FD3 dsNor0FD3 dsVex0FD3, pos - | 0xD4uy -> parseVEX t SzDef32 opNor0FD4 opVex0FD4 dsNor0FD4 dsVex0FD4, pos - | 0xD5uy -> parseVEX t SzDef32 opNor0FD5 opVex0FD5 dsNor0FD5 dsVex0FD5, pos - | 0xD6uy -> assertVEX128 t - parseVEX t SzDef32 opNor0FD6 opVex0FD6 dsNor0FD6 dsVex0FD6, pos - | 0xD7uy -> parseVEX t SzDef32 opNor0FD7 opVex0FD7 dsNor0FD7 dsVex0FD7, pos - | 0xD8uy -> parseVEX t SzDef32 opNor0FD8 opVex0FD8 dsNor0FD8 dsVex0FD8, pos - | 0xD9uy -> parseVEX t SzDef32 opNor0FD9 opVex0FD9 dsNor0FD9 dsVex0FD9, pos - | 0xDAuy -> parseVEX t SzDef32 opNor0FDA opVex0FDA dsNor0FDA dsVex0FDA, pos - | 0xDBuy -> parseVEX t SzDef32 opNor0FDB opVex0FDB dsNor0FDB dsVex0FDB, pos - | 0xDCuy -> parseVEX t SzDef32 opNor0FDC opVex0FDC dsNor0FDC dsVex0FDC, pos - | 0xDDuy -> parseVEX t SzDef32 opNor0FDD opVex0FDD dsNor0FDD dsVex0FDD, pos - | 0xDEuy -> parseVEX t SzDef32 opNor0FDE opVex0FDE dsNor0FDE dsVex0FDE, pos - | 0xDFuy -> parseVEX t SzDef32 opNor0FDF opVex0FDF dsNor0FDF dsVex0FDF, pos - | 0xE0uy -> parseVEX t SzDef32 opNor0FE0 opVex0FE0 dsNor0FE0 dsVex0FE0, pos - | 0xE1uy -> parseVEX t SzDef32 opNor0FE1 opVex0FE1 dsNor0FE1 dsVex0FE1, pos - | 0xE2uy -> parseVEX t SzDef32 opNor0FE2 opVex0FE2 dsNor0FE2 dsVex0FE2, pos - | 0xE3uy -> parseVEX t SzDef32 opNor0FE3 opVex0FE3 dsNor0FE3 dsVex0FE3, pos - | 0xE4uy -> parseVEX t SzDef32 opNor0FE4 opVex0FE4 dsNor0FE4 dsVex0FE4, pos - | 0xE5uy -> parseVEX t SzDef32 opNor0FE5 opVex0FE5 dsNor0FE5 dsVex0FE5, pos - | 0xE6uy -> parseVEX t SzDef32 opNor0FE6 opVex0FE6 dsNor0FE6 dsVex0FE6, pos - | 0xE7uy -> parseEVEXByRex t pos opNor0FE7 opVex0FE7 - opEVex0FE7B64 opEVex0FE7B32 - dsNor0FE7 dsVex0FE7 - dsEVex0FE7B64 dsEVex0FE7B32 - | 0xE8uy -> parseVEX t SzDef32 opNor0FE8 opVex0FE8 dsNor0FE8 dsVex0FE8, pos - | 0xE9uy -> parseVEX t SzDef32 opNor0FE9 opVex0FE9 dsNor0FE9 dsVex0FE9, pos - | 0xEAuy -> parseVEX t SzDef32 opNor0FEA opVex0FEA dsNor0FEA dsVex0FEA, pos - | 0xEBuy -> parseVEX t SzDef32 opNor0FEB opVex0FEB dsNor0FEB dsVex0FEB, pos - | 0xECuy -> parseVEX t SzDef32 opNor0FEC opVex0FEC dsNor0FEC dsVex0FEC, pos - | 0xEDuy -> parseVEX t SzDef32 opNor0FED opVex0FED dsNor0FED dsVex0FED, pos - | 0xEEuy -> parseVEX t SzDef32 opNor0FEE opVex0FEE dsNor0FEE dsVex0FEE, pos - | 0xEFuy -> parseVEX t SzDef32 opNor0FEF opVex0FEF dsNor0FEF dsVex0FEF, pos - | 0xF0uy -> parseVEX t SzDef32 opNor0FF0 opVex0FF0 dsNor0FF0 dsVex0FF0, pos - | 0xF1uy -> parseVEX t SzDef32 opNor0FF1 opVex0FF1 dsNor0FF1 dsVex0FF1, pos - | 0xF2uy -> parseVEX t SzDef32 opNor0FF2 opVex0FF2 dsNor0FF2 dsVex0FF2, pos - | 0xF3uy -> parseVEX t SzDef32 opNor0FF3 opVex0FF3 dsNor0FF3 dsVex0FF3, pos - | 0xF4uy -> parseVEX t SzDef32 opNor0FF4 opVex0FF4 dsNor0FF4 dsVex0FF4, pos - | 0xF5uy -> parseVEX t SzDef32 opNor0FF5 opVex0FF5 dsNor0FF5 dsVex0FF5, pos - | 0xF6uy -> parseVEX t SzDef32 opNor0FF6 opVex0FF6 dsNor0FF6 dsVex0FF6, pos - | 0xF8uy -> parseVEX t SzDef32 opNor0FF8 opVex0FF8 dsNor0FF8 dsVex0FF8, pos - | 0xF9uy -> parseVEX t SzDef32 opNor0FF9 opVex0FF9 dsNor0FF9 dsVex0FF9, pos - | 0xFAuy -> parseVEX t SzDef32 opNor0FFA opVex0FFA dsNor0FFA dsVex0FFA, pos - | 0xFBuy -> parseVEX t SzDef32 opNor0FFB opVex0FFB dsNor0FFB dsVex0FFB, pos - | 0xFCuy -> parseVEX t SzDef32 opNor0FFC opVex0FFC dsNor0FFC dsVex0FFC, pos - | 0xFDuy -> parseVEX t SzDef32 opNor0FFD opVex0FFD dsNor0FFD dsVex0FFD, pos - | 0xFEuy -> parseVEX t SzDef32 opNor0FFE opVex0FFE dsNor0FFE dsVex0FFE, pos - (* Group Opcode s: Vol.2C A-19 Table A-6. Opcode Extensions for One- and - Two-byte Opcodes by Group Number *) - | 0x00uy -> parseGrpOpcode t reader pos OpGroup.G6 [||] - | 0x01uy -> parseGrpOpcode t reader pos OpGroup.G7 [||] - | 0xBAuy -> parseGrpOpcode t reader pos OpGroup.G8 EvIb - | 0xC7uy -> parseGrpOpcode t reader pos OpGroup.G9 [||] - | 0x71uy -> parseGrpOpcode t reader pos OpGroup.G12 [||] - | 0x72uy -> parseGrpOpcode t reader pos OpGroup.G13 [||] - | 0x73uy -> parseGrpOpcode t reader pos OpGroup.G14 [||] - | 0xAEuy -> parseGrpOpcode t reader pos OpGroup.G15 [||] - | 0x18uy -> parseGrpOpcode t reader pos OpGroup.G16 Mv - | 0x38uy -> parseThreeByteOp1 t reader pos - | 0x3Auy -> parseThreeByteOp2 t reader pos - | _ -> raise ParsingFailureException - -(* Table A-3 of Volume 2 (Two-byte Opcode Map) *) -let private parseTwoByteOpcode t (reader: BinReader) pos = - reader.PeekByte pos |> pTwoByteOp t reader (pos + 1) - -let inline private getDescForRegGrp t regGrp = - int regGrp |> findReg 8 RGrpAttr.AMod11 t.TREXPrefix |> RegIb - -let private pOneByteOpcode t reader pos = function - | 0x00uy -> parseOp t Opcode.ADD SzDef32 EbGb, pos - | 0x01uy -> parseOp t Opcode.ADD SzDef32 EvGv, pos - | 0x02uy -> parseOp t Opcode.ADD SzDef32 GbEb, pos - | 0x03uy -> parseOp t Opcode.ADD SzDef32 GvEv, pos - | 0x04uy -> parseOp t Opcode.ADD SzDef32 ALIb, pos - | 0x05uy -> parseOp t Opcode.ADD SzDef32 RGvSIz, pos - | 0x06uy -> ensure32 t; parseOp t Opcode.PUSH SzInv64 (ORSR R.ES), pos - | 0x07uy -> ensure32 t; parseOp t Opcode.POP SzInv64 (ORSR R.ES), pos - | 0x08uy -> parseOp t Opcode.OR SzDef32 EbGb, pos - | 0x09uy -> parseOp t Opcode.OR SzDef32 EvGv, pos - | 0x0Auy -> parseOp t Opcode.OR SzDef32 GbEb, pos - | 0x0Buy -> parseOp t Opcode.OR SzDef32 GvEv, pos - | 0x0Cuy -> parseOp t Opcode.OR SzDef32 ALIb, pos - | 0x0Duy -> parseOp t Opcode.OR SzDef32 RGvSIz, pos - | 0x0Euy -> ensure32 t; parseOp t Opcode.PUSH SzInv64 (ORSR R.CS), pos - | 0x10uy -> parseOp t Opcode.ADC SzDef32 EbGb, pos - | 0x11uy -> parseOp t Opcode.ADC SzDef32 EvGv, pos - | 0x12uy -> parseOp t Opcode.ADC SzDef32 GbEb, pos - | 0x13uy -> parseOp t Opcode.ADC SzDef32 GvEv, pos - | 0x14uy -> parseOp t Opcode.ADC SzDef32 ALIb, pos - | 0x15uy -> parseOp t Opcode.ADC SzDef32 RGvSIz, pos - | 0x16uy -> ensure32 t; parseOp t Opcode.PUSH SzInv64 (ORSR R.SS), pos - | 0x17uy -> ensure32 t; parseOp t Opcode.POP SzInv64 (ORSR R.SS), pos - | 0x18uy -> parseOp t Opcode.SBB SzDef32 EbGb, pos - | 0x19uy -> parseOp t Opcode.SBB SzDef32 EvGv, pos - | 0x1Auy -> parseOp t Opcode.SBB SzDef32 GbEb, pos - | 0x1Buy -> parseOp t Opcode.SBB SzDef32 GvEv, pos - | 0x1Cuy -> parseOp t Opcode.SBB SzDef32 ALIb, pos - | 0x1Duy -> parseOp t Opcode.SBB SzDef32 RGvSIz, pos - | 0x1Euy -> ensure32 t; parseOp t Opcode.PUSH SzInv64 (ORSR R.DS), pos - | 0x1Fuy -> ensure32 t; parseOp t Opcode.POP SzInv64 (ORSR R.DS), pos - | 0x20uy -> parseOp t Opcode.AND SzDef32 EbGb, pos - | 0x21uy -> parseOp t Opcode.AND SzDef32 EvGv, pos - | 0x22uy -> parseOp t Opcode.AND SzDef32 GbEb, pos - | 0x23uy -> parseOp t Opcode.AND SzDef32 GvEv, pos - | 0x24uy -> parseOp t Opcode.AND SzDef32 ALIb, pos - | 0x25uy -> parseOp t Opcode.AND SzDef32 RGvSIz, pos - | 0x27uy -> ensure32 t; parseOp t Opcode.DAA SzInv64 [||], pos - | 0x28uy -> parseOp t Opcode.SUB SzDef32 EbGb, pos - | 0x29uy -> parseOp t Opcode.SUB SzDef32 EvGv, pos - | 0x2Auy -> parseOp t Opcode.SUB SzDef32 GbEb, pos - | 0x2Buy -> parseOp t Opcode.SUB SzDef32 GvEv, pos - | 0x2Cuy -> parseOp t Opcode.SUB SzDef32 ALIb, pos - | 0x2Duy -> parseOp t Opcode.SUB SzDef32 RGvSIz, pos - | 0x2Fuy -> ensure32 t; parseOp t Opcode.DAS SzInv64 [||], pos - | 0x30uy -> parseOp t Opcode.XOR SzDef32 EbGb, pos - | 0x31uy -> parseOp t Opcode.XOR SzDef32 EvGv, pos - | 0x32uy -> parseOp t Opcode.XOR SzDef32 GbEb, pos - | 0x33uy -> parseOp t Opcode.XOR SzDef32 GvEv, pos - | 0x34uy -> parseOp t Opcode.XOR SzDef32 ALIb, pos - | 0x35uy -> parseOp t Opcode.XOR SzDef32 RGvSIz, pos - | 0x37uy -> ensure32 t; parseOp t Opcode.AAA SzInv64 [||], pos - | 0x38uy -> parseOp t Opcode.CMP SzDef32 EbGb, pos - | 0x39uy -> parseOp t Opcode.CMP SzDef32 EvGv, pos - | 0x3Auy -> parseOp t Opcode.CMP SzDef32 GbEb, pos - | 0x3Buy -> parseOp t Opcode.CMP SzDef32 GvEv, pos - | 0x3Cuy -> parseOp t Opcode.CMP SzDef32 ALIb, pos - | 0x3Duy -> parseOp t Opcode.CMP SzDef32 RGvSIz, pos - | 0x3Fuy -> - ensure32 t; parseOp t Opcode.AAS SzInv64 [||], pos - | 0x40uy -> - ensure32 t; parseOp t Opcode.INC SzInv64 (RGz RegGrp.RG0 false), pos - | 0x41uy -> - ensure32 t; parseOp t Opcode.INC SzInv64 (RGz RegGrp.RG1 false), pos - | 0x42uy -> - ensure32 t; parseOp t Opcode.INC SzInv64 (RGz RegGrp.RG2 false), pos - | 0x43uy -> - ensure32 t; parseOp t Opcode.INC SzInv64 (RGz RegGrp.RG3 false), pos - | 0x44uy -> - ensure32 t; parseOp t Opcode.INC SzInv64 (RGz RegGrp.RG4 false), pos - | 0x45uy -> - ensure32 t; parseOp t Opcode.INC SzInv64 (RGz RegGrp.RG5 false), pos - | 0x46uy -> - ensure32 t; parseOp t Opcode.INC SzInv64 (RGz RegGrp.RG6 false), pos - | 0x47uy -> - ensure32 t; parseOp t Opcode.INC SzInv64 (RGz RegGrp.RG7 false), pos - | 0x48uy -> - ensure32 t; parseOp t Opcode.DEC SzInv64 (RGz RegGrp.RG0 false), pos - | 0x49uy -> - ensure32 t; parseOp t Opcode.DEC SzInv64 (RGz RegGrp.RG1 false), pos - | 0x4Auy -> - ensure32 t; parseOp t Opcode.DEC SzInv64 (RGz RegGrp.RG2 false), pos - | 0x4Buy -> - ensure32 t; parseOp t Opcode.DEC SzInv64 (RGz RegGrp.RG3 false), pos - | 0x4Cuy -> - ensure32 t; parseOp t Opcode.DEC SzInv64 (RGz RegGrp.RG4 false), pos - | 0x4Duy -> - ensure32 t; parseOp t Opcode.DEC SzInv64 (RGz RegGrp.RG5 false), pos - | 0x4Euy -> - ensure32 t; parseOp t Opcode.DEC SzInv64 (RGz RegGrp.RG6 false), pos - | 0x4Fuy -> - ensure32 t; parseOp t Opcode.DEC SzInv64 (RGz RegGrp.RG7 false), pos - | 0x50uy -> parseOp t Opcode.PUSH SzDef64 (RGv RegGrp.RG0), pos - | 0x51uy -> parseOp t Opcode.PUSH SzDef64 (RGv RegGrp.RG1), pos - | 0x52uy -> parseOp t Opcode.PUSH SzDef64 (RGv RegGrp.RG2), pos - | 0x53uy -> parseOp t Opcode.PUSH SzDef64 (RGv RegGrp.RG3), pos - | 0x54uy -> parseOp t Opcode.PUSH SzDef64 (RGv RegGrp.RG4), pos - | 0x55uy -> parseOp t Opcode.PUSH SzDef64 (RGv RegGrp.RG5), pos - | 0x56uy -> parseOp t Opcode.PUSH SzDef64 (RGv RegGrp.RG6), pos - | 0x57uy -> parseOp t Opcode.PUSH SzDef64 (RGv RegGrp.RG7), pos - | 0x58uy -> parseOp t Opcode.POP SzDef64 (RGv RegGrp.RG0), pos - | 0x59uy -> parseOp t Opcode.POP SzDef64 (RGv RegGrp.RG1), pos - | 0x5Auy -> parseOp t Opcode.POP SzDef64 (RGv RegGrp.RG2), pos - | 0x5Buy -> parseOp t Opcode.POP SzDef64 (RGv RegGrp.RG3), pos - | 0x5Cuy -> parseOp t Opcode.POP SzDef64 (RGv RegGrp.RG4), pos - | 0x5Duy -> parseOp t Opcode.POP SzDef64 (RGv RegGrp.RG5), pos - | 0x5Euy -> parseOp t Opcode.POP SzDef64 (RGv RegGrp.RG6), pos - | 0x5Fuy -> parseOp t Opcode.POP SzDef64 (RGv RegGrp.RG7), pos - | 0x60uy -> - ensure32 t - if hasOprSz t.TPrefixes then parseOp t Opcode.PUSHA SzInv64 [||], pos - else parseOp t Opcode.PUSHAD SzInv64 [||], pos - | 0x61uy -> - ensure32 t - if hasOprSz t.TPrefixes then parseOp t Opcode.POPA SzInv64 [||], pos - else parseOp t Opcode.POPAD SzInv64 [||], pos - | 0x62uy -> ensure32 t; parseOp t Opcode.BOUND SzInv64 GvMa, pos - | 0x63uy -> - if is64bit t && not (hasREXW t.TREXPrefix) then - raise ParsingFailureException - elif is64bit t then parseOp t Opcode.MOVSXD SzOnly64 GvEd, pos - else parseOp t Opcode.ARPL SzInv64 EwGw, pos - | 0x68uy -> parseOp t Opcode.PUSH SzDef64 SIz, pos - | 0x69uy -> parseOp t Opcode.IMUL SzDef32 GvEvSIz, pos - | 0x6Auy -> parseOp t Opcode.PUSH SzDef64 SIb, pos - | 0x6Buy -> parseOp t Opcode.IMUL SzDef32 GvEvSIb, pos - | 0x6Cuy -> parseOp t Opcode.INSB SzDef32 [||], pos - | 0x6Duy -> - if hasOprSz t.TPrefixes then parseOp t Opcode.INSW SzDef32 [||], pos - else parseOp t Opcode.INSD SzDef32 [||], pos - | 0x6Euy -> parseOp t Opcode.OUTSB SzDef32 [||], pos - | 0x6Fuy -> - if hasOprSz t.TPrefixes then parseOp t Opcode.OUTSW SzDef32 [||], pos - else parseOp t Opcode.OUTSD SzDef32 [||], pos - | 0x70uy -> parseOp (pBNDPref t) Opcode.JO Sz64 Jb, pos - | 0x71uy -> parseOp (pBNDPref t) Opcode.JNO Sz64 Jb, pos - | 0x72uy -> parseOp (pBNDPref t) Opcode.JB Sz64 Jb, pos - | 0x73uy -> parseOp (pBNDPref t) Opcode.JNB Sz64 Jb, pos - | 0x74uy -> parseOp (pBNDPref t) Opcode.JZ Sz64 Jb, pos - | 0x75uy -> parseOp (pBNDPref t) Opcode.JNZ Sz64 Jb, pos - | 0x76uy -> parseOp (pBNDPref t) Opcode.JBE Sz64 Jb, pos - | 0x77uy -> parseOp (pBNDPref t) Opcode.JA Sz64 Jb, pos - | 0x78uy -> parseOp (pBNDPref t) Opcode.JS Sz64 Jb, pos - | 0x79uy -> parseOp (pBNDPref t) Opcode.JNS Sz64 Jb, pos - | 0x7Auy -> parseOp (pBNDPref t) Opcode.JP Sz64 Jb, pos - | 0x7Buy -> parseOp (pBNDPref t) Opcode.JNP Sz64 Jb, pos - | 0x7Cuy -> parseOp (pBNDPref t) Opcode.JL Sz64 Jb, pos - | 0x7Duy -> parseOp (pBNDPref t) Opcode.JNL Sz64 Jb, pos - | 0x7Euy -> parseOp (pBNDPref t) Opcode.JLE Sz64 Jb, pos - | 0x7Fuy -> parseOp (pBNDPref t) Opcode.JG Sz64 Jb, pos - | 0x84uy -> parseOp t Opcode.TEST SzDef32 EbGb, pos - | 0x85uy -> parseOp t Opcode.TEST SzDef32 EvGv, pos - | 0x86uy -> parseOp t Opcode.XCHG SzDef32 EbGb, pos - | 0x87uy -> parseOp t Opcode.XCHG SzDef32 EvGv, pos - | 0x88uy -> parseOp t Opcode.MOV SzDef32 EbGb, pos - | 0x89uy -> parseOp t Opcode.MOV SzDef32 EvGv, pos - | 0x8Auy -> parseOp t Opcode.MOV SzDef32 GbEb, pos - | 0x8Buy -> parseOp t Opcode.MOV SzDef32 GvEv, pos - | 0x8Cuy -> parseOp t Opcode.MOV SzDef32 EvSw, pos - | 0x8Duy -> parseOp t Opcode.LEA SzDef32 GvMv, pos - | 0x8Euy -> parseOp t Opcode.MOV SzDef32 SwEw, pos - | 0x90uy -> - if hasNoPrefNoREX t then parseOp t Opcode.NOP SzDef32 [||], pos - elif hasREPZ t.TPrefixes then parseOp t Opcode.PAUSE SzDef32 [||], pos - else parseOp t Opcode.XCHG SzDef32 RGzRGz, pos - | 0x91uy -> parseOp t Opcode.XCHG SzDef32 (RGvRGv RegGrp.RG1), pos - | 0x92uy -> parseOp t Opcode.XCHG SzDef32 (RGvRGv RegGrp.RG2), pos - | 0x93uy -> parseOp t Opcode.XCHG SzDef32 (RGvRGv RegGrp.RG3), pos - | 0x94uy -> parseOp t Opcode.XCHG SzDef32 (RGvRGv RegGrp.RG4), pos - | 0x95uy -> parseOp t Opcode.XCHG SzDef32 (RGvRGv RegGrp.RG5), pos - | 0x96uy -> parseOp t Opcode.XCHG SzDef32 (RGvRGv RegGrp.RG6), pos - | 0x97uy -> parseOp t Opcode.XCHG SzDef32 (RGvRGv RegGrp.RG7), pos - | 0x98uy -> - if hasOprSz t.TPrefixes then parseOp t Opcode.CBW SzDef32 [||], pos - elif hasREXW t.TREXPrefix then parseOp t Opcode.CDQE SzDef32 [||], pos - else parseOp t Opcode.CWDE SzDef32 [||], pos - | 0x99uy -> - if hasOprSz t.TPrefixes then parseOp t Opcode.CWD SzDef32 [||], pos - elif hasREXW t.TREXPrefix then parseOp t Opcode.CQO SzDef32 [||], pos - else parseOp t Opcode.CDQ SzDef32 [||], pos - | 0x9Auy -> ensure32 t; parseOp (pBNDPref t) Opcode.CALLFar SzInv64 Ap, pos - | 0x9Buy -> parseOp t Opcode.WAIT SzDef32 [||], pos - | 0x9Cuy -> - if is64bitWithOprSz t then parseOp t Opcode.PUSHF SzDef64 [||], pos - elif hasOprSz t.TPrefixes then parseOp t Opcode.PUSHF SzDef32 [||], pos - elif is64bit t then parseOp t Opcode.PUSHFQ SzDef64 [||], pos - else parseOp t Opcode.PUSHFD SzDef32 [||], pos - | 0x9Duy -> - if is64bitWithOprSz t then parseOp t Opcode.POPF SzDef64 [||], pos - elif hasOprSz t.TPrefixes then parseOp t Opcode.POPF SzDef32 [||], pos - elif is64bit t then parseOp t Opcode.POPFQ SzDef64 [||], pos - else parseOp t Opcode.POPFD SzDef32 [||], pos - | 0x9Euy -> parseOp t Opcode.SAHF SzDef32 [||], pos - | 0x9Fuy -> parseOp t Opcode.LAHF SzDef32 [||], pos - | 0xA0uy -> parseOp t Opcode.MOV SzDef32 ALOb, pos - | 0xA1uy -> parseOp t Opcode.MOV SzDef32 (RGvOv RegGrp.RG0 false), pos - | 0xA2uy -> parseOp t Opcode.MOV SzDef32 ObAL, pos - | 0xA3uy -> parseOp t Opcode.MOV SzDef32 (OvRGv RegGrp.RG0 false), pos - | 0xA4uy -> parseOp t Opcode.MOVSB SzDef32 [||], pos - | 0xA5uy -> - if hasOprSz t.TPrefixes then parseOp t Opcode.MOVSW SzDef32 [||], pos - elif hasREXW t.TREXPrefix then parseOp t Opcode.MOVSQ SzDef32 [||], pos - else parseOp t Opcode.MOVSD SzDef32 [||], pos - | 0xA6uy -> parseOp t Opcode.CMPSB SzDef32 XbYb, pos - | 0xA7uy -> - if hasOprSz t.TPrefixes then parseOp t Opcode.CMPSW SzDef32 [||], pos - elif hasREXW t.TREXPrefix then parseOp t Opcode.CMPSQ SzDef32 [||], pos - else parseOp t Opcode.CMPSD SzDef32 [||], pos - | 0xA8uy -> parseOp t Opcode.TEST SzDef32 ALIb, pos - | 0xA9uy -> parseOp t Opcode.TEST SzDef32 RGvSIz, pos - | 0xAAuy -> parseOp t Opcode.STOSB SzDef32 [||], pos - | 0xABuy -> - if hasOprSz t.TPrefixes then parseOp t Opcode.STOSW SzDef32 [||], pos - elif hasREXW t.TREXPrefix then parseOp t Opcode.STOSQ SzDef32 [||], pos - else parseOp t Opcode.STOSD SzDef32 [||], pos - | 0xACuy -> parseOp t Opcode.LODSB SzDef32 [||], pos - | 0xADuy -> - if hasOprSz t.TPrefixes then parseOp t Opcode.LODSW SzDef32 [||], pos - elif hasREXW t.TREXPrefix then parseOp t Opcode.LODSQ SzDef32 [||], pos - else parseOp t Opcode.LODSD SzDef32 [||], pos - | 0xAEuy -> parseOp t Opcode.SCASB SzDef32 [||], pos - | 0xAFuy -> - if hasOprSz t.TPrefixes then parseOp t Opcode.SCASW SzDef32 [||], pos - elif hasREXW t.TREXPrefix then parseOp t Opcode.SCASQ SzDef32 [||], pos - else parseOp t Opcode.SCASD SzDef32 [||], pos - | 0xB0uy -> parseOp t Opcode.MOV SzDef32 (getDescForRegGrp t RegGrp.RG0), pos - | 0xB1uy -> parseOp t Opcode.MOV SzDef32 (getDescForRegGrp t RegGrp.RG1), pos - | 0xB2uy -> parseOp t Opcode.MOV SzDef32 (getDescForRegGrp t RegGrp.RG2), pos - | 0xB3uy -> parseOp t Opcode.MOV SzDef32 (getDescForRegGrp t RegGrp.RG3), pos - | 0xB4uy -> parseOp t Opcode.MOV SzDef32 (getDescForRegGrp t RegGrp.RG4), pos - | 0xB5uy -> parseOp t Opcode.MOV SzDef32 (getDescForRegGrp t RegGrp.RG5), pos - | 0xB6uy -> parseOp t Opcode.MOV SzDef32 (getDescForRegGrp t RegGrp.RG6), pos - | 0xB7uy -> parseOp t Opcode.MOV SzDef32 (getDescForRegGrp t RegGrp.RG7), pos - | 0xB8uy -> parseOp t Opcode.MOV SzDef32 (RGvIv RegGrp.RG0), pos - | 0xB9uy -> parseOp t Opcode.MOV SzDef32 (RGvIv RegGrp.RG1), pos - | 0xBAuy -> parseOp t Opcode.MOV SzDef32 (RGvIv RegGrp.RG2), pos - | 0xBBuy -> parseOp t Opcode.MOV SzDef32 (RGvIv RegGrp.RG3), pos - | 0xBCuy -> parseOp t Opcode.MOV SzDef32 (RGvIv RegGrp.RG4), pos - | 0xBDuy -> parseOp t Opcode.MOV SzDef32 (RGvIv RegGrp.RG5), pos - | 0xBEuy -> parseOp t Opcode.MOV SzDef32 (RGvIv RegGrp.RG6), pos - | 0xBFuy -> parseOp t Opcode.MOV SzDef32 (RGvIv RegGrp.RG7), pos - | 0xC2uy -> parseOp (pBNDPref t) Opcode.RETNearImm Sz64 Iw, pos - | 0xC3uy -> parseOp (pBNDPref t) Opcode.RETNear Sz64 [||], pos - | 0xC4uy -> ensure32 t; parseOp t Opcode.LES SzInv64 GzMp, pos - | 0xC5uy -> ensure32 t; parseOp t Opcode.LDS SzInv64 GzMp, pos - | 0xC8uy -> parseOp t Opcode.ENTER SzDef32 IwIb, pos - | 0xC9uy -> parseOp t Opcode.LEAVE SzDef64 [||], pos - | 0xCAuy -> parseOp (pBNDPref t) Opcode.RETFarImm SzDef32 Iw, pos - | 0xCBuy -> parseOp (pBNDPref t) Opcode.RETFar SzDef32 [||], pos - | 0xCCuy -> parseOp t Opcode.INT3 SzDef32 [||], pos - | 0xCDuy -> parseOp t Opcode.INT SzDef32 Ib, pos - | 0xCEuy -> ensure32 t; parseOp t Opcode.INTO SzInv64 [||], pos - | 0xCFuy -> - if hasOprSz t.TPrefixes then parseOp t Opcode.IRETW SzDef32 [||], pos - elif hasREXW t.TREXPrefix then parseOp t Opcode.IRETQ SzDef32 [||], pos - else parseOp t Opcode.IRETD SzDef32 [||], pos - | 0xD4uy -> ensure32 t; parseOp t Opcode.AAM SzInv64 Ib, pos - | 0xD5uy -> ensure32 t; parseOp t Opcode.AAD SzInv64 Ib, pos - | 0xD7uy -> parseOp t Opcode.XLATB SzDef32 [||], pos - | 0xD8uy -> parseESCOp t reader pos 0xD8uy getD8OpWithin00toBF getD8OverBF - | 0xD9uy -> parseESCOp t reader pos 0xD9uy getD9OpWithin00toBF getD9OverBF - | 0xDAuy -> parseESCOp t reader pos 0xDAuy getDAOpWithin00toBF getDAOverBF - | 0xDBuy -> parseESCOp t reader pos 0xDBuy getDBOpWithin00toBF getDBOverBF - | 0xDCuy -> parseESCOp t reader pos 0xDCuy getDCOpWithin00toBF getDCOverBF - | 0xDDuy -> parseESCOp t reader pos 0xDDuy getDDOpWithin00toBF getDDOverBF - | 0xDEuy -> parseESCOp t reader pos 0xDEuy getDEOpWithin00toBF getDEOverBF - | 0xDFuy -> parseESCOp t reader pos 0xDFuy getDFOpWithin00toBF getDFOverBF - | 0xE0uy -> parseOp t Opcode.LOOPNE Sz64 Jb, pos - | 0xE1uy -> parseOp t Opcode.LOOPE Sz64 Jb, pos - | 0xE2uy -> parseOp t Opcode.LOOP Sz64 Jb, pos - | 0xE3uy -> - if is64bitWithAddrSz t then parseOp t Opcode.JECXZ Sz64 Jb, pos - elif hasAddrSz t.TPrefixes then parseOp t Opcode.JCXZ Sz64 Jb, pos - elif is64bit t then parseOp t Opcode.JRCXZ Sz64 Jb, pos - else parseOp t Opcode.JECXZ Sz64 Jb, pos - | 0xE4uy -> parseOp t Opcode.IN SzDef32 ALIb, pos - | 0xE5uy -> parseOp t Opcode.IN SzDef32 (RGvIb RegGrp.RG0 false), pos - | 0xE6uy -> parseOp t Opcode.OUT SzDef32 IbAL, pos - | 0xE7uy -> parseOp t Opcode.OUT SzDef32 (IbRGv RegGrp.RG0 false), pos - | 0xE8uy -> parseOp (pBNDPref t) Opcode.CALLNear Sz64 Jz, pos - | 0xE9uy -> parseOp (pBNDPref t) Opcode.JMPNear Sz64 Jz, pos - | 0xEAuy -> ensure32 t; parseOp (pBNDPref t) Opcode.JMPFar SzInv64 Ap, pos - | 0xEBuy -> parseOp (pBNDPref t) Opcode.JMPNear Sz64 Jb, pos - | 0xECuy -> parseOp t Opcode.IN SzDef32 ALDX, pos - | 0xEDuy -> parseOp t Opcode.IN SzDef32 RGzDX, pos - | 0xEEuy -> parseOp t Opcode.OUT SzDef32 DXAL, pos - | 0xEFuy -> parseOp t Opcode.OUT SzDef32 DXRGz, pos - | 0xF4uy -> parseOp t Opcode.HLT Sz64 [||], pos - | 0xF5uy -> parseOp t Opcode.CMC Sz64 [||], pos - | 0xF8uy -> parseOp t Opcode.CLC Sz64 [||], pos - | 0xF9uy -> parseOp t Opcode.STC Sz64 [||], pos - | 0xFAuy -> parseOp t Opcode.CLI Sz64 [||], pos - | 0xFBuy -> parseOp t Opcode.STI Sz64 [||], pos - | 0xFCuy -> parseOp t Opcode.CLD Sz64 [||], pos - | 0xFDuy -> parseOp t Opcode.STD Sz64 [||], pos - (* Group Opcodes Vol.2C A-19 Table A-6. - Opcode Extensions for One- and Two-byte Opcodes by Group Number *) - | 0x80uy -> parseGrpOpcode t reader pos OpGroup.G1 EbIb - | 0x81uy -> parseGrpOpcode t reader pos OpGroup.G1 EvSIz - | 0x82uy -> parseGrpOpcode t reader pos OpGroup.G1Inv64 EbIb - | 0x83uy -> parseGrpOpcode t reader pos OpGroup.G1 EvSIb - | 0x8Fuy -> parseGrpOpcode t reader pos OpGroup.G1A Ev - | 0xC0uy -> parseGrpOpcode t reader pos OpGroup.G2 EbIb - | 0xC1uy -> parseGrpOpcode t reader pos OpGroup.G2 EvIb - | 0xD0uy -> parseGrpOpcode t reader pos OpGroup.G2 Eb1L - | 0xD1uy -> parseGrpOpcode t reader pos OpGroup.G2 Ev1L - | 0xD2uy -> parseGrpOpcode t reader pos OpGroup.G2 EbCL - | 0xD3uy -> parseGrpOpcode t reader pos OpGroup.G2 EvCL - | 0xF6uy -> parseGrpOpcode t reader pos OpGroup.G3A Eb - | 0xF7uy -> parseGrpOpcode t reader pos OpGroup.G3B Ev - | 0xFEuy -> parseGrpOpcode t reader pos OpGroup.G4 [||] - | 0xFFuy -> parseGrpOpcode t reader pos OpGroup.G5 [||] - | 0xC6uy -> parseGrpOpcode t reader pos OpGroup.G11A EbIb - | 0xC7uy -> parseGrpOpcode t reader pos OpGroup.G11B EvSIz - | 0x0Fuy -> parseTwoByteOpcode t reader pos - | _ -> raise ParsingFailureException - -(* -let private memoizeOneByte f t = - let cache = System.Collections.Generic.Dictionary<_, _> () - fun (reader: BinReader) -> - let b = reader.ReadByte () - let key = int t.TPrefixes ||| (int t.TREXPrefix <<< 12) - let mutable ok = Unchecked.defaultof<_> - let res = cache.TryGetValue (x, &ok) - if ok then res - else let res = f x - cache.[x] <- res - res -*) - -let private parseRegularOpcode t (reader: BinReader) pos = - reader.PeekByte pos |> pOneByteOpcode t reader (pos + 1) - -let private parseOpcode t (reader: BinReader) pos = - match t.TVEXInfo with - | Some { VEXType = vt } -> - if VEXType.isTwoByteOp vt then parseTwoByteOpcode t reader pos - elif VEXType.isThreeByteOpOne vt then parseThreeByteOp1 t reader pos - elif VEXType.isThreeByteOpTwo vt then parseThreeByteOp2 t reader pos - else raise ParsingFailureException - | None -> parseRegularOpcode t reader pos - -let inline private getOprFromRegGrp rgrp attr insInfo = - findReg insInfo.InsSize.RegSize attr insInfo.REXPrefix rgrp |> OprReg - -let private parseSignedImm (reader: BinReader) pos = function - | 1 -> reader.PeekInt8 pos |> int64, pos + 1 - | 2 -> reader.PeekInt16 pos |> int64, pos + 2 - | 4 -> reader.PeekInt32 pos |> int64, pos + 4 - | 8 -> reader.PeekInt64 pos, pos + 8 - | _ -> raise ParsingFailureException - -let private parseUnsignedImm (reader: BinReader) pos = function - | 1 -> reader.PeekUInt8 pos |> uint64, pos + 1 - | 2 -> reader.PeekUInt16 pos |> uint64, pos + 2 - | 4 -> reader.PeekUInt32 pos |> uint64, pos + 4 - | 8 -> reader.PeekUInt64 pos, pos + 8 - | _ -> raise ParsingFailureException - -let inline private parseOprForDirectJmp insInfo reader pos = - let addrSz = RegType.toByteWidth insInfo.InsSize.MemSize.EffAddrSize - let addrValue, nextPos = parseUnsignedImm reader pos addrSz - let selector = reader.PeekInt16 nextPos - let absAddr = Absolute (selector, addrValue, RegType.fromByteWidth addrSz) - struct (OprDirAddr absAddr, nextPos + 2) - -let inline private getImmSize effOprSz = function - | OprSize.B -> 8 - | OprSize.V -> effOprSz - | OprSize.W -> 16 - | OprSize.Z -> - if effOprSz = 64 || effOprSz = 32 then 32 else effOprSz - | _ -> raise ParsingFailureException - -let inline private parseOprForRelJmp insInfo oldPos reader pos sKnd = - let sz = getImmSize insInfo.InsSize.MemSize.EffOprSize sKnd - let offset, nextPos = parseSignedImm reader pos (RegType.toByteWidth sz) - let relOffset = offset + int64 nextPos - int64 oldPos - struct (OprDirAddr (Relative (relOffset)), nextPos) - -/// EVEX uses compressed displacement. See the manual Chap. 15 of Vol. 1. -let compressDisp vInfo disp = - match vInfo with - | Some { VectorLength = 128; VEXType = vt } when VEXType.isEnhanced vt -> - disp * 16L - | Some { VectorLength = 256; VEXType = vt } when VEXType.isEnhanced vt -> - disp * 32L - | Some { VectorLength = 512; VEXType = vt } when VEXType.isEnhanced vt -> - disp * 64L - | _ -> disp - -let inline private parseOprMem insInfo reader pos baseReg siReg disp = - let memSz = insInfo.InsSize.MemSize.EffOprSize - match disp with - | None -> struct (OprMem (baseReg, siReg, None, memSz), pos) - | Some dispSz -> let vInfo = insInfo.VEXInfo - let disp, nextPos = parseSignedImm reader pos dispSz - let disp = compressDisp vInfo disp - struct (OprMem (baseReg, siReg, Some disp, memSz), nextPos) - -let inline private parseOprImm insInfo reader pos sKnd = - let sz = - getImmSize insInfo.InsSize.MemSize.EffOprSize sKnd |> RegType.toByteWidth - let imm, nextPos = parseUnsignedImm reader pos sz - struct (OprImm (int64 imm), nextPos) - -let inline private parseOprSImm insInfo reader pos sKnd = - let sz = - getImmSize insInfo.InsSize.MemSize.EffOprSize sKnd |> RegType.toByteWidth - let imm, nextPos = parseSignedImm reader pos sz - struct (OprImm imm, nextPos) - -/// The first 24 rows of Table 2-1. of the manual Vol. 2A. -/// The index of this tbl is a number that is a concatenation of (mod) and -/// (r/m) field of the ModR/M byte. Each element is a tuple of base register, -/// scaled index register, and the size of the displacement. -let tbl16bitMem = [| - (* Mod 00b *) - struct (Some R.BX, Some (R.SI, Scale.X1), None) - struct (Some R.BX, Some (R.DI, Scale.X1), None) - struct (Some R.BP, Some (R.SI, Scale.X1), None) - struct (Some R.BP, Some (R.DI, Scale.X1), None) - struct (Some R.SI, None, None) - struct (Some R.DI, None, None) - struct (None, None, Some 2) - struct (Some R.BX, None, None) - (* Mod 01b *) - struct (Some R.BX, Some (R.SI, Scale.X1), Some 1) - struct (Some R.BX, Some (R.DI, Scale.X1), Some 1) - struct (Some R.BP, Some (R.SI, Scale.X1), Some 1) - struct (Some R.BP, Some (R.DI, Scale.X1), Some 1) - struct (Some R.SI, None, Some 1) - struct (Some R.DI, None, Some 1) - struct (Some R.BP, None, Some 1) - struct (Some R.BX, None, Some 1) - (* Mod 10b *) - struct (Some R.BX, Some (R.SI, Scale.X1), Some 2) - struct (Some R.BX, Some (R.DI, Scale.X1), Some 2) - struct (Some R.BP, Some (R.SI, Scale.X1), Some 2) - struct (Some R.BP, Some (R.DI, Scale.X1), Some 2) - struct (Some R.SI, None, Some 2) - struct (Some R.DI, None, Some 2) - struct (Some R.BP, None, Some 2) - struct (Some R.BX, None, Some 2) -|] - -/// The first 24 rows of Table 2-2. of the manual Vol. 2A. -/// The index of this tbl is a number that is a concatenation of (mod) and -/// (r/m) field of the ModR/M byte. Each element is a tuple of (MemLookupType, -/// and the size of the displacement). If the first value of the tuple (register -/// group) is None, it means we need to look up the SIB tbl (Table 2-3). If -/// not, then it represents the reg group of the base reigster. -let tbl32bitMem = [| - (* Mod 00b *) - struct (NOSIB (Some RegGrp.RG0), None) - struct (NOSIB (Some RegGrp.RG1), None) - struct (NOSIB (Some RegGrp.RG2), None) - struct (NOSIB (Some RegGrp.RG3), None) - struct (SIB, None) - struct (NOSIB (None), Some 4) - struct (NOSIB (Some RegGrp.RG6), None) - struct (NOSIB (Some RegGrp.RG7), None) - (* Mod 01b *) - struct (NOSIB (Some RegGrp.RG0), Some 1) - struct (NOSIB (Some RegGrp.RG1), Some 1) - struct (NOSIB (Some RegGrp.RG2), Some 1) - struct (NOSIB (Some RegGrp.RG3), Some 1) - struct (SIB, Some 1) - struct (NOSIB (Some RegGrp.RG5), Some 1) - struct (NOSIB (Some RegGrp.RG6), Some 1) - struct (NOSIB (Some RegGrp.RG7), Some 1) - (* Mod 10b *) - struct (NOSIB (Some RegGrp.RG0), Some 4) - struct (NOSIB (Some RegGrp.RG1), Some 4) - struct (NOSIB (Some RegGrp.RG2), Some 4) - struct (NOSIB (Some RegGrp.RG3), Some 4) - struct (SIB, Some 4) - struct (NOSIB (Some RegGrp.RG5), Some 4) - struct (NOSIB (Some RegGrp.RG6), Some 4) - struct (NOSIB (Some RegGrp.RG7), Some 4) -|] - -/// Table for register groups. This tbl can be referenced by RM field or REG -/// field of the ModR/M byte. -/// Table for scales (of SIB). This tbl is indexbed by the scale value of SIB. -let tblScale = [| Scale.X1; Scale.X2; Scale.X4; Scale.X8 |] - -let private parseMEM16 insInfo reader pos modRM = - let m = getMod modRM - let rm = getRM modRM - let mrm = (m <<< 3) ||| rm (* Concatenation of mod and rm bit *) - match tbl16bitMem.[mrm] with - | struct (b, si, disp) -> parseOprMem insInfo reader pos b si disp - -let inline private hasREXX rexPref = rexPref &&& REXPrefix.REXX = REXPrefix.REXX - -let private getScaledIndex s i insInfo rexPref = - if i = 0b100 && (not <| hasREXX rexPref) then None - else let sz = insInfo.InsSize.MemSize.EffAddrSize - let r = findReg sz RGrpAttr.ASIBIdx rexPref i - Some (r, tblScale.[s]) - -let private getBaseReg b insInfo modValue rexPref = - (* See Notes 1 of Table 2-3 of the manual Vol. 2A *) - if b = int RegGrp.RG5 && modValue = 0b00 then None - else let sz = insInfo.InsSize.MemSize.EffAddrSize - Some (findReg sz RGrpAttr.ASIBBase rexPref b) - -let inline private getSIB b = - struct ((b >>> 6) &&& 0b11, (b >>> 3) &&& 0b111, b &&& 0b111) - -let parseSIB insInfo (reader: BinReader) pos modValue = - let struct (s, i, b) = reader.PeekByte pos |> int |> getSIB - let rexPref = selectREX insInfo.VEXInfo insInfo.REXPrefix - let si = getScaledIndex s i insInfo rexPref - let baseReg = getBaseReg b insInfo modValue rexPref - struct (si, baseReg, b), pos + 1 - -let getSIBDisplacement disp bgrp modValue = - match disp with - | Some dispSz -> dispSz - | None when modValue = 0 && bgrp = int RegGrp.RG5 -> 4 - | None when modValue = 1 && bgrp = int RegGrp.RG5 -> 1 - | None when modValue = 2 && bgrp = int RegGrp.RG5 -> 4 - | _ -> 0 - -let parseOprMemWithSIB insInfo reader pos oprSize modValue disp = - let struct (si, b, bgrp), nextPos = parseSIB insInfo reader pos modValue - match getSIBDisplacement disp bgrp modValue with - | 0 -> struct (OprMem (b, si, None, oprSize), nextPos) - | dispSz -> - let vInfo = insInfo.VEXInfo - let disp, nextPos = parseSignedImm reader nextPos dispSz - let disp = compressDisp vInfo disp - struct (OprMem (b, si, Some disp, oprSize), nextPos) - -/// RIP-relative addressing (see Section 2.2.1.6. of Vol. 2A). -let parseOprRIPRelativeMem insInfo wordSz reader pos disp = - if wordSz = WordSize.Bit64 then - if hasAddrSz insInfo.Prefixes then - parseOprMem insInfo reader pos (Some R.EIP) None disp - else parseOprMem insInfo reader pos (Some R.RIP) None disp - else parseOprMem insInfo reader pos None None disp - -let inline private getBaseRMReg insInfo regGrp = - let rexPref = selectREX insInfo.VEXInfo insInfo.REXPrefix - let regSz = insInfo.InsSize.MemSize.EffAddrSize - findReg regSz RGrpAttr.ABaseRM rexPref (int regGrp) |> Some - -let inline private parseMEM32 insInfo wordSz reader pos oprSize modRM = - let m = getMod modRM - let rm = getRM modRM - let mrm = (m <<< 3) ||| rm (* Concatenation of mod and rm bit *) - match tbl32bitMem.[mrm] with - | struct (NOSIB (None), disp) -> - parseOprRIPRelativeMem insInfo wordSz reader pos disp - | struct (NOSIB (Some b), disp) -> - parseOprMem insInfo reader pos (getBaseRMReg insInfo b) None disp - | struct (SIB, disp) -> parseOprMemWithSIB insInfo reader pos oprSize m disp - -let inline private parseMemory modRM insInfo wordSz reader pos = - let addrSize = insInfo.InsSize.MemSize.EffAddrSize - if addrSize = 16 then parseMEM16 insInfo reader pos modRM - else parseMEM32 insInfo wordSz reader pos insInfo.InsSize.MemSize.EffOprSize - modRM - -let inline private parseReg rgrp sz attr insInfo pos = - let rexPref = selectREX insInfo.VEXInfo insInfo.REXPrefix - struct (findReg sz attr rexPref rgrp |> OprReg, pos) - -let inline private parseMemOrReg modRM insInfo wordSz reader pos = - if getMod modRM = 0b11 then - let regSize = insInfo.InsSize.MemSize.EffRegSize - parseReg (getRM modRM) regSize RGrpAttr.AMod11 insInfo pos - else parseMemory modRM insInfo wordSz reader pos - -let inline private parseXMMReg insInfo = - match insInfo.VEXInfo with - | None -> raise ParsingFailureException - | Some vInfo when vInfo.VectorLength = 256 -> - Register.make (int vInfo.VVVV) Register.Kind.YMM |> OprReg - | Some vInfo -> - Register.make (int vInfo.VVVV) Register.Kind.XMM |> OprReg - -let inline private parseVEXtoGPR insInfo = - match insInfo.VEXInfo with - | None -> raise ParsingFailureException - | Some vInfo -> - let grp = ~~~(int vInfo.VVVV) &&& 0b111 - pickReg insInfo.InsSize.RegSize tblGrpNOREX.[grp] |> OprReg - -let inline private parseMMXReg n = - Register.make n Register.Kind.MMX |> OprReg - -let inline private parseSegReg n = - Register.make n Register.Kind.Segment |> OprReg - -let inline private parseBoundRegister n = - Register.make n Register.Kind.Bound |> OprReg - -let inline private parseControlReg n = - Register.make n Register.Kind.Control |> OprReg - -let inline private parseDebugReg n = - Register.make n Register.Kind.Debug |> OprReg - -let parseWithModRM insInfo wordSz reader pos modRM mode = - match mode with - | OprMode.M | OprMode.MZ when modIsMemory modRM -> - parseMemory modRM insInfo wordSz reader pos - | OprMode.R | OprMode.U -> - parseReg (getRM modRM) - insInfo.InsSize.MemSize.EffRegSize RGrpAttr.AMod11 insInfo pos - | OprMode.E | OprMode.W | OprMode.WZ -> - parseMemOrReg modRM insInfo wordSz reader pos - | OprMode.E0 when getReg modRM = 0 -> - parseMemOrReg modRM insInfo wordSz reader pos - | OprMode.G | OprMode.V | OprMode.VZ -> - parseReg (getReg modRM) insInfo.InsSize.RegSize RGrpAttr.ARegBits insInfo - pos - | OprMode.B -> struct (parseVEXtoGPR insInfo, pos) - | OprMode.C when insInfo.Opcode = Opcode.MOV && hasREXR insInfo.REXPrefix -> - struct (parseControlReg 0x808, pos) (* CR8 *) - | OprMode.C -> struct (parseControlReg (getReg modRM), pos) - | OprMode.D -> struct (parseDebugReg (getReg modRM), pos) - | OprMode.H -> struct (parseXMMReg insInfo, pos) - | OprMode.P -> struct (parseMMXReg (getReg modRM), pos) - | OprMode.S when (getReg modRM) < 6 -> (* 6 means number of Seg registers *) - struct (parseSegReg (getReg modRM), pos) - | OprMode.N -> struct (parseMMXReg (getRM modRM), pos) - | OprMode.Q when modIsMemory modRM -> - parseMemory modRM insInfo wordSz reader pos - | OprMode.Q -> struct (parseMMXReg (getRM modRM), pos) - | OprMode.BndR -> struct (parseBoundRegister (getReg modRM), pos) - | OprMode.BndM when modIsMemory modRM -> - parseMemory modRM insInfo wordSz reader pos - | OprMode.BndM -> struct (parseBoundRegister (getRM modRM), pos) - | _ -> raise ParsingFailureException - -let parseOprOnlyDisp insInfo reader pos = - let dispSz = RegType.toByteWidth insInfo.InsSize.MemSize.EffAddrSize - parseOprMem insInfo reader pos None None (Some dispSz) - -let parseOperand insInfo wordSz modRM oldPos reader pos oprDesc = - match oprDesc with - | ODRegGrp (rGrp, _, attr) -> - struct (getOprFromRegGrp (int rGrp) attr insInfo, pos) - | ODReg r -> struct (OprReg r, pos) - | ODImmOne -> struct (OprImm 1L, pos) - | ODModeSize (struct (OprMode.A, _)) -> - parseOprForDirectJmp insInfo reader pos - | ODModeSize (struct (OprMode.J, sKnd)) -> - parseOprForRelJmp insInfo oldPos reader pos sKnd - | ODModeSize (struct (OprMode.O, _)) -> - parseOprOnlyDisp insInfo reader pos - | ODModeSize (struct (OprMode.I, sKnd)) -> - parseOprImm insInfo reader pos sKnd - | ODModeSize (struct (OprMode.SI, sKnd)) -> - parseOprSImm insInfo reader pos sKnd - | ODModeSize (struct (m, _)) -> - parseWithModRM insInfo wordSz reader pos (Option.get modRM) m - -let parseOperands insInfo descs wordSz modRM oldPos reader pos = - let inline getOprAndNextPos pos desc = - parseOperand insInfo wordSz modRM oldPos reader pos desc - match descs with - | [||] -> struct (NoOperand, pos) - | [| o |] -> - let struct (opr, nextPos) = getOprAndNextPos pos o - struct (OneOperand opr, nextPos) - | [| o1; o2 |] -> - let struct (opr1, nextPos) = getOprAndNextPos pos o1 - let struct (opr2, nextPos) = getOprAndNextPos nextPos o2 - struct (TwoOperands (opr1, opr2), nextPos) - | [| o1; o2; o3 |] -> - let struct (opr1, nextPos) = getOprAndNextPos pos o1 - let struct (opr2, nextPos) = getOprAndNextPos nextPos o2 - let struct (opr3, nextPos) = getOprAndNextPos nextPos o3 - struct (ThreeOperands (opr1, opr2, opr3), nextPos) - | [| o1; o2; o3; o4 |] -> - let struct (opr1, nextPos) = getOprAndNextPos pos o1 - let struct (opr2, nextPos) = getOprAndNextPos nextPos o2 - let struct (opr3, nextPos) = getOprAndNextPos nextPos o3 - let struct (opr4, nextPos) = getOprAndNextPos nextPos o4 - struct (FourOperands (opr1, opr2, opr3, opr4), nextPos) - | _ -> raise ParsingFailureException - -let inline private newInsInfo addr (parsingInfo: InsInfo) instrLen wordSize = - IntelInstruction (addr, instrLen, parsingInfo, wordSize) - -let private hasModRM = function - | ODModeSize (struct (OprMode.A, _)) | ODModeSize (struct (OprMode.I,_ )) - | ODModeSize (struct (OprMode.SI, _)) | ODModeSize (struct (OprMode.J, _)) - | ODModeSize (struct (OprMode.O, _)) -> false - | ODModeSize _ -> true - | _ -> false - -let parseModRM oprDescs (reader: BinReader) pos = - if (Array.isEmpty oprDescs |> not) && (hasModRM oprDescs.[0]) then - struct (reader.PeekByte pos |> Some, pos + 1) - else struct (None, pos) - -let parse (reader: BinReader) wordSz addr pos = - let struct (prefs, nextPos) = parsePrefix reader pos - let struct (rexPref, nextPos) = parseREX wordSz reader nextPos - let struct (vInfo, nextPos) = parseVEXInfo wordSz reader nextPos - let t = newTemporaryInfo prefs rexPref vInfo wordSz - let ins, nextPos = parseOpcode t reader nextPos - match ins with - | None - | Some (struct ({ Opcode = Opcode.InvalOP }, _) ) -> - raise ParsingFailureException - | Some (struct (insInfo, _)) when insInfo.Operands <> NoOperand -> - let len = nextPos - pos |> uint32 - newInsInfo addr insInfo len wordSz - | Some (struct (insInfo, oprDescs)) -> - let struct (modRM, nextPos) = parseModRM oprDescs reader nextPos - let struct (oprs, nextPos) = - parseOperands insInfo oprDescs wordSz modRM pos reader nextPos - let len = nextPos - pos |> uint32 - newInsInfo addr { insInfo with Operands = oprs } len wordSz - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/Intel/IntelParser.fsi b/src/FrontEnd/Intel/IntelParser.fsi deleted file mode 100644 index affc22a1..00000000 --- a/src/FrontEnd/Intel/IntelParser.fsi +++ /dev/null @@ -1,34 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -/// Intel instruction parser. -module B2R2.FrontEnd.Intel.Parser - -open B2R2 - -/// Read in bytes and return a parsed instruction for Intel. This function -/// returns IntelInstruction, which is a specialized type for x86 or x86-64. If -/// you want to handle instructions in a platform-agnostic manner, you'd better -/// use the Intel class. -val parse: BinReader -> WordSize -> Addr -> int -> IntelInstruction diff --git a/src/FrontEnd/Intel/IntelRegisterBay.fs b/src/FrontEnd/Intel/IntelRegisterBay.fs deleted file mode 100644 index 840f4fcd..00000000 --- a/src/FrontEnd/Intel/IntelRegisterBay.fs +++ /dev/null @@ -1,268 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.Intel - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinIR.LowUIR - -type IntelRegisterBay (wordSize) = - - inherit RegisterBay () - - let R = RegExprs (wordSize) - - override __.GetAllRegExprs () = - if WordSize.is32 wordSize then - [ R.EAX; R.EBX; R.ECX; R.EDX; R.ESP; R.EBP; R.ESI; R.EDI; R.EIP; R.CS; - R.DS; R.ES; R.FS; R.GS; R.SS; R.CSBase; R.DSBase; R.ESBase; R.FSBase; - R.GSBase; R.SSBase; R.CR0; R.CR2; R.CR3; R.CR4; R.OF; R.DF; R.IF; R.TF; - R.SF; R.ZF; R.AF; R.PF; R.CF; R.FCW; R.FSW; R.FTW; R.FOP; R.FIP; R.FCS; - R.FDP; R.FDS; R.MXCSR; R.MXCSRMASK; R.PKRU; R.K0; R.K1; R.K2; R.K3; - R.K4; R.K5; R.K6; R.K7; R.ST0A; R.ST0B; R.ST1A; R.ST1B; R.ST2A; R.ST2B; - R.ST3A; R.ST3B; R.ST4A; R.ST4B; R.ST5A; R.ST5B; R.ST6A; R.ST6B; R.ST7A; - R.ST7B; R.ZMM0A; R.ZMM0B; R.ZMM1A; R.ZMM1B; R.ZMM2A; R.ZMM2B; R.ZMM3A; - R.ZMM3B; R.ZMM4A; R.ZMM4B; R.ZMM5A; R.ZMM5B; R.ZMM6A; R.ZMM6B; R.ZMM7A; - R.ZMM7B; R.ZMM8A; R.ZMM8B ] - else - [ R.RAX; R.RBX; R.RCX; R.RDX; R.RSP; R.RBP; R.RSI; R.RDI; R.R8; R.R9; - R.R10; R.R11; R.R12; R.R13; R.R14; R.R15; R.RIP; R.CS; R.DS; R.ES; R.FS; - R.GS; R.SS; R.CSBase; R.DSBase; R.ESBase; R.FSBase; R.GSBase; R.SSBase; - R.CR0;R.CR2; R.CR3; R.CR4; R.CR8; R.OF; R.DF; R.IF; R.TF; R.SF; R.ZF; - R.AF; R.PF; R.CF; R.FCW; R.FSW; R.FTW; R.FOP; R.FIP; R.FCS; R.FDP; - R.FDS; R.MXCSR; R.MXCSRMASK; R.PKRU; R.K0; R.K1; R.K2; R.K3; R.K4; R.K5; - R.K6; R.K7; R.ST0A; R.ST0B; R.ST1A; R.ST1B; R.ST2A; R.ST2B; R.ST3A; - R.ST3B; R.ST4A; R.ST4B; R.ST5A; R.ST5B; R.ST6A; R.ST6B; R.ST7A; R.ST7B; - R.ZMM0A; R.ZMM0B; R.ZMM1A; R.ZMM1B; R.ZMM2A; R.ZMM2B; R.ZMM3A; R.ZMM3B; - R.ZMM4A; R.ZMM4B; R.ZMM5A; R.ZMM5B; R.ZMM6A; R.ZMM6B; R.ZMM7A; R.ZMM7B; - R.ZMM8A; R.ZMM8B ] - - override __.GetAllRegNames () = - __.GetAllRegExprs () - |> List.map (__.RegIDFromRegExpr >> __.RegIDToString) - - override __.GetGeneralRegExprs () = - if WordSize.is32 wordSize then - [ R.EAX; R.EBX; R.ECX; R.EDX; R.ESP; R.EBP; R.ESI; R.EDI; R.EIP - R.OF; R.DF; R.IF; R.SF; R.ZF; R.AF; R.PF; R.CF ] - else - [ R.RAX; R.RBX; R.RCX; R.RDX; R.RSP; R.RBP; R.RSI; R.RDI; R.R8; R.R9 - R.R10; R.R11; R.R12; R.R13; R.R14; R.R15; R.RIP - R.OF; R.DF; R.IF; R.SF; R.ZF; R.AF; R.PF; R.CF ] - - override __.RegIDFromRegExpr (e) = - match e with - | Var (_,id, _,_) -> id - | PCVar (regT, _) -> - if regT = 32 then Register.toRegID Register.EIP - else Register.toRegID Register.RIP - | _ -> failwith "not a register expression" - - override __.StrToRegExpr s = - match s with - | "RAX" -> R.RAX - | "RBX" -> R.RBX - | "RCX" -> R.RCX - | "RDX" -> R.RDX - | "RSP" -> R.RSP - | "RBP" -> R.RBP - | "RSI" -> R.RSI - | "RDI" -> R.RDI - | "EAX" -> R.EAX - | "EBX" -> R.EBX - | "ECX" -> R.ECX - | "EDX" -> R.EDX - | "ESP" -> R.ESP - | "EBP" -> R.EBP - | "ESI" -> R.ESI - | "EDI" -> R.EDI - | "AX" -> R.AX - | "BX" -> R.BX - | "CX" -> R.CX - | "DX" -> R.DX - | "SP" -> R.SP - | "BP" -> R.BP - | "SI" -> R.SI - | "DI" -> R.DI - | "AL" -> R.AL - | "BL" -> R.BL - | "CL" -> R.CL - | "DL" -> R.DL - | "AH" -> R.AH - | "BH" -> R.BH - | "CH" -> R.CH - | "DH" -> R.DH - | "R8" -> R.R8 - | "R9" -> R.R9 - | "R10" -> R.R10 - | "R11" -> R.R11 - | "R12" -> R.R12 - | "R13" -> R.R13 - | "R14" -> R.R14 - | "R15" -> R.R15 - | "R8D" -> R.R8D - | "R9D" -> R.R9D - | "R10D" -> R.R10D - | "R11D" -> R.R11D - | "R12D" -> R.R12D - | "R13D" -> R.R13D - | "R14D" -> R.R14D - | "R15D" -> R.R15D - | "R8W" -> R.R8W - | "R9W" -> R.R9W - | "R10W" -> R.R10W - | "R11W" -> R.R11W - | "R12W" -> R.R12W - | "R13W" -> R.R13W - | "R14W" -> R.R14W - | "R15W" -> R.R15W - | "R8L" -> R.R8L - | "R9L" -> R.R9L - | "R10L" -> R.R10L - | "R11L" -> R.R11L - | "R12L" -> R.R12L - | "R13L" -> R.R13L - | "R14L" -> R.R14L - | "R15L" -> R.R15L - | "SPL" -> R.SPL - | "BPL" -> R.BPL - | "SIL" -> R.SIL - | "DIL" -> R.DIL - | "EIP" -> R.EIP - | "RIP" -> R.RIP - | "MM0" -> R.MM0 - | "MM1" -> R.MM1 - | "MM2" -> R.MM2 - | "MM3" -> R.MM3 - | "MM4" -> R.MM4 - | "MM5" -> R.MM5 - | "MM6" -> R.MM6 - | "MM7" -> R.MM7 - | "CS" -> R.CS - | "DS" -> R.DS - | "SS" -> R.SS - | "ES" -> R.ES - | "FS" -> R.FS - | "GS" -> R.GS - | "CSBase" -> R.CSBase - | "DSBase" -> R.DSBase - | "ESBase" -> R.ESBase - | "FSBase" -> R.FSBase - | "GSBase" -> R.GSBase - | "SSBase" -> R.SSBase - | "CR0" -> R.CR0 - | "CR2" -> R.CR2 - | "CR3" -> R.CR3 - | "CR4" -> R.CR4 - | "CR8" -> R.CR8 - | "OF" -> R.OF - | "DF" -> R.DF - | "IF" -> R.IF - | "TF" -> R.TF - | "SF" -> R.SF - | "ZF" -> R.ZF - | "AF" -> R.AF - | "PF" -> R.PF - | "CF" -> R.CF - | "K0" -> R.K0 - | "K1" -> R.K1 - | "K2" -> R.K2 - | "K3" -> R.K3 - | "K4" -> R.K4 - | "K5" -> R.K5 - | "K6" -> R.K6 - | "K7" -> R.K7 - | "ST0A" -> R.ST0A - | "ST0B" -> R.ST0B - | "ST1A" -> R.ST1A - | "ST1B" -> R.ST1B - | "ST2A" -> R.ST2A - | "ST2B" -> R.ST2B - | "ST3A" -> R.ST3A - | "ST3B" -> R.ST3B - | "ST4A" -> R.ST4A - | "ST4B" -> R.ST4B - | "ST5A" -> R.ST5A - | "ST5B" -> R.ST5B - | "ST6A" -> R.ST6A - | "ST6B" -> R.ST6B - | "ST7A" -> R.ST7A - | "ST7B" -> R.ST7B - | "ZMM0A" -> R.ZMM0A - | "ZMM0B" -> R.ZMM0B - | "ZMM1A" -> R.ZMM1A - | "ZMM1B" -> R.ZMM1B - | "ZMM2A" -> R.ZMM2A - | "ZMM2B" -> R.ZMM2B - | "ZMM3A" -> R.ZMM3A - | "ZMM3B" -> R.ZMM3B - | "ZMM4A" -> R.ZMM4A - | "ZMM4B" -> R.ZMM4B - | "ZMM5A" -> R.ZMM5A - | "ZMM5B" -> R.ZMM5B - | "ZMM6A" -> R.ZMM6A - | "ZMM6B" -> R.ZMM6B - | "ZMM7A" -> R.ZMM7A - | "ZMM7B" -> R.ZMM7B - | "ZMM8A" -> R.ZMM8A - | "ZMM8B" -> R.ZMM8B - | _ -> raise UnhandledRegExprException - - override __.RegIDFromString str = - Register.ofString str |> Register.toRegID - - override __.RegIDToString rid = - Register.ofRegID rid |> Register.toString - - override __.RegIDToRegType rid = - Register.ofRegID rid |> Register.toRegType - - override __.GetRegisterAliases rid = - Register.ofRegID rid - |> Register.getAliases - |> Array.map Register.toRegID - - override __.ProgramCounter = - if WordSize.is32 wordSize then Register.EIP |> Register.toRegID - else Register.RIP |> Register.toRegID - - override __.StackPointer = - if WordSize.is32 wordSize then Register.ESP |> Register.toRegID - else Register.RSP |> Register.toRegID - |> Some - - override __.FramePointer = - if WordSize.is32 wordSize then Register.EBP |> Register.toRegID - else Register.RBP |> Register.toRegID - |> Some - - override __.IsProgramCounter regid = - __.ProgramCounter = regid - - override __.IsStackPointer regid = - (__.StackPointer |> Option.get) = regid - - override __.IsFramePointer regid = - (__.FramePointer |> Option.get) = regid diff --git a/src/FrontEnd/Intel/IntelRegisterSet.fs b/src/FrontEnd/Intel/IntelRegisterSet.fs deleted file mode 100644 index 4a8e9afb..00000000 --- a/src/FrontEnd/Intel/IntelRegisterSet.fs +++ /dev/null @@ -1,249 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.Intel - -open B2R2 - -type IntelRegisterSet (bitArray: uint64 [], s: Set) = - inherit NonEmptyRegisterSet (bitArray, s) - - static let defaultSize = 4 - static let emptyArr = Array.init defaultSize (fun _ -> 0UL) - static member EmptySet = - new IntelRegisterSet (emptyArr, Set.empty) :> RegisterSet - - override __.Tag = RegisterSetTag.Intel - override __.ArrSize = defaultSize - override __.New x s = new IntelRegisterSet (x, s) :> RegisterSet - override __.Empty = IntelRegisterSet.EmptySet - override __.EmptyArr = emptyArr - override __.Project x = - match Register.ofRegID x with - | R.RAX | R.EAX -> 0 - | R.RBX | R.EBX -> 1 - | R.RCX | R.ECX -> 2 - | R.RDX | R.EDX -> 3 - | R.RSP | R.ESP -> 4 - | R.RBP | R.EBP -> 5 - | R.RSI | R.ESI -> 6 - | R.RDI | R.EDI -> 7 - | R.R8 -> 8 - | R.R9 -> 9 - | R.R10 -> 10 - | R.R11 -> 11 - | R.R12 -> 12 - | R.R13 -> 13 - | R.R14 -> 14 - | R.R15 -> 15 - | R.SPL -> 16 - | R.BPL -> 17 - | R.SIL -> 18 - | R.DIL -> 19 - | R.ES -> 20 - | R.CS -> 21 - | R.SS -> 22 - | R.DS -> 23 - | R.FS -> 24 - | R.GS -> 25 - | R.ESBase -> 26 - | R.CSBase -> 27 - | R.SSBase -> 28 - | R.DSBase -> 29 - | R.FSBase -> 30 - | R.GSBase -> 31 - | R.OF -> 32 - | R.DF -> 33 - | R.IF -> 34 - | R.TF -> 35 - | R.SF -> 36 - | R.ZF -> 37 - | R.AF -> 38 - | R.PF -> 39 - | R.CF -> 40 - | R.MM0 -> 41 - | R.MM1 -> 42 - | R.MM2 -> 43 - | R.MM3 -> 44 - | R.MM4 -> 45 - | R.MM5 -> 45 - | R.MM6 -> 47 - | R.MM7 -> 48 - | R.ZMM0A -> 49 - | R.ZMM0B -> 50 - | R.ZMM0C -> 51 - | R.ZMM0D -> 52 - | R.ZMM0E -> 53 - | R.ZMM0F -> 54 - | R.ZMM0G -> 55 - | R.ZMM0H -> 56 - | R.ZMM1A -> 57 - | R.ZMM1B -> 58 - | R.ZMM1C -> 59 - | R.ZMM1D -> 60 - | R.ZMM1E -> 61 - | R.ZMM1F -> 62 - | R.ZMM1G -> 63 - | R.ZMM1H -> 64 - | R.ZMM2A -> 65 - | R.ZMM2B -> 66 - | R.ZMM2C -> 67 - | R.ZMM2D -> 68 - | R.ZMM2E -> 69 - | R.ZMM2F -> 70 - | R.ZMM2G -> 71 - | R.ZMM2H -> 72 - | R.ZMM3A -> 73 - | R.ZMM3B -> 74 - | R.ZMM3C -> 75 - | R.ZMM3D -> 76 - | R.ZMM3E -> 77 - | R.ZMM3F -> 78 - | R.ZMM3G -> 79 - | R.ZMM3H -> 80 - | R.ZMM4A -> 81 - | R.ZMM4B -> 82 - | R.ZMM4C -> 83 - | R.ZMM4D -> 84 - | R.ZMM4E -> 85 - | R.ZMM4F -> 86 - | R.ZMM4G -> 87 - | R.ZMM4H -> 88 - | R.ZMM5A -> 89 - | R.ZMM5B -> 90 - | R.ZMM5C -> 91 - | R.ZMM5D -> 92 - | R.ZMM5E -> 93 - | R.ZMM5F -> 94 - | R.ZMM5G -> 95 - | R.ZMM5H -> 96 - | R.ZMM6A -> 97 - | R.ZMM6B -> 98 - | R.ZMM6C -> 99 - | R.ZMM6D -> 100 - | R.ZMM6E -> 101 - | R.ZMM6F -> 102 - | R.ZMM6G -> 103 - | R.ZMM6H -> 104 - | R.ZMM7A -> 105 - | R.ZMM7B -> 106 - | R.ZMM7C -> 107 - | R.ZMM7D -> 108 - | R.ZMM7E -> 109 - | R.ZMM7F -> 110 - | R.ZMM7G -> 111 - | R.ZMM7H -> 112 - | R.ZMM8A -> 113 - | R.ZMM8B -> 114 - | R.ZMM8C -> 115 - | R.ZMM8D -> 116 - | R.ZMM8E -> 117 - | R.ZMM8F -> 118 - | R.ZMM8G -> 119 - | R.ZMM8H -> 120 - | R.ZMM9A -> 121 - | R.ZMM9B -> 122 - | R.ZMM9C -> 123 - | R.ZMM9D -> 124 - | R.ZMM9E -> 125 - | R.ZMM9F -> 126 - | R.ZMM9G -> 127 - | R.ZMM9H -> 128 - | R.ZMM10A -> 129 - | R.ZMM10B -> 130 - | R.ZMM10C -> 131 - | R.ZMM10D -> 132 - | R.ZMM10E -> 133 - | R.ZMM10F -> 134 - | R.ZMM10G -> 135 - | R.ZMM10H -> 136 - | R.ZMM11A -> 137 - | R.ZMM11B -> 138 - | R.ZMM11C -> 139 - | R.ZMM11D -> 140 - | R.ZMM11E -> 141 - | R.ZMM11F -> 142 - | R.ZMM11G -> 143 - | R.ZMM11H -> 144 - | R.ZMM12A -> 145 - | R.ZMM12B -> 146 - | R.ZMM12C -> 147 - | R.ZMM12D -> 148 - | R.ZMM12E -> 149 - | R.ZMM12F -> 150 - | R.ZMM12G -> 151 - | R.ZMM12H -> 152 - | R.ZMM13A -> 153 - | R.ZMM13B -> 154 - | R.ZMM13C -> 155 - | R.ZMM13D -> 156 - | R.ZMM13E -> 157 - | R.ZMM13F -> 158 - | R.ZMM13G -> 159 - | R.ZMM13H -> 160 - | R.ZMM14A -> 161 - | R.ZMM14B -> 162 - | R.ZMM14C -> 163 - | R.ZMM14D -> 164 - | R.ZMM14E -> 165 - | R.ZMM14F -> 166 - | R.ZMM14G -> 167 - | R.ZMM14H -> 168 - | R.ZMM15A -> 169 - | R.ZMM15B -> 170 - | R.ZMM15C -> 171 - | R.ZMM15D -> 172 - | R.ZMM15E -> 173 - | R.ZMM15F -> 174 - | R.ZMM15G -> 175 - | R.ZMM15H -> 176 - | R.BND0A -> 177 - | R.BND0B -> 178 - | R.BND1A -> 179 - | R.BND1B -> 180 - | R.BND2A -> 181 - | R.BND2B -> 182 - | R.BND3A -> 183 - | R.BND3B -> 184 - | R.FCW -> 185 - | R.FSW -> 186 - | R.FTW -> 187 - | R.FOP -> 188 - | R.FIP -> 189 - | R.FCS -> 190 - | R.FDP -> 191 - | R.FDS -> 192 - | R.MXCSR -> 193 - | R.MXCSRMASK -> 194 - | R.PKRU -> 195 - | _ -> -1 - - override __.ToString () = - sprintf "IntelRegisterSet<%x, %x, %x, %x>" __.BitArray.[0] __.BitArray.[1] - __.BitArray.[2] __.BitArray.[3] - -[] -module IntelRegisterSet = - let singleton = RegisterSetBuilder.singletonBuilder IntelRegisterSet.EmptySet - let empty = IntelRegisterSet.EmptySet diff --git a/src/FrontEnd/Library/B2R2.FrontEnd.Library.fsproj b/src/FrontEnd/Library/B2R2.FrontEnd.Library.fsproj deleted file mode 100644 index a872f2e7..00000000 --- a/src/FrontEnd/Library/B2R2.FrontEnd.Library.fsproj +++ /dev/null @@ -1,95 +0,0 @@ - - - - netstandard2.1 - true - false - B2R2.FrontEnd - LICENSE.md - b2r2-240x240.png - https://github.com/B2R2-org/B2R2 - git - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage - - - - - - - %(ProjectReference.Identity) - $([System.IO.Path]::GetFileNameWithoutExtension($(CurrentReference))) - - - - - - - - - - - - - - - - %(ProjectReference.Identity) - $([System.IO.Path]::GetFileNameWithoutExtension($(CurrentReference))) - - - - - - - - - - - lib/$(TargetFramework) - - - - - - - diff --git a/src/FrontEnd/Library/BinHandler.fs b/src/FrontEnd/Library/BinHandler.fs deleted file mode 100644 index 604d2cf6..00000000 --- a/src/FrontEnd/Library/BinHandler.fs +++ /dev/null @@ -1,220 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd - -open System -open B2R2 -open B2R2.BinFile -open B2R2.FrontEnd -open B2R2.FrontEnd.BinHandlerHelper - -type BinHandler = { - ISA: ISA - FileInfo: FileInfo - DefaultParsingContext: ParsingContext - TranslationContext: TranslationContext - Parser: Parser - RegisterBay: RegisterBay -} -with - static member private Init (isa, mode, autoDetect, baseAddr, bytes, path) = - let path = try IO.Path.GetFullPath path with _ -> "" - let fi = newFileInfo bytes baseAddr path isa autoDetect - let isa = fi.ISA - let needCheckThumb = mode = ArchOperationMode.NoMode && isARM isa - let mode = if needCheckThumb then detectThumb fi.EntryPoint isa else mode - let ctxt, parser, regbay = initHelpers isa - { ISA = isa - FileInfo = fi - DefaultParsingContext = ParsingContext.Init (mode) - TranslationContext = ctxt - Parser = parser - RegisterBay = regbay } - - static member Init (isa, archMode, autoDetect, baseAddr, bytes) = - BinHandler.Init (isa, archMode, autoDetect, baseAddr, bytes, "") - - static member Init (isa, archMode, autoDetect, baseAddr, fileName) = - let bytes = IO.File.ReadAllBytes fileName - BinHandler.Init (isa, archMode, autoDetect, baseAddr, bytes, fileName) - - static member Init (isa, baseAddr, fileName) = - let bytes = IO.File.ReadAllBytes fileName - let defaultMode = ArchOperationMode.NoMode - BinHandler.Init (isa, defaultMode, true, baseAddr, bytes, fileName) - - static member Init (isa, fileName) = - BinHandler.Init (isa=isa, baseAddr=0UL, fileName=fileName) - - static member Init (isa, baseAddr, bytes) = - let defaultMode = ArchOperationMode.NoMode - BinHandler.Init (isa, defaultMode, false, baseAddr, bytes, "") - - static member Init (isa, bytes) = - BinHandler.Init (isa=isa, baseAddr=0UL, bytes=bytes) - - static member Init (isa, archMode) = - BinHandler.Init (isa, archMode, false, 0UL, [||], "") - - static member Init (isa) = BinHandler.Init (isa, [||]) - - static member UpdateCode h addr bs = - { h with FileInfo = new RawFileInfo (bs, h.ISA, addr) :> FileInfo } - - member __.ReadBytes (addr, nBytes) = - BinHandler.ReadBytes (__, addr, nBytes) - - static member TryReadBytes ({ FileInfo = fi }, addr, nBytes) = - let range = AddrRange (addr, addr + uint64 nBytes) - if fi.IsInFileRange range then - fi.BinReader.PeekBytes (nBytes, fi.TranslateAddress addr) |> Some - elif fi.IsValidRange range then - fi.GetNotInFileIntervals range - |> classifyRanges range - |> List.fold (fun bs (range, isInFile) -> - let len = range.Max - range.Min |> int - if isInFile then - let addr = fi.TranslateAddress range.Min - fi.BinReader.PeekBytes (len, addr) - |> Array.append bs - else Array.create len 0uy |> Array.append bs - ) [||] - |> Some - else None - - static member ReadBytes (hdl, addr, nBytes) = - match BinHandler.TryReadBytes (hdl, addr, nBytes) with - | Some bs -> bs - | None -> invalidArg "ReadBytes" "Invalid size given." - - member __.ReadInt (addr, nBytes) = - BinHandler.ReadInt (__, addr, nBytes) - - static member TryReadInt ({ FileInfo = fi }, addr, nBytes) = - let pos = fi.TranslateAddress addr - if pos >= fi.BinReader.Bytes.Length || pos < 0 then None - else - match nBytes with - | 1 -> fi.BinReader.PeekInt8 pos |> int64 |> Some - | 2 -> fi.BinReader.PeekInt16 pos |> int64 |> Some - | 4 -> fi.BinReader.PeekInt32 pos |> int64 |> Some - | 8 -> fi.BinReader.PeekInt64 pos |> Some - | _ -> None - - static member ReadInt (hdl, addr, nBytes) = - match BinHandler.TryReadInt (hdl, addr, nBytes) with - | Some i -> i - | None -> invalidArg "ReadInt" "Invalid size given." - - member __.ReadUInt (addr, nBytes) = - BinHandler.ReadUInt (__, addr, nBytes) - - static member TryReadUInt ({ FileInfo = fi }, addr, nBytes) = - let pos = fi.TranslateAddress addr - match nBytes with - | 1 -> fi.BinReader.PeekUInt8 pos |> uint64 |> Some - | 2 -> fi.BinReader.PeekUInt16 pos |> uint64 |> Some - | 4 -> fi.BinReader.PeekUInt32 pos |> uint64 |> Some - | 8 -> fi.BinReader.PeekUInt64 pos |> Some - | _ -> None - - static member ReadUInt (hdl, addr, nBytes) = - match BinHandler.TryReadUInt (hdl, addr, nBytes) with - | Some i -> i - | None -> invalidArg "ReadUInt" "Invalid size given." - - member __.ReadASCII (addr) = - BinHandler.ReadASCII (__, addr) - - static member ReadASCII ({ FileInfo = fi }, addr) = - let rec loop acc pos = - let b = fi.BinReader.PeekByte pos - if b = 0uy then List.rev (b :: acc) |> List.toArray - else loop (b :: acc) (pos + 1) - let bs = fi.TranslateAddress addr |> loop [] - ByteArray.extractCString bs 0 - - static member ParseInstr (hdl: BinHandler) ctxt addr = - hdl.FileInfo.TranslateAddress addr - |> hdl.Parser.Parse hdl.FileInfo.BinReader ctxt addr - - static member TryParseInstr hdl ctxt addr = - try BinHandler.ParseInstr hdl ctxt addr |> Some - with _ -> None - - static member ParseBBlock handle ctxt addr = - let rec parseLoop ctxt acc pc = - match BinHandler.TryParseInstr handle ctxt pc with - | Some ins -> - let ctxt = ins.NextParsingContext - if ins.IsExit () then Ok (List.rev (ins :: acc), ctxt) - else parseLoop ctxt (ins :: acc) (pc + uint64 ins.Length) - | None -> Error <| List.rev acc - parseLoop ctxt [] addr - - static member inline LiftInstr (handle: BinHandler) (ins: Instruction) = - ins.Translate handle.TranslationContext - - static member LiftBBlock (hdl: BinHandler) ctxt addr = - match BinHandler.ParseBBlock hdl ctxt addr with - | Ok (bbl, ctxt) -> - let struct (stmts, addr) = lift hdl.TranslationContext addr bbl - Ok (stmts, addr, ctxt) - | Error bbl -> - let struct (stmts, addr) = lift hdl.TranslationContext addr bbl - Error (stmts, addr) - - static member LiftIRBBlock (hdl: BinHandler) ctxt addr = - let rec liftLoop ctxt acc pc = - match BinHandler.TryParseInstr hdl ctxt pc with - | Some ins -> - let stmts = ins.Translate hdl.TranslationContext - let acc = (ins, stmts) :: acc - let pc = pc + uint64 ins.Length - let lastStmt = stmts.[stmts.Length - 1] - if BinIR.Utils.isBBEnd lastStmt then - Ok (List.rev acc, ctxt, pc) - else liftLoop ins.NextParsingContext acc pc - | None -> Error [] - liftLoop ctxt [] addr - - static member inline DisasmInstr hdl showAddr resolve (ins: Instruction) = - ins.Disasm (showAddr, resolve, hdl.FileInfo) - - static member inline DisasmInstrSimple (ins: Instruction) = - ins.Disasm () - - static member DisasmBBlock hdl ctxt showAddr resolve addr = - match BinHandler.ParseBBlock hdl ctxt addr with - | Ok (bbl, ctxt) -> - let struct (str, addr) = disasm showAddr resolve hdl.FileInfo addr bbl - Ok (str, addr, ctxt) - | Error bbl -> - let struct (str, addr) = disasm showAddr resolve hdl.FileInfo addr bbl - Error (str, addr) - - static member Optimize stmts = LocalOptimizer.Optimize stmts - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/Library/BinHandler.fsi b/src/FrontEnd/Library/BinHandler.fsi deleted file mode 100644 index 31fbec31..00000000 --- a/src/FrontEnd/Library/BinHandler.fsi +++ /dev/null @@ -1,420 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd - -open B2R2 -open B2R2.BinFile -open B2R2.BinIR - -/// The main hdl for reading/parsing a binary code. BinHandler essentially -/// represents a chunk of binary code either from a string or from an actual -/// binary file. -type BinHandler = { - ISA: ISA - FileInfo: FileInfo - DefaultParsingContext: ParsingContext - TranslationContext: TranslationContext - Parser: Parser - RegisterBay: RegisterBay -} -with - /// - /// Return the byte array of size (nBytes) at the addr from the current - /// binary. - /// - /// The address. - /// The size of the byte array (in bytes). - /// - /// Return the byte array if succeed. Otherwise, raise an exception. - /// - member ReadBytes: addr: Addr * nBytes: int -> byte [] - - /// - /// Return the corresponding integer value at the addr of the size from the - /// current binary. - /// - /// The address. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding integer (int64). - /// - member ReadInt: addr: Addr * size: int -> int64 - - /// - /// Return the corresponding unsigned integer value at the addr of the size - /// from the binary. - /// - /// The address. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding unsigned integer (uint64). - /// - member ReadUInt: addr: Addr * size: int -> uint64 - - /// - /// Return the ASCII string at the addr from the given BinHandler. - /// - /// The address. - /// - /// Return the corresponding ASCII string. - /// - member ReadASCII: addr: Addr -> string - - /// - /// Initialize a BInHnalder from a given binary byte sequence. This function - /// will read the byte sequence and automatically detect its binary format - /// if autoDetect is true. Otherwise, it will consider the given binary - /// sequence as a raw binary (just a series of machine instructions without - /// specific file format). - /// - /// ISA. - /// ArchOperatinoMode. - /// Perform auto format detection or not. - /// Base address for calculating instruction - /// addresses. - /// Raw binary sequence. - /// BinHandler. - static member Init: - isa: ISA - * archMode: ArchOperationMode - * autoDetect: bool - * baseAddr: Addr - * bytes: byte [] - -> BinHandler - - /// - /// Initialize a BinHandler from a given binary file (fileName). This - /// function will read the file and parse it. It will automatically detect - /// the file format if autoDetect is true. Otherwise, it will cnosider the - /// file as a raw binary. - /// - /// ISA. - /// ArchOperatinoMode. - /// Whether to perform auto format detection. - /// Base address for calculating instruction - /// addresses. - /// Binary file. - /// BinHandler. - static member Init: - isa: ISA - * archMode: ArchOperationMode - * autoDetect: bool - * baseAddr: Addr - * fileName: string - -> BinHandler - - /// - /// Initialize a BinHandler from an ISA and a binary file path, assuming - /// that the archMode is NoMode. This function behaves the same as the - /// 2-argument constructor Init (isa, fileName), with a difference of using - /// the specified base address when initializing the BinHandler. - /// - /// ISA. - /// Base address. - /// Binary file path. - /// BinHandler. - static member Init: isa: ISA * baseAddr: Addr * fileName: string -> BinHandler - - /// - /// Initialize a BinHandler from an ISA and a byte sequence, assuming that - /// the archMode is NoMode. This function behaves the same as the 2-argument - /// constructor Init (isa, bytes), with a difference of using the specified - /// base address when initializing the BinHandler. - /// - /// ISA. - /// Base address. - /// Byte sequence. - /// BinHandler. - static member Init: isa: ISA * baseAddr: Addr * bytes: byte [] -> BinHandler - - /// - /// Initialize a BinHandler from an ISA and a binary file path, assuming - /// that the archMode is NoMode. B2R2 will automatically detect the file - /// format of the given binary file, but it will refer to the given ISA - /// parameter either when the binary has multiple architectures, e.g., a fat - /// binary on macOS, or when B2R2 cannot recognize the given file format. If - /// the given binary file does not follow the known formats, then B2R2 - /// consider it as a raw binary with base address at 0. - /// - /// ISA. - /// Binary file path. - /// BinHandler. - static member Init: isa: ISA * fileName: string -> BinHandler - - /// - /// Initialize a BinHandler from an ISA and a byte sequence, assuming that - /// the archMode is NoMode, and the format is RawBinary. - /// - /// ISA. - /// Byte sequence. - /// BinHandler. - static member Init: isa: ISA * bytes: byte [] -> BinHandler - - /// - /// Initialize an empty BinHandler. This function is useful when you want to - /// delay loading the actual body of your binary blob. - /// - /// ISA. - /// ArchOperatinoMode. - /// BinHandler. - static member Init: - isa: ISA - * archMode: ArchOperationMode - -> BinHandler - - /// - /// Initialize an empty BinHandler solely from an ISA, assuming that the - /// archMode is NoMode, and the format is RawBinary. This function is useful - /// when you want to delay loading the actual body of your binary blob. - /// - /// ISA. - /// BinHandler. - static member Init: isa: ISA -> BinHandler - - /// - /// Update BinHandler to have new code at a new address (addr). BinHandler - /// is immutable. - /// - /// The new address to use. - /// The new address to use. - /// The new address to use. - /// New BinHandler. - static member UpdateCode: - hdl: BinHandler -> addr: Addr -> bs: byte [] -> BinHandler - - /// - /// Return the byte array of size (nBytes) at the addr from the given - /// BinHandler. The return value is an option type. When the given address - /// is invalid, this function returns None. - /// - /// BinHandler. - /// The address. - /// The size of the byte array (in bytes). - /// - /// Return (Some bytes) if succeeded, (None) otherwise. - /// - static member TryReadBytes: - hdl: BinHandler * addr: Addr * nBytes: int -> byte [] option - - /// - /// Return the byte array of size (nBytes) at the addr from the given - /// BinHandler. - /// - /// BinHandler. - /// The address. - /// The size of the byte array (in bytes). - /// - /// Return the byte array if succeed. Otherwise, raise an exception. - /// - static member ReadBytes: - hdl: BinHandler * addr: Addr * nBytes: int -> byte [] - - /// - /// Return the corresponding integer option value at the addr of the size - /// from the given BinHandler. - /// - /// BinHandler. - /// The address. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding value (Some int64) if the address and the size - /// is valid. Otherwise None. - /// - static member TryReadInt: - hdl: BinHandler * addr: Addr * size: int -> int64 option - - /// - /// Return the corresponding integer value at the addr of the size from the - /// given BinHandler. - /// - /// BinHandler. - /// The address. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding integer (int64). - /// - static member ReadInt: - hdl: BinHandler * addr: Addr * size: int -> int64 - - /// - /// Return the corresponding unsigned integer option value at the addr of - /// the size from the given BinHandler. - /// - /// BinHandler. - /// The address. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding unsigned integer (Some uint64) if the address - /// and the size is valid. Otherwise, None. - /// - static member TryReadUInt: - hdl: BinHandler * addr: Addr * size: int -> uint64 option - - /// - /// Return the corresponding unsigned integer value at the addr of the size - /// from the given BinHandler. - /// - /// BinHandler. - /// The address. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding unsigned integer (uint64). - /// - static member ReadUInt: - hdl: BinHandler * addr: Addr * size: int -> uint64 - - /// - /// Return the ASCII string at the addr from the given BinHandler. - /// - /// BinHandler. - /// The address. - /// - /// Return the corresponding ASCII string. - /// - static member ReadASCII: - hdl: BinHandler * addr: Addr -> string - - /// - /// Parse one instruction at the given address (addr) from the BinHandler, - /// and return the corresponding instruction. This function raises an - /// exception if the parsing process failed. - /// - /// BinHandler. - /// The address. - /// - /// Parsed instruction. - /// - static member ParseInstr: - hdl: BinHandler -> ParsingContext -> addr: Addr -> Instruction - - /// - /// Parse one instruction at the given address (addr) from the BinHandler, - /// and return the corresponding instruction. This function does not raise - /// an exception, but returns an option type. - /// - /// BinHandler. - /// The address. - /// - /// Parsed instruction (option type). - /// - static member TryParseInstr: - hdl: BinHandler -> ParsingContext -> addr: Addr -> Instruction option - - /// Parse a basic block from the given address, and return the sequence of the - /// instructions of the basic block. This function may return an incomplete - /// basic block as an Error type. This function can be safely used for any - /// ISAs, and thus, this should be the main parsing function. - static member ParseBBlock: - BinHandler - -> ParsingContext - -> addr:Addr - -> Result - - /// Lift a parsed instruction (Instruction) to produce an array of IR - /// statements from a given BinHandler. - static member inline LiftInstr: - hdl: BinHandler -> ins: Instruction -> LowUIR.Stmt [] - - /// Return the lifted IR (an array of statements) of a basic block at the - /// given address. This function returns a partial bblock with Error, if the - /// parsing of the bblock was not successful. - static member LiftBBlock: - hdl: BinHandler - -> ParsingContext - -> addr: Addr - -> Result<(LowUIR.Stmt [] * Addr * ParsingContext), - (LowUIR.Stmt [] * Addr)> - - /// Return the lifted IR (an array of statements) of a basic block at the - /// given address. This function returns a partial bblock with Error, if the - /// parsing of the bblock was not successful. Unlike liftBBlock where the end - /// of a basic block is decided by insInfo, liftIRBBlock decides the end of a - /// basic block when any branch IR statement is encountered. This means that - /// control flows within complex instructions like rep are reflected in - /// splitting basic blocks. - static member LiftIRBBlock: - hdl: BinHandler - -> ParsingContext - -> addr: Addr - -> Result<((Instruction * LowUIR.Stmt []) list * ParsingContext * Addr), - 'a list> - - /// - /// Return a disassembled string from the parsed instruction. - /// - /// BinHandler. - /// Whether to show the instruction address or - /// not. - /// Whether to resolve symbols while disassembling - /// the instruction. - /// The instruction to disassemble. - /// - /// Disassembled string. - /// - static member inline DisasmInstr: - hdl: BinHandler - -> showAddr: bool - -> resolveSymbol: bool - -> ins: Instruction - -> string - - /// - /// Return a disassembled string from the parsed instruction. This function - /// returns a simplified disassembly, which does not contain the instruction - /// address nor symbols. - /// - /// BinHandler. - /// The instruction to disassemble. - /// - /// Disassembled string. - /// - static member inline DisasmInstrSimple: ins: Instruction -> string - - /// - /// Return the disassembled string for a basic block starting at the given - /// address along with the fall-through address of the block. This function - /// returns a partial disassembly if parsing of the bblock was not - /// successful. - /// - static member DisasmBBlock: - hdl: BinHandler - -> ParsingContext - -> showAddr:bool - -> resolveSymbol: bool - -> addr: Addr - -> Result<(string * Addr * ParsingContext), (string * Addr)> - - /// - /// Return optimized statements from the given statements. - /// - static member Optimize: stmts: LowUIR.Stmt [] -> LowUIR.Stmt [] - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/Library/BinHandlerHelper.fs b/src/FrontEnd/Library/BinHandlerHelper.fs deleted file mode 100644 index 1761e681..00000000 --- a/src/FrontEnd/Library/BinHandlerHelper.fs +++ /dev/null @@ -1,115 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinHandlerHelper - -open B2R2 -open B2R2.BinFile -open System.Text - -let initHelpers isa = - match isa.Arch with - | Arch.IntelX64 - | Arch.IntelX86 -> - Intel.IntelTranslationContext (isa) :> TranslationContext, - Intel.IntelParser (isa.WordSize) :> Parser, - Intel.IntelRegisterBay (isa.WordSize) :> RegisterBay - | Arch.ARMv7 -> - ARM32.ARM32TranslationContext (isa) :> TranslationContext, - ARM32.ARM32Parser (isa.Arch) :> Parser, - ARM32.ARM32RegisterBay () :> RegisterBay - | Arch.AARCH64 -> - ARM64.ARM64TranslationContext (isa) :> TranslationContext, - ARM64.ARM64Parser () :> Parser, - ARM64.ARM64RegisterBay () :> RegisterBay - | Arch.MIPS1 | Arch.MIPS2 | Arch.MIPS3 | Arch.MIPS4 | Arch.MIPS5 - | Arch.MIPS32 | Arch.MIPS32R2 | Arch.MIPS32R6 - | Arch.MIPS64 | Arch.MIPS64R2 | Arch.MIPS64R6 -> - MIPS.MIPSTranslationContext (isa) :> TranslationContext, - MIPS.MIPSParser (isa.WordSize, isa.Arch) :> Parser, - MIPS.MIPSRegisterBay (isa.WordSize) :> RegisterBay - | Arch.EVM -> - EVM.EVMTranslationContext (isa) :> TranslationContext, - EVM.EVMParser (isa.WordSize) :> Parser, - EVM.EVMRegisterBay () :> RegisterBay - | Arch.TMS320C6000 -> - TMS320C6000.TMS320C6000TranslationContext (isa) :> TranslationContext, - TMS320C6000.TMS320C6000Parser () :> Parser, - TMS320C6000.TMS320C6000RegisterBay () :> RegisterBay - | _ -> Utils.futureFeature () - -let newFileInfo bs (baddr: Addr) path isa autoDetect = - if autoDetect then - if System.IO.File.Exists path - then FormatDetector.detect path - else FormatDetector.detectBuffer bs - |> function - | FileFormat.ELFBinary -> ELFFileInfo (bs, path, baddr) :> FileInfo - | FileFormat.PEBinary -> PEFileInfo (bs, path, baddr) :> FileInfo - | FileFormat.MachBinary -> MachFileInfo (bs, path, isa, baddr) :> FileInfo - | _ -> new RawFileInfo (bs, isa, baddr) :> FileInfo - else new RawFileInfo (bs, isa, baddr) :> FileInfo - -let detectThumb entryPoint (isa: ISA) = - match entryPoint, isa.Arch with - | Some entry, Arch.ARMv7 when entry % 2UL <> 0UL -> (* XXX: LIbraries? *) - ArchOperationMode.ThumbMode - | _ -> ArchOperationMode.ARMMode - -let isARM (isa: ISA) = - match isa.Arch with - | Arch.ARMv7 | Arch.AARCH32 | Arch.AARCH64 -> true - | _ -> false - -let inline lift translator addr bbl = - let liftFolder (stmts, nextAddr) (ins: Instruction) = - ins.Translate translator :: stmts, nextAddr + uint64 ins.Length - let stmts, addr = List.fold liftFolder ([], addr) bbl - struct (List.rev stmts |> Array.concat, addr) - -let inline disasm showAddr resolveSymbol fileInfo addr bbl = - let disasmFolder (sb: StringBuilder, nextAddr) (ins: Instruction) = - let s = ins.Disasm (showAddr, resolveSymbol, fileInfo) - let s = if sb.Length = 0 then s else System.Environment.NewLine + s - sb.Append(s), nextAddr + uint64 ins.Length - let sb, addr = List.fold disasmFolder (StringBuilder (), addr) bbl - struct (sb.ToString (), addr) - -/// Classify ranges to be either in-file or not-in-file. The second parameter -/// (notinfiles) is a sequence of (exclusive) ranges within the myrange, which -/// represent the not-in-file ranges. This function will simply divide the -/// myrange into subranges where each subrange is labeled with either true or -/// false, where true means in-file, and false means not-in-file. -let classifyRanges myrange notinfiles = - notinfiles - |> Seq.fold (fun (infiles, saddr) r -> - let l = AddrRange.GetMin r - let h = AddrRange.GetMax r - if saddr = l then (r, false) :: infiles, h - else (r, false) :: ((AddrRange (saddr, l), true) :: infiles), h - ) ([], AddrRange.GetMin myrange) - |> (fun (infiles, saddr) -> - if saddr = myrange.Max then infiles - else ((AddrRange (saddr, myrange.Max), true) :: infiles)) - |> List.rev diff --git a/src/FrontEnd/MIPS/B2R2.FrontEnd.MIPS.fsproj b/src/FrontEnd/MIPS/B2R2.FrontEnd.MIPS.fsproj deleted file mode 100644 index 400dadd8..00000000 --- a/src/FrontEnd/MIPS/B2R2.FrontEnd.MIPS.fsproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - netstandard2.1 - false - false - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/FrontEnd/NameMangling.Tests/B2R2.FrontEnd.NameMangling.Tests.fsproj b/src/FrontEnd/NameMangling.Tests/B2R2.FrontEnd.NameMangling.Tests.fsproj new file mode 100644 index 00000000..62f5a0af --- /dev/null +++ b/src/FrontEnd/NameMangling.Tests/B2R2.FrontEnd.NameMangling.Tests.fsproj @@ -0,0 +1,24 @@ + + + + net5.0 + false + + + + + + + + + + + + + + + + + + + diff --git a/src/NameMangling.Tests/ItaniumTests.fs b/src/FrontEnd/NameMangling.Tests/ItaniumTests.fs similarity index 99% rename from src/NameMangling.Tests/ItaniumTests.fs rename to src/FrontEnd/NameMangling.Tests/ItaniumTests.fs index 77a95d05..a5708921 100644 --- a/src/NameMangling.Tests/ItaniumTests.fs +++ b/src/FrontEnd/NameMangling.Tests/ItaniumTests.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -namespace B2R2.NameMangling.Tests +namespace B2R2.FrontEnd.NameMangling.Tests open Microsoft.VisualStudio.TestTools.UnitTesting -open B2R2.NameMangling.Tests.TestLib +open B2R2.FrontEnd.NameMangling.Tests.TestLib [] type ItaniumTests () = diff --git a/src/NameMangling.Tests/MSTests.fs b/src/FrontEnd/NameMangling.Tests/MSTests.fs similarity index 99% rename from src/NameMangling.Tests/MSTests.fs rename to src/FrontEnd/NameMangling.Tests/MSTests.fs index 3bdb236b..74fce164 100644 --- a/src/NameMangling.Tests/MSTests.fs +++ b/src/FrontEnd/NameMangling.Tests/MSTests.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -namespace B2R2.NameMangling.Tests +namespace B2R2.FrontEnd.NameMangling.Tests open Microsoft.VisualStudio.TestTools.UnitTesting -open B2R2.NameMangling.Tests.TestLib +open B2R2.FrontEnd.NameMangling.Tests.TestLib [] type MSTests () = diff --git a/src/NameMangling.Tests/TestLib.fs b/src/FrontEnd/NameMangling.Tests/TestLib.fs similarity index 84% rename from src/NameMangling.Tests/TestLib.fs rename to src/FrontEnd/NameMangling.Tests/TestLib.fs index 66e29b0e..aee8f81f 100644 --- a/src/NameMangling.Tests/TestLib.fs +++ b/src/FrontEnd/NameMangling.Tests/TestLib.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -module B2R2.NameMangling.Tests.TestLib +module B2R2.FrontEnd.NameMangling.Tests.TestLib -open B2R2.NameMangling +open B2R2.FrontEnd.NameMangling open Microsoft.VisualStudio.TestTools.UnitTesting let test mangled demangled = - match Demangler.Demangle mangled with - | true, result -> Assert.AreEqual (demangled, result) - | false, _ -> failwith "Demangling failure." + match Demangler.demangle mangled with + | Ok result -> Assert.AreEqual (demangled, result) + | Error _ -> failwith "Demangling failure." diff --git a/src/NameMangling/B2R2.NameMangling.fsproj b/src/FrontEnd/NameMangling/B2R2.FrontEnd.NameMangling.fsproj similarity index 52% rename from src/NameMangling/B2R2.NameMangling.fsproj rename to src/FrontEnd/NameMangling/B2R2.FrontEnd.NameMangling.fsproj index 9f6f4d80..3fcc213a 100644 --- a/src/NameMangling/B2R2.NameMangling.fsproj +++ b/src/FrontEnd/NameMangling/B2R2.FrontEnd.NameMangling.fsproj @@ -1,7 +1,11 @@ - + - netstandard2.1 + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 name demangling module. @@ -9,20 +13,21 @@ - - + + + - + diff --git a/src/NameMangling/Demangle.fs b/src/FrontEnd/NameMangling/Demangle.fs similarity index 67% rename from src/NameMangling/Demangle.fs rename to src/FrontEnd/NameMangling/Demangle.fs index 191a80a6..f1f20ba2 100644 --- a/src/NameMangling/Demangle.fs +++ b/src/FrontEnd/NameMangling/Demangle.fs @@ -22,22 +22,19 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *) -namespace B2R2.NameMangling - -open System.Runtime.InteropServices - -type Demangler = - static member Detect str = - if MSDemangler.isMSMangled str then MSMangler - elif ItaniumDemangler.isItaniumMangled str then ItaniumMangler +namespace B2R2.FrontEnd.NameMangling + +[] +module Demangler = + [] + let detect str = + if MSDemangler.IsWellFormed str then MSMangler + elif ItaniumDemangler.IsWellFormed str then ItaniumMangler else UnknownMangler - static member Demangle (str, [] dest: byref) = - let result = - match Demangler.Detect str with - | MSMangler -> MSDemangler.demangle str - | ItaniumMangler -> ItaniumDemangler.demangle str - | UnknownMangler-> None - match result with - | None -> false - | Some s -> dest <- s; true + [] + let demangle str = + match detect str with + | MSMangler -> MSDemangler().Run str + | ItaniumMangler -> ItaniumDemangler().Run str + | UnknownMangler-> Error InvalidFormat diff --git a/src/NameMangling/DemangleTypes.fs b/src/FrontEnd/NameMangling/DemangleTypes.fs similarity index 73% rename from src/NameMangling/DemangleTypes.fs rename to src/FrontEnd/NameMangling/DemangleTypes.fs index 7e1317da..4111521a 100644 --- a/src/NameMangling/DemangleTypes.fs +++ b/src/FrontEnd/NameMangling/DemangleTypes.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.NameMangling +namespace B2R2.FrontEnd.NameMangling /// Name mangling schemes. type ManglingScheme = @@ -33,3 +33,18 @@ type ManglingScheme = | ItaniumMangler /// Unknown mangling scheme. | UnknownMangler + +/// Demangler error types. +type DemanglerError = + /// Unknown demangled string format encountered. + | InvalidFormat + /// Parsing failed in the middle. + | ParsingFailure + /// Parsing didn't consume all the string; there is/are trailing char(s). + | TrailingChars + +/// The main demangler interface. +[] +type Demangler () = + /// Take a string as input and return a demangled string as output. + abstract Run: string -> Result diff --git a/src/NameMangling/ItaniumParser.fs b/src/FrontEnd/NameMangling/ItaniumDemangler.fs similarity index 96% rename from src/NameMangling/ItaniumParser.fs rename to src/FrontEnd/NameMangling/ItaniumDemangler.fs index dad5d3df..c02b21ca 100644 --- a/src/NameMangling/ItaniumParser.fs +++ b/src/FrontEnd/NameMangling/ItaniumDemangler.fs @@ -22,14 +22,16 @@ SOFTWARE. *) -namespace B2R2.NameMangling +namespace B2R2.FrontEnd.NameMangling open FParsec open System -open B2R2.NameMangling.ItaniumTables -open B2R2.NameMangling.ItaniumUtils +open B2R2.FrontEnd.NameMangling.ItaniumTables +open B2R2.FrontEnd.NameMangling.ItaniumUtils + +type ItaniumDemangler () = + inherit Demangler () -type ItaniumParser () = let charListtoStr a = String (List.toArray a) let rec convertbase36todecimal idx res input = @@ -557,5 +559,15 @@ type ItaniumParser () = <|> attempt (pScope .>> pDiscard) <|> attempt (pFunctionRetArgs) - member __.Run str = - runParserOnString (stmt) ItaniumUserState.Default "" str + override __.Run str = + match runParserOnString (stmt) ItaniumUserState.Default "" str.[2..] with + | Success (result, _, pos) -> + if pos.Column = int64(str.Length) - 1L then + Result.Ok <| ItaniumInterpreter.interpret result + else Result.Error TrailingChars + | Failure (e, _, _) -> + Result.Error ParsingFailure + + /// Check if the given string is a well-formed mangled string. + static member IsWellFormed (str: string) = + str.Length > 2 && str.[0 .. 1] = "_Z" diff --git a/src/NameMangling/ItaniumFunctionPointer.fs b/src/FrontEnd/NameMangling/ItaniumFunctionPointer.fs similarity index 99% rename from src/NameMangling/ItaniumFunctionPointer.fs rename to src/FrontEnd/NameMangling/ItaniumFunctionPointer.fs index 2dd4ad1e..8a3578dc 100644 --- a/src/NameMangling/ItaniumFunctionPointer.fs +++ b/src/FrontEnd/NameMangling/ItaniumFunctionPointer.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module B2R2.NameMangling.ItaniumFunctionPointer +module B2R2.FrontEnd.NameMangling.ItaniumFunctionPointer /// Getting return from string gained from interpreter for FunctionPointer in /// ItaniumInterpreter.fs. diff --git a/src/NameMangling/ItaniumInterpreter.fs b/src/FrontEnd/NameMangling/ItaniumInterpreter.fs similarity index 99% rename from src/NameMangling/ItaniumInterpreter.fs rename to src/FrontEnd/NameMangling/ItaniumInterpreter.fs index df90570f..78fe20b2 100644 --- a/src/NameMangling/ItaniumInterpreter.fs +++ b/src/FrontEnd/NameMangling/ItaniumInterpreter.fs @@ -23,9 +23,9 @@ *) -module B2R2.NameMangling.ItaniumInterpreter +module B2R2.FrontEnd.NameMangling.ItaniumInterpreter -open B2R2.NameMangling.ItaniumFunctionPointer +open B2R2.FrontEnd.NameMangling.ItaniumFunctionPointer let rec interpret (input: ItaniumExpr) = match input with diff --git a/src/NameMangling/ItaniumTables.fs b/src/FrontEnd/NameMangling/ItaniumTables.fs similarity index 97% rename from src/NameMangling/ItaniumTables.fs rename to src/FrontEnd/NameMangling/ItaniumTables.fs index d8b9f526..8e0cde7f 100644 --- a/src/NameMangling/ItaniumTables.fs +++ b/src/FrontEnd/NameMangling/ItaniumTables.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module B2R2.NameMangling.ItaniumTables +module B2R2.FrontEnd.NameMangling.ItaniumTables let getTypeS = function | 'v' -> "void" diff --git a/src/NameMangling/ItaniumTypes.fs b/src/FrontEnd/NameMangling/ItaniumTypes.fs similarity index 99% rename from src/NameMangling/ItaniumTypes.fs rename to src/FrontEnd/NameMangling/ItaniumTypes.fs index e2323ea2..a9e16726 100644 --- a/src/NameMangling/ItaniumTypes.fs +++ b/src/FrontEnd/NameMangling/ItaniumTypes.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.NameMangling +namespace B2R2.FrontEnd.NameMangling type BuiltinTypeIndicator = | Void @@ -718,6 +718,3 @@ with Carry = Dummy "" RetFlag = 0 ArgPackFlag = 0 } - -type ItaniumParser<'a> = FParsec.Primitives.Parser<'a, ItaniumUserState> - diff --git a/src/NameMangling/ItaniumUtils.fs b/src/FrontEnd/NameMangling/ItaniumUtils.fs similarity index 98% rename from src/NameMangling/ItaniumUtils.fs rename to src/FrontEnd/NameMangling/ItaniumUtils.fs index 30c61ac0..8b17ab25 100644 --- a/src/NameMangling/ItaniumUtils.fs +++ b/src/FrontEnd/NameMangling/ItaniumUtils.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module B2R2.NameMangling.ItaniumUtils +module internal B2R2.FrontEnd.NameMangling.ItaniumUtils open FParsec -open B2R2.NameMangling.ItaniumFunctionPointer +open B2R2.FrontEnd.NameMangling.ItaniumFunctionPointer /// Adding Function Pointer to substitution list. let addfunctionptolist expr = diff --git a/src/NameMangling/MSParser.fs b/src/FrontEnd/NameMangling/MSDemangler.fs similarity index 96% rename from src/NameMangling/MSParser.fs rename to src/FrontEnd/NameMangling/MSDemangler.fs index c04ca461..fbd8e553 100644 --- a/src/NameMangling/MSParser.fs +++ b/src/FrontEnd/NameMangling/MSDemangler.fs @@ -22,13 +22,14 @@ SOFTWARE. *) -namespace B2R2.NameMangling +namespace B2R2.FrontEnd.NameMangling open System open FParsec -open B2R2.NameMangling.MSUtils +open B2R2.FrontEnd.NameMangling.MSUtils -type MSParser () = +type MSDemangler () = + inherit Demangler () (* Helper functions for updating the UserState. *) let addToNameList c = updateUserState ( fun us -> { us with NameList = c :: us.NameList }) @@ -42,7 +43,7 @@ type MSParser () = getUserState >>= (fun parent -> p .>> updateUserState (fun _ -> parent)) let clearUserState = - updateUserState ( fun us -> MSUserState.Default) + updateUserState ( fun _us -> MSUserState.Default) (* Helper functions to parse name. *) let charListToStr lst = String (List.toArray lst) @@ -536,7 +537,15 @@ type MSParser () = attempt pFunc <|> attempt nonFunctionString <|> attempt allThunkFunc <|> attempt pTemplate <|> fullName - - /// Runs parser from a string. - member __.Run str = - runParserOnString allExpressions MSUserState.Default "" str + override __.Run str = + match runParserOnString allExpressions MSUserState.Default "" str.[1..] with + | Success (result, _, _) -> + let result = MSInterpreter.interpret result + Result.Ok <| result.Trim () + | Failure (_, _, _) -> + Result.Error ParsingFailure + + /// Check if the given string is a well-formed mangled string. + static member IsWellFormed (str: string) = + let str = str.Trim () + str.Length <> 0 && str.StartsWith "?" && str.Contains "@" diff --git a/src/NameMangling/MSInterpreter.fs b/src/FrontEnd/NameMangling/MSInterpreter.fs similarity index 98% rename from src/NameMangling/MSInterpreter.fs rename to src/FrontEnd/NameMangling/MSInterpreter.fs index e4704b81..a633e2fb 100644 --- a/src/NameMangling/MSInterpreter.fs +++ b/src/FrontEnd/NameMangling/MSInterpreter.fs @@ -22,9 +22,9 @@ SOFTWARE. *) -module B2R2.NameMangling.MSInterpreter +module B2R2.FrontEnd.NameMangling.MSInterpreter -open B2R2.NameMangling.MSUtils +open B2R2.FrontEnd.NameMangling.MSUtils /// Main interpreter function that outputs the demangled string let rec interpret (sample: MSExpr) = diff --git a/src/NameMangling/MSTypes.fs b/src/FrontEnd/NameMangling/MSTypes.fs similarity index 99% rename from src/NameMangling/MSTypes.fs rename to src/FrontEnd/NameMangling/MSTypes.fs index f80d87ec..538ce84e 100644 --- a/src/NameMangling/MSTypes.fs +++ b/src/FrontEnd/NameMangling/MSTypes.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.NameMangling +namespace B2R2.FrontEnd.NameMangling /// Indicates the data type in the Enum Type. type EnumTypeKind = @@ -470,5 +470,3 @@ type MSUserState = { } with static member Default = { NameList = []; TypeList = [] } - -type MSParser<'a> = FParsec.Primitives.Parser<'a, MSUserState> diff --git a/src/NameMangling/MSUtils.fs b/src/FrontEnd/NameMangling/MSUtils.fs similarity index 99% rename from src/NameMangling/MSUtils.fs rename to src/FrontEnd/NameMangling/MSUtils.fs index 6cb8310b..59226de6 100644 --- a/src/NameMangling/MSUtils.fs +++ b/src/FrontEnd/NameMangling/MSUtils.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module B2R2.NameMangling.MSUtils +module B2R2.FrontEnd.NameMangling.MSUtils let getSpecialName n = match n with diff --git a/src/FrontEnd/NameMangling/README.md b/src/FrontEnd/NameMangling/README.md new file mode 100644 index 00000000..59a2c02b --- /dev/null +++ b/src/FrontEnd/NameMangling/README.md @@ -0,0 +1,11 @@ +# B2R2.FrontEnd.NameMangling + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.FrontEnd.NameMangling Package? + +`B2R2.FrontEnd.NameMangling` contains functions to demangle C++ decorated names. diff --git a/src/FrontEnd/Optimizer/B2R2.FrontEnd.Optimizer.fsproj b/src/FrontEnd/Optimizer/B2R2.FrontEnd.Optimizer.fsproj deleted file mode 100644 index d1f02c0d..00000000 --- a/src/FrontEnd/Optimizer/B2R2.FrontEnd.Optimizer.fsproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - netstandard2.1 - false - false - - - - - - - - - - - - - diff --git a/src/FrontEnd/Optimizer/ExprWalker.fs b/src/FrontEnd/Optimizer/ExprWalker.fs deleted file mode 100644 index c50100ff..00000000 --- a/src/FrontEnd/Optimizer/ExprWalker.fs +++ /dev/null @@ -1,81 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd - -open System.Runtime.InteropServices - -open B2R2 -open B2R2.BinIR.LowUIR - -type internal ConstPropContext = { - VarMap : Map - TempVarMap : Map -} - -type internal ExprWalker = - static member Replace (cpc, e, [] out: byref) = - match e with - | Var (_, n, _, _) -> match cpc.VarMap.TryGetValue n with - | (true, e) -> out <- e; true - | _ -> false - | TempVar (_, n) -> match cpc.TempVarMap.TryGetValue n with - | (true, e) -> out <- e; true - | _ -> false - | UnOp (t, _e, _, _) -> - let (trans, o) = ExprWalker.Replace (cpc, _e) - if trans then out <- AST.unop t o; true else false - | BinOp (t, rt, e1, e2, _, _) -> - let (trans, e1') = ExprWalker.Replace (cpc, e1) - let (trans1, e2') = ExprWalker.Replace (cpc, e2) - if trans || trans1 then - let e1 = if trans then e1' else e1 - let e2 = if trans1 then e2' else e2 - out <- AST.binop t e1 e2; true - else false - | RelOp (t, e1, e2, _, _) -> - let (trans, e1') = ExprWalker.Replace (cpc, e1) - let (trans1, e2') = ExprWalker.Replace (cpc, e2) - if trans || trans1 then - let e1 = if trans then e1' else e1 - let e2 = if trans1 then e2' else e2 - out <- AST.relop t e1 e2; true - else false - | Load (endian, rt, _e, _, _) -> - let (trans, o) = ExprWalker.Replace (cpc, _e) - if trans then out <- AST.load endian rt o; true else false - | Ite (cond, e1, e2, _, _) -> - let (trans, cond') = ExprWalker.Replace (cpc, cond) - let (trans1, e1') = ExprWalker.Replace (cpc, e1) - let (trans2, e2') = ExprWalker.Replace (cpc, e2) - if trans || trans1 || trans2 then - let c = if trans then cond' else cond - let e1 = if trans1 then e1' else e1 - let e2 = if trans2 then e2' else e2 - out <- AST.ite c e1 e2; true - else false - | Cast (t, rt, _e, _, _) -> - let (trans, o) = ExprWalker.Replace (cpc, _e) - if trans then out <- AST.cast t rt o; true else false - | _ -> false diff --git a/src/FrontEnd/Optimizer/LocalOptimizer.fs b/src/FrontEnd/Optimizer/LocalOptimizer.fs deleted file mode 100644 index c67fc4d6..00000000 --- a/src/FrontEnd/Optimizer/LocalOptimizer.fs +++ /dev/null @@ -1,233 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinIR.LowUIR - -module internal DeadCodeEliminator = - type DeadCodeRemovalState = - | IntraBB - | BB - - type DeadCodeRemovalContext = { - UseRegisters : RegisterSet - OutRegisters : RegisterSet - UseTempVar : Set - OutTempVar : Set - State : DeadCodeRemovalState } - - let emptydrc st = - { UseRegisters = RegisterSet.empty - OutRegisters = RegisterSet.empty - UseTempVar = Set.empty - OutTempVar = Set.empty - State = st } - - let removeUse n drc = - { drc with UseRegisters = RegisterSet.remove n drc.UseRegisters } - - let updateUse ei drc = - let { VarInfo = var; TempVarInfo = tvar } = ei - { drc with UseTempVar = Set.union tvar drc.UseTempVar - UseRegisters = RegisterSet.union var drc.UseRegisters } - - let updateUse2 ei ei2 drc = - let { VarInfo = var; TempVarInfo = tvar } = ei - let { VarInfo = var2; TempVarInfo = tvar2 } = ei2 - { drc with UseTempVar = Set.union tvar drc.UseTempVar - |> Set.union tvar2 - UseRegisters = RegisterSet.union var drc.UseRegisters - |> RegisterSet.union var2 } - - let updateUse3 ei ei2 ei3 drc = - let { VarInfo = var; TempVarInfo = tvar } = ei - let { VarInfo = var2; TempVarInfo = tvar2 } = ei2 - let { VarInfo = var3; TempVarInfo = tvar3 } = ei3 - { drc with UseTempVar = Set.union tvar drc.UseTempVar - |> Set.union tvar2 - |> Set.union tvar3 - UseRegisters = RegisterSet.union var drc.UseRegisters - |> RegisterSet.union var2 - |> RegisterSet.union var3 } - - let updateOutUse rs ei drc = - let { VarInfo = var; TempVarInfo = tvar } = ei - { drc with UseTempVar = Set.union tvar drc.UseTempVar - UseRegisters = RegisterSet.union var drc.UseRegisters - OutRegisters = RegisterSet.union rs drc.OutRegisters } - - let createNewArr (stmts: Stmt []) newLen (useInfo: bool []) = - let newStmts = Array.zeroCreate newLen - let rec loop cFinger nFinger = - if nFinger <> newLen then - if useInfo.[cFinger] then - newStmts.[nFinger] <- stmts.[cFinger] - loop (cFinger + 1) (nFinger + 1) - else loop (cFinger + 1) nFinger - else newStmts - loop 0 0 - - let optimize (stmts: Stmt []): Stmt [] = - let len = Array.length stmts - let useInfo = Array.init len (fun _ -> true) - let rec loop idx len drc = - if idx >= 0 then - match stmts.[idx] with - | Store (_, e1, e2) -> - let ei1 = AST.getExprInfo e1 - let ei2 = AST.getExprInfo e2 - loop (idx - 1) len (updateUse2 ei1 ei2 drc) - | InterJmp (_, e, _) -> - let ei = AST.getExprInfo e - loop (idx - 1) len (updateUse ei drc) - | InterCJmp (e, _, e1, e2) -> - let ei = AST.getExprInfo e - let ei1 = AST.getExprInfo e1 - let ei2 = AST.getExprInfo e2 - loop (idx - 1) len (updateUse3 ei ei1 ei2 drc) - (* Need Barrier: Flush whole context *) - | LMark _ -> loop (idx - 1) len (emptydrc IntraBB) - | Jmp e -> - let ei = AST.getExprInfo e - loop (idx - 1) len (updateUse ei drc) - | CJmp (e, e1, e2) -> - let ei = AST.getExprInfo e - let ei1 = AST.getExprInfo e1 - let ei2 = AST.getExprInfo e2 - loop (idx - 1) len (updateUse3 ei ei1 ei2 drc) - (* Update ctx *) - | Put (Var (_, n, nn, rs), rhs) -> - let isUsed = RegisterSet.exist n drc.UseRegisters - let drc = if isUsed then removeUse n drc else drc - if not isUsed && RegisterSet.exist n drc.OutRegisters then - useInfo.[idx] <- false; loop (idx - 1) (len - 1) drc - else loop (idx - 1) len (updateOutUse rs (AST.getExprInfo rhs) drc) - | Put (TempVar (_, n), rhs) -> - match drc.State with - | BB -> - if Set.contains n drc.UseTempVar then - loop (idx - 1) len (updateUse (AST.getExprInfo rhs) drc) - else useInfo.[idx] <- false; loop (idx - 1) (len - 1) drc - | IntraBB -> - loop (idx - 1) len (updateUse (AST.getExprInfo rhs) drc) - | ISMark _ -> - loop (idx - 1) len { drc with UseTempVar = Set.empty; State = BB } - (* Always out *) - | _ -> loop (idx - 1) len drc - else createNewArr stmts len useInfo - loop (len - 1) len (emptydrc BB) - -module internal ConstantFolder = - let emptyCtx = - { VarMap = Map.empty - TempVarMap = Map.empty } - - let update cpc lhs rhs = - (* Only capturing in case of Num *) - match lhs, rhs with - | Var (_, n, _, _), Num _ -> - { cpc with VarMap = Map.add n rhs cpc.VarMap } - (* FIXME: Ensure SSA - | Var (_, n, _), Var _ -> - { cpc with VarMap = Map.add n rhs cpc.VarMap } *) - | Var (_, n, _, _), _ -> { cpc with VarMap = Map.remove n cpc.VarMap } - | TempVar (_, n), Num _ -> - { cpc with TempVarMap = Map.add n rhs cpc.TempVarMap } - (* FIXME: Ensure SSA - | TempVar (_, n), Var _ -> - { cpc with TempVarMap = Map.add n rhs cpc.TempVarMap } *) - | TempVar (_, n), _ -> - { cpc with TempVarMap = Map.remove n cpc.TempVarMap } - | _ -> cpc - - let optimize (stmts: Stmt []) = - let stmts = Array.copy stmts - let rec loop idx cpc = - if Array.length stmts > idx then - match stmts.[idx] with - | Store (endian, e1, e2) -> - let (nT1, e1') = ExprWalker.Replace (cpc, e1) - let (nT2, e2') = ExprWalker.Replace (cpc, e2) - if nT1 || nT2 then - let e1' = if nT1 then e1' else e1 - let e2' = if nT2 then e2' else e2 - stmts.[idx] <- Store (endian, e1', e2') - loop (idx + 1) cpc - | InterJmp (pc, e, t) -> - let (needTrans, e') = ExprWalker.Replace (cpc, e) - if needTrans then stmts.[idx] <- InterJmp (pc, e', t) - loop (idx + 1) cpc - | InterCJmp (e, pc, e1, e2) -> - let (nT, e') = ExprWalker.Replace (cpc, e) - let (nT1, e1') = ExprWalker.Replace (cpc, e1) - let (nT2, e2') = ExprWalker.Replace (cpc, e2) - if nT || nT1 || nT2 then - let e' = if nT then e' else e - let e1' = if nT1 then e1' else e1 - let e2' = if nT2 then e2' else e2 - stmts.[idx] <- match e' with - | Num (n) when BitVector.isOne n -> - InterJmp (pc, e1', InterJmpInfo.Base) - | Num (n) -> InterJmp (pc, e2', InterJmpInfo.Base) - | _ -> InterCJmp (e', pc, e1', e2') - loop (idx + 1) cpc - (* Need Barrier: Flush whole context *) - | LMark _ -> loop (idx + 1) emptyCtx - | Jmp e -> - let (needTrans, e') = ExprWalker.Replace (cpc, e) - if needTrans then stmts.[idx] <- Jmp (e') - loop (idx + 1) emptyCtx - | CJmp (e, e1, e2) -> - let (nT, e') = ExprWalker.Replace (cpc, e) - let (nT1, e1') = ExprWalker.Replace (cpc, e1) - let (nT2, e2') = ExprWalker.Replace (cpc, e2) - if nT || nT1 || nT2 then - let e' = if nT then e' else e - let e1' = if nT1 then e1' else e1 - let e2' = if nT2 then e2' else e2 - stmts.[idx] <- match e' with - | Num (n) when BitVector.isOne n -> Jmp (e1') - | Num (n) -> Jmp (e2') - | _ -> CJmp (e', e1', e2') - loop (idx + 1) emptyCtx - (* Update ctx *) - | Put (lhs, rhs) -> - let rhs = match ExprWalker.Replace (cpc, rhs) with - | true, rhs -> stmts.[idx] <- Put (lhs, rhs); rhs - | _ -> rhs - loop (idx + 1) (update cpc lhs rhs) - (* Always out *) - | ISMark _ | IEMark _ | SideEffect _ -> loop (idx + 1) cpc - else stmts - loop 0 emptyCtx - -/// Intra-block local IR optimizer. -type LocalOptimizer = - /// Run optimization on the basic block (an array of IR statements). - static member Optimize stmts = - ConstantFolder.optimize stmts - |> DeadCodeEliminator.optimize diff --git a/src/FrontEnd/TMS320C6000/B2R2.FrontEnd.TMS320C6000.fsproj b/src/FrontEnd/TMS320C6000/B2R2.FrontEnd.TMS320C6000.fsproj deleted file mode 100644 index 31b98f31..00000000 --- a/src/FrontEnd/TMS320C6000/B2R2.FrontEnd.TMS320C6000.fsproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - netstandard2.1 - false - false - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/FrontEnd/TMS320C6000/TMS320C6000Parser.fsi b/src/FrontEnd/TMS320C6000/TMS320C6000Parser.fsi deleted file mode 100644 index 27574d5d..00000000 --- a/src/FrontEnd/TMS320C6000/TMS320C6000Parser.fsi +++ /dev/null @@ -1,35 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -/// TMS320C6000 instruction parser. -module B2R2.FrontEnd.TMS320C6000.Parser - -open B2R2 -open B2R2.FrontEnd - -/// Read in bytes and return a parsed instruction for TMS320C6000. This function -/// returns TMS320C6000Instruction, which is a specialized type for TMS320C6000. -/// If you want to handle instructions in a platform-agnostic manner, you'd -/// better use the TMS320C6000 class. -val parse: BinReader -> ParsingContext -> Addr -> int -> TMS320C6000Instruction diff --git a/src/Lens/B2R2.Lens.fsproj b/src/Lens/B2R2.Lens.fsproj deleted file mode 100644 index 570306d5..00000000 --- a/src/Lens/B2R2.Lens.fsproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - netstandard2.1 - - - - - - - - - - - - - - - - - - - diff --git a/src/Lens/CallGraphLens.fs b/src/Lens/CallGraphLens.fs deleted file mode 100644 index fa77a286..00000000 --- a/src/Lens/CallGraphLens.fs +++ /dev/null @@ -1,133 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.Lens - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinGraph -open B2R2.BinEssence -open System.Collections.Generic - -/// Basic block type for a call graph (CallCFG). -type CallGraphBBlock (addr, id, name, isFake, isExternal) = - inherit BasicBlock (ProgramPoint (addr, 0)) - - member __.ID with get () = id - - member __.Name with get () = name - - member __.IsExternal with get () = isExternal - - override __.Range = AddrRange (addr, addr + 1UL) - - override __.IsFakeBlock () = isFake - - override __.ToVisualBlock () = - [| [| { AsmWordKind = AsmWordKind.Address - AsmWordValue = Addr.toString WordSize.Bit32 addr } - { AsmWordKind = AsmWordKind.String - AsmWordValue = ": " } - { AsmWordKind = AsmWordKind.Value - AsmWordValue = id } |] |] - -/// Call graph, where each node represents a function. -type CallCFG = ControlFlowGraph - -module CallCFG = - let private initializer core = - CallCFG (core) :> DiGraph - - let private initImperative () = - ImperativeCore (initializer, UnknownEdge) - |> CallCFG - :> DiGraph - - let private initPersistent () = - PersistentCore (initializer, UnknownEdge) - |> CallCFG - :> DiGraph - - /// Initialize CallCFG based on the implementation type. - let init = function - | ImperativeGraph -> initImperative () - | PersistentGraph -> initPersistent () - -/// A mapping from an address to a CallCFG vertex. -type CallVMap = Dictionary> - -/// A graph lens for obtaining CallGraph. -type CallGraphLens () = - let getFunctionVertex g vMap (old: Vertex) addr ess = - match (vMap: CallVMap).TryGetValue addr with - | false, _ -> - let fake = old.VData.IsFakeBlock () - match ess.CalleeMap.Find (addr) with - | None -> None - | Some callee -> - let id = callee.CalleeID - let name = callee.CalleeName - let ext = callee.CalleeKind = ExternalCallee - let v, g = - DiGraph.addVertex g (CallGraphBBlock (addr, id, name, fake, ext)) - vMap.Add (addr, v) - Some (v, g) - | true, v -> Some (v, g) - - let getVertex g vMap (old: Vertex) ess = - let addr = old.VData.PPoint.Address - match ess.CalleeMap.Find (addr) with - | None -> None - | Some _ -> getFunctionVertex g vMap old addr ess - - let buildCG callCFG vMap ess = - callCFG - |> DiGraph.foldEdge ess.SCFG (fun callCFG src dst e -> - match e with - | IntraJmpEdge - | IndirectJmpEdge - | IndirectCallEdge - | ExternalJmpEdge - | ExternalCallEdge - | CallEdge -> - (* XXX: Should be fixed *) - match ess.FindFunctionVertex src.VData.PPoint.Address with - | None -> callCFG - | Some src -> - match getVertex callCFG vMap src ess with - | None -> callCFG - | Some (s, callCFG) -> - match getVertex callCFG vMap dst ess with - | None -> callCFG - | Some (d, callCFG) -> DiGraph.addEdge callCFG s d e - | _ -> callCFG) - - interface ILens with - member __.Filter (g, _, ess) = - let vMap = CallVMap () - let callCFG = buildCG (CallCFG.init g.ImplementationType) vMap ess - callCFG, DiGraph.getUnreachables callCFG |> Seq.toList - - static member Init () = - CallGraphLens () :> ILens diff --git a/src/Lens/DisasmLens.fs b/src/Lens/DisasmLens.fs deleted file mode 100644 index db0cb970..00000000 --- a/src/Lens/DisasmLens.fs +++ /dev/null @@ -1,177 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.Lens - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinGraph -open B2R2.BinEssence -open System -open System.Collections.Generic - -/// Basic block type for a disassembly-based CFG (DisasmCFG). -type DisasmBBlock (instrs: Instruction [], pp, ess: BinEssence) = - inherit BasicBlock (pp) - - let mutable instructions = instrs - - let symbolize (ins: Instruction) (words: AsmWord []) = - let last = words.[words.Length - 1] - if ins.IsBranch () && last.AsmWordKind = AsmWordKind.Value then - let addr = Convert.ToUInt64 (last.AsmWordValue, 16) - match ess.CalleeMap.Find (addr) with - | Some callee -> - words.[words.Length - 1] <- - { AsmWordKind = AsmWordKind.Value; AsmWordValue = callee.CalleeID } - | None -> () - words - else words - - override __.Range = - let last = instructions.[instructions.Length - 1] - AddrRange (last.Address, last.Address + uint64 last.Length) - - override __.IsFakeBlock () = Array.isEmpty instructions - - override __.ToVisualBlock () = - instructions - |> Array.map (fun i -> i.Decompose () |> symbolize i) - - member __.Instructions - with get () = instructions - and set (i) = instructions <- i - - member __.Disassemblies - with get () = - instructions |> Array.map (fun i -> i.Disasm ()) - - override __.ToString () = - if instrs.Length = 0 then "DisasmBBLK(Dummy)" - else "DisasmBBLK(" + __.PPoint.Address.ToString("X") + ")" - -/// Disassembly-based CFG, where each node contains disassembly code. -type DisasmCFG = ControlFlowGraph - -[] -module DisasmCFG = - let private initializer core = - DisasmCFG (core) :> DiGraph - - let private initImperative () = - ImperativeCore (initializer, UnknownEdge) - |> DisasmCFG - :> DiGraph - - let private initPersistent () = - PersistentCore (initializer, UnknownEdge) - |> DisasmCFG - :> DiGraph - - /// Initialize IRCFG based on the implementation type. - let init = function - | ImperativeGraph -> initImperative () - | PersistentGraph -> initPersistent () - -/// A mapping from an address to a DisasmCFG vertex. -type DisasmVMap = Dictionary> - -/// A graph lens for obtaining DisasmCFG. -type DisasmLens (ess) = - let getVertex g (vMap: DisasmVMap) oldVertex addr = - match vMap.TryGetValue addr with - | false, _ -> - let instrs = (oldVertex: Vertex).VData.GetInstructions () - let blk = DisasmBBlock (instrs, oldVertex.VData.PPoint, ess) - let v, g = DiGraph.addVertex g blk - vMap.Add (addr, v) - v, g - | true, v -> v, g - - let dfs fnMerge fnEdge ircfg newGraph (roots: Vertex list) = - let visited = HashSet () - let rec traverse newGraph = function - | [] -> newGraph - | (addr, v: Vertex) :: rest -> - if visited.Contains v.VData.PPoint then traverse newGraph rest - else - visited.Add v.VData.PPoint |> ignore - let acc, newGraph = - DiGraph.getSuccs ircfg v - |> List.fold (succFold addr v) (rest, newGraph) - traverse newGraph acc - and succFold addr v (acc, newGraph) succ = - match DiGraph.findEdgeData ircfg v succ with - | ExternalJmpEdge - | ExternalCallEdge - | CallEdge - | RetEdge -> acc, newGraph - | CallFallThroughEdge - when DiGraph.getPreds ircfg succ |> List.length <= 2 -> - (* Two edges: (1) RetEdge from a fake node; (2) CallFallThroughEdge. *) - let newGraph = fnMerge newGraph addr v succ - if visited.Contains succ.VData.PPoint then acc, newGraph - else (addr, succ) :: acc, newGraph - | IntraCJmpTrueEdge - | IntraCJmpFalseEdge - | IntraJmpEdge -> - let newGraph = fnMerge newGraph addr v succ - if visited.Contains succ.VData.PPoint then acc, newGraph - else (addr, succ) :: acc, newGraph - | e -> - let newGraph = fnEdge newGraph addr v succ e - if visited.Contains succ.VData.PPoint then acc, newGraph - else (succ.VData.PPoint.Address, succ) :: acc, newGraph - roots - |> List.map (fun r -> r.VData.PPoint.Address, r) - |> traverse newGraph - - let merge vMap newGraph addr v (succ: Vertex) = - let srcV, newGraph = getVertex newGraph vMap v addr - Array.append srcV.VData.Instructions (succ.VData.GetInstructions ()) - |> Array.fold (fun m i -> Map.add i.Address i m) Map.empty - |> Map.toArray (* Remove overlapping instructions in an inefficient way. *) - |> Array.map snd - |> fun instrs -> srcV.VData.Instructions <- instrs - newGraph - - let addEdge vMap newGraph sAddr src dst e = - let dstAddr = (dst: Vertex).VData.PPoint.Address - let srcV, newGraph = getVertex newGraph vMap src sAddr - let dstV, newGraph = getVertex newGraph vMap dst dstAddr - DiGraph.addEdge newGraph srcV dstV e - - interface ILens with - member __.Filter (g, roots, _) = - let newGraph = DisasmCFG.init g.ImplementationType - let vMap = DisasmVMap () - let roots', newGraph = - roots (* Add nodes to newGraph. *) - |> List.fold (fun (roots, newGraph) r -> - let r, newGraph = getVertex newGraph vMap r r.VData.PPoint.Address - r :: roots, newGraph) ([], newGraph) - let newGraph = dfs (merge vMap) (addEdge vMap) g newGraph roots - newGraph, roots' - - static member Init (ess) = DisasmLens (ess) :> ILens diff --git a/src/Lens/ILens.fs b/src/Lens/ILens.fs deleted file mode 100644 index 9f57f8cb..00000000 --- a/src/Lens/ILens.fs +++ /dev/null @@ -1,48 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.Lens - -open B2R2.BinGraph -open B2R2.BinEssence - -/// The Lens interface, which is a converter from a graph to another graph. In -/// B2R2, An IR-level SCFG forms the basis, and we should apply different lenses -/// to obtain different graphs. For example, we can get disassembly-based CFG by -/// applying DisasmLens to the SCFG. -type ILens<'D when 'D :> BasicBlock and 'D: equality> = - /// - /// The main function of the ILens interface, which will essentially convert a - /// given CFG into another graph. - /// - /// The given CFG. - /// The list of root nodes of the CFG. - /// - /// A converted graph along with its root node. - /// - abstract member Filter: - graph: DiGraph - * roots: Vertex list - * ess: BinEssence - -> DiGraph<'D, CFGEdgeKind> * Vertex<'D> list diff --git a/src/Lens/SSABlock.fs b/src/Lens/SSABlock.fs deleted file mode 100644 index dff52f30..00000000 --- a/src/Lens/SSABlock.fs +++ /dev/null @@ -1,159 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.Lens - -open B2R2 -open B2R2.BinIR -open B2R2.FrontEnd -open B2R2.BinGraph -open B2R2.BinEssence - -module SSABlockHelper = - let private updateDefinedVar set = function - | LowUIR.Put (LowUIR.Var (_) as dst, _) -> - Set.add (SSA.AST.translateDest dst) set - | LowUIR.Store (_) -> - Set.add ({ SSA.Kind = SSA.MemVar; SSA.Identifier = -1 }) set - | _ -> set - - let private defVarFolder acc (v: Vertex) = - v.VData.GetIRStatements () - |> Array.fold (fun acc stmts -> Array.fold updateDefinedVar acc stmts) acc - - let private getStackPtrDef (hdl: BinHandler) wordSize = - match hdl.RegisterBay.StackPointer with - | Some sp -> - SSA.RegVar (wordSize, sp, hdl.RegisterBay.RegIDToString sp) |> Some - | None -> None - - let private getReturnValDef (hdl: BinHandler) wordSize = - let r = CallingConvention.returnRegister hdl - SSA.RegVar (wordSize, r, hdl.RegisterBay.RegIDToString r) |> Some - - let private addDefaultDefs hdl = - let wordSize = hdl.ISA.WordSize |> WordSize.toRegType - [ getStackPtrDef hdl wordSize; getReturnValDef hdl wordSize ] - |> List.choose id - |> List.map (fun kind -> { SSA.Kind = kind; SSA.Identifier = -1 }) - |> Set.ofList - - let private isGetPCThunkCode = function - | 0xc324048bUL | 0xc3241c8bUL | 0xc3240c8bUL | 0xc324148bUL - | 0xc324348bUL | 0xc3243c8bUL | 0xc3242c8bUL -> true - | _ -> false - - /// This is a heuristic to discover __x86.get_pc_thunk- family functions. - /// 1. If a function name symbol exists and its name matches, then we know it is - /// __x86.get_pc_thunk- family - /// 2. But there are some cases we don't have symbols for them. In such cases, - /// we directly compare first 4 bytes of byte code. Because __x86.get_pc_thunk- - /// family only has 4 bytes for its function body and their values are fixed. - let private isGetPCThunk hdl addr = - match hdl.FileInfo.TryFindFunctionSymbolName addr |> Utils.tupleToOpt with - | Some name -> name.StartsWith "__x86.get_pc_thunk" - | None -> BinHandler.ReadUInt (hdl, addr, 4) |> isGetPCThunkCode - - /// This is currently intra-procedural. - let computeDefinedVars (ess: BinEssence) addr = - let hdl = ess.BinHandler - try - let g, _ = ess.GetFunctionCFG (addr, false) - let defs = DiGraph.foldVertex g defVarFolder Set.empty - let defs = if Set.isEmpty defs then addDefaultDefs hdl else defs - let defs = - if isGetPCThunk hdl addr then defs - else - let wordSize = hdl.ISA.WordSize |> WordSize.toRegType - let r = CallingConvention.returnRegister hdl - let retReg = SSA.RegVar (wordSize, r, hdl.RegisterBay.RegIDToString r) - if not <| hdl.FileInfo.IsLinkageTable addr then defs - else Set.add { SSA.Kind = SSA.MemVar; SSA.Identifier = -1 } defs - |> Set.add { SSA.Kind = retReg; SSA.Identifier = -1 } - Set.toArray defs - with _ -> addDefaultDefs hdl |> Set.toArray - -/// Basic block type for an SSA-based CFG (SSACFG). -type SSABBlock private (ess, pp, instrs, retPoint, hasIndirectBranch) = - inherit BasicBlock (pp) - - let mutable stmts = - match retPoint with - | Some (ret: ProgramPoint) -> - let stmts = (* For a fake block, we check which things can be modified. *) - SSABlockHelper.computeDefinedVars ess (pp: ProgramPoint).Address - |> Array.map (fun dst -> - let src = { SSA.Kind = dst.Kind; SSA.Identifier = -1 } - SSA.Def (dst, SSA.ReturnVal (pp.Address, ret.Address, src))) - let wordSize = ess.BinHandler.ISA.WordSize |> WordSize.toRegType - let fallThrough = BitVector.ofUInt64 ret.Address wordSize - let jmpToFallThrough = SSA.Jmp (SSA.InterJmp (SSA.Num fallThrough)) - Array.append stmts [| jmpToFallThrough |] - | None -> - (instrs: InstructionInfo []) - |> Array.map (fun i -> - let wordSize = i.Instruction.WordSize |> WordSize.toRegType - i.Stmts |> SSA.AST.translateStmts wordSize i.Instruction.Address) - |> Array.concat - - let mutable frontier: Vertex list = [] - - new (ess, pp, instrs, hasIndirectBranch) = - SSABBlock (ess, pp, instrs, None, hasIndirectBranch) - - new (ess, pp, retAddr, hasIndirectBranch) = - SSABBlock (ess, pp, [||], Some retAddr, hasIndirectBranch) - - override __.Range = - let last = instrs.[instrs.Length - 1].Instruction - AddrRange (pp.Address, last.Address + uint64 last.Length) - - override __.IsFakeBlock () = Array.isEmpty instrs - - override __.ToVisualBlock () = - __.Stmts - |> Array.map (fun stmt -> - [| { AsmWordKind = AsmWordKind.String - AsmWordValue = SSA.Pp.stmtToString stmt } |]) - - /// Does this block has indirect branch? - member __.HasIndirectBranch: bool = hasIndirectBranch - - /// Get the last statement of the bblock. - member __.GetLastStmt () = - stmts.[stmts.Length - 1] - - member __.Stmts with get () = stmts and set (v) = stmts <- v - - member __.InsInfos with get () = instrs - - member __.Frontier with get () = frontier and set(v) = frontier <- v - - member __.InsertPhi varKind count = - let var = { SSA.Kind = varKind; SSA.Identifier = -1 } - stmts <- Array.append [| SSA.Phi (var, Array.zeroCreate count) |] stmts - - override __.ToString () = - if instrs.Length = 0 then "SSABBLK(Dummy)" - else "SSABBLK(" + __.PPoint.Address.ToString("X") + ")" diff --git a/src/Lens/SSAEdges.fs b/src/Lens/SSAEdges.fs deleted file mode 100644 index 7e67a171..00000000 --- a/src/Lens/SSAEdges.fs +++ /dev/null @@ -1,94 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.Lens.SSAEdges - -open B2R2 -open B2R2.BinIR -open B2R2.BinGraph - -type SSAStmtLocation = VertexID * int - -type EdgeInfo = { - /// A mapping from an SSA var to a set of use locations. - Uses: Map> - /// A mapping from an SSA var to its def stmt. - Defs: Map -} - -let private addUse var loc info = - match Map.tryFind var info.Uses with - | Some set -> Set.add loc set - | None -> Set.singleton loc - |> fun set -> { info with Uses = Map.add var set info.Uses } - -let private addDef var stmt info = - { info with Defs = Map.add var stmt info.Defs } - -let rec private computeUses loc expr acc = - match expr with - | SSA.Var v -> addUse v loc acc - | SSA.Load (mem, _, addr) -> addUse mem loc acc |> computeUses loc addr - | SSA.Store (mem, _, addr, v) -> - addUse mem loc acc |> computeUses loc addr |> computeUses loc v - | SSA.UnOp (_, _, e) -> computeUses loc e acc - | SSA.BinOp (_, _, e1, e2) -> computeUses loc e1 acc |> computeUses loc e2 - | SSA.RelOp (_, _, e1, e2) -> computeUses loc e1 acc |> computeUses loc e2 - | SSA.Ite (cond, _, e1, e2) -> - computeUses loc cond acc |> computeUses loc e1 |> computeUses loc e2 - | SSA.Cast (_, _, e) -> computeUses loc e acc - | SSA.Extract (e, _, _) -> computeUses loc e acc - | SSA.ReturnVal (_, _, v) -> addUse v loc acc - | _ -> acc - -/// Compute SSA edge map (SSA Var -> a set of (VertexID, Stmt idx)). From a -/// given ssa var, this function returns a set of SSA-edge destination. -let compute ssaCFG = - let emptyInfo = { Uses = Map.empty; Defs = Map.empty } - emptyInfo - |> DiGraph.foldVertex ssaCFG (fun acc (v: Vertex) -> - let vid = v.GetID () - v.VData.Stmts - |> Array.foldi (fun acc idx stmt -> - match stmt with - | SSA.LMark _ - | SSA.SideEffect _ -> acc - | SSA.Jmp (SSA.IntraJmp _) -> acc - | SSA.Jmp (SSA.IntraCJmp (cond, _, _)) -> computeUses (vid, idx) cond acc - | SSA.Jmp (SSA.InterJmp (target)) -> computeUses (vid, idx) target acc - | SSA.Jmp (SSA.InterCJmp (cond, t1, t2)) -> - let loc = vid, idx - computeUses loc cond acc |> computeUses loc t1 |> computeUses loc t2 - | SSA.Def (v, e) -> - let loc = vid, idx - addDef v stmt acc - |> computeUses loc e - | SSA.Phi (v, ns) -> - let loc = vid, idx - let acc = addDef v stmt acc - ns - |> Array.fold (fun acc n -> - let u = { v with Identifier = n } - addUse u loc acc) acc - ) acc |> fst) diff --git a/src/Lens/SSALens.fs b/src/Lens/SSALens.fs deleted file mode 100644 index 2b8fde40..00000000 --- a/src/Lens/SSALens.fs +++ /dev/null @@ -1,99 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.Lens - -open B2R2 -open B2R2.BinGraph -open B2R2.BinEssence - -/// A graph lens for obtaining SSACFG. -type SSALens (ess) = - let getVertex g (vMap: SSAVMap) oldSrc = - let vData = (oldSrc: Vertex).VData - let pos = vData.PPoint - match vMap.TryGetValue pos with - | false, _ -> - let instrs = vData.GetInsInfos () - let hasIndBranch = vData.HasIndirectBranch - let bblock = SSABBlock (ess, pos, instrs, hasIndBranch) - let v, g = DiGraph.addVertex g bblock - vMap.Add (pos, v) - v, g - | true, v -> v, g - - let getFakeVertex g (fMap: FakeVMap) srcPos dstPos = - let pos = (srcPos, dstPos) - match fMap.TryGetValue pos with - | false, _ -> - let bblock = SSABBlock (ess, srcPos, dstPos, false) - let v, g = DiGraph.addVertex g bblock - fMap.Add (pos, v) - v, g - | true, v -> v, g - - let convertToSSA irCFG ssaCFG vMap fMap roots = - let roots, ssaCFG = - roots |> List.fold (fun (roots, ssaCFG) r -> - let r, ssaCFG = getVertex ssaCFG vMap r - r :: roots, ssaCFG) ([], ssaCFG) - let ssaCFG = - ssaCFG - |> DiGraph.foldEdge irCFG (fun ssaCFG src dst e -> - (* If a node is fake, it is a call target. *) - if (dst: Vertex).VData.IsFakeBlock () then - let last = src.VData.LastInstruction - let fall = ProgramPoint (last.Address + uint64 last.Length, 0) - let srcV, ssaCFG = getVertex ssaCFG vMap src - let dstV, ssaCFG = - getFakeVertex ssaCFG fMap dst.VData.PPoint fall - DiGraph.addEdge ssaCFG srcV dstV e - elif src.VData.IsFakeBlock () then - let srcV, ssaCFG = - getFakeVertex ssaCFG fMap src.VData.PPoint dst.VData.PPoint - let dstV, ssaCFG = getVertex ssaCFG vMap dst - DiGraph.addEdge ssaCFG srcV dstV e - else - let srcV, ssaCFG = getVertex ssaCFG vMap src - let dstV, ssaCFG = getVertex ssaCFG vMap dst - DiGraph.addEdge ssaCFG srcV dstV e) - ssaCFG, roots - - interface ILens with - member __.Filter (g, roots, _) = - let ssaCFG = SSACFG.init g.ImplementationType - let vMap = SSAVMap () - let fMap = FakeVMap () - let defSites = DefSites () - let ssaCFG, roots = convertToSSA g ssaCFG vMap fMap roots - let root = List.head roots - DiGraph.findVertexBy ssaCFG (fun v -> - v.VData.PPoint = root.VData.PPoint && not <| v.VData.IsFakeBlock ()) - |> SSAUtils.computeFrontiers ssaCFG - |> SSAUtils.placePhis ssaCFG vMap fMap defSites - |> SSAUtils.renameVars ssaCFG defSites - ssaCFG, roots - - static member Init ess = - SSALens (ess) :> ILens diff --git a/src/Lens/SSATypes.fs b/src/Lens/SSATypes.fs deleted file mode 100644 index c7f8b75e..00000000 --- a/src/Lens/SSATypes.fs +++ /dev/null @@ -1,78 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.Lens - -open B2R2 -open B2R2.BinIR -open B2R2.BinGraph -open B2R2.BinEssence -open System.Collections.Generic - -type SSAVertex = Vertex - -/// SSA-based CFG, where each node contains disassembly code. -type SSACFG = ControlFlowGraph - -module SSACFG = - let private initializer core = - SSACFG (core) :> DiGraph - - let private initImperative () = - ImperativeCore (initializer, UnknownEdge) - |> SSACFG - :> DiGraph - - let private initPersistent () = - PersistentCore (initializer, UnknownEdge) - |> SSACFG - :> DiGraph - - /// Initialize SSACFG based on the implementation type. - let init = function - | ImperativeGraph -> initImperative () - | PersistentGraph -> initPersistent () - -/// A mapping from an address to a SSACFG vertex. -type SSAVMap = Dictionary - -/// This is a mapping from an edge to a dummy vertex (for external function -/// calls). We first separately create dummy vertices even if they are -/// associated with the same node (address) in order to compute dominance -/// relationships without introducing incorrect paths or cycles. For -/// convenience, we will always consider as a key "a return edge" from a fake -/// vertex to a fall-through vertex. -type FakeVMap= Dictionary - -/// Mapping from a variable to a set of defining SSA basic blocks. -type DefSites = Dictionary> - -/// Defined variables per node in a SSACFG. -type DefsPerNode = Dictionary> - -/// Counter for each variable. -type VarCountMap = Dictionary - -/// Variable ID stack. -type IDStack = Dictionary diff --git a/src/Lens/SSAUtils.fs b/src/Lens/SSAUtils.fs deleted file mode 100644 index b1a0dbff..00000000 --- a/src/Lens/SSAUtils.fs +++ /dev/null @@ -1,193 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.Lens.SSAUtils - -open B2R2 -open B2R2.BinIR -open B2R2.BinGraph - -let computeFrontiers g root = - let domCtxt = Dominator.initDominatorContext g root - DiGraph.iterVertex g (fun (v: SSAVertex) -> - v.VData.Frontier <- Dominator.frontier domCtxt v) - domCtxt - -let collectDefVars defs = function - | SSA.Def ({ Kind = k }, _) -> Set.add k defs - | _ -> defs - -let findPhiSites g defsPerNode variable (phiSites, workList) v = - if Set.contains v phiSites then phiSites, workList - else - (* Insert Phi for v *) - DiGraph.getPreds g v - |> List.length - |> (v: Vertex).VData.InsertPhi variable - let phiSites = Set.add v phiSites - let defs = (defsPerNode: DefsPerNode).[v] - if not <| Set.contains variable defs then phiSites, v :: workList - else phiSites, workList - -let rec iterDefs g phiSites defsPerNode variable = function - | [] -> phiSites - | (v: SSAVertex) :: workList -> - let phiSites, workList = - v.VData.Frontier - |> List.fold (findPhiSites g defsPerNode variable) (phiSites, workList) - iterDefs g phiSites defsPerNode variable workList - -let placePhis g vMap (fMap: FakeVMap) (defSites: DefSites) domCtxt = - let defsPerNode = DefsPerNode () - Seq.append (vMap: SSAVMap).Values fMap.Values - |> Seq.iter (fun v -> - let defs = v.VData.Stmts |> Array.fold collectDefVars Set.empty - defsPerNode.[v] <- defs - defs |> Set.iter (fun d -> - if defSites.ContainsKey d then defSites.[d] <- Set.add v defSites.[d] - else defSites.[d] <- Set.singleton v)) - for KeyValue (variable, defs) in defSites do - match variable with - | SSA.TempVar (_) when defs.Count = 1 -> - (* We can safely ignore TempVars here because they are used only within a - single basic block. *) - () - | _ -> - Set.toList defs - |> iterDefs g Set.empty defsPerNode variable - |> ignore - domCtxt - -let renameDest (stack: IDStack) (dest: SSA.Variable) = - match dest.Kind with - | SSA.RegVar (_) - | SSA.TempVar (_) - | SSA.MemVar - | SSA.PCVar (_) -> - match stack.TryGetValue dest.Kind with - | false, _ -> dest.Identifier <- 0 - | true, ids -> dest.Identifier <- List.head ids - -let rec renameExpr stack = function - | SSA.Num (_) - | SSA.Undefined (_) - | SSA.FuncName (_) - | SSA.Nil -> () - | SSA.ReturnVal (_, _, v) -> renameDest stack v - | SSA.Var v -> renameDest stack v - | SSA.Load (v, _, expr) -> - renameDest stack v - renameExpr stack expr - | SSA.Store (mem, _, addr, expr) -> - renameDest stack mem - renameExpr stack addr - renameExpr stack expr - | SSA.UnOp (_, _, expr) -> - renameExpr stack expr - | SSA.BinOp (_, _, expr1, expr2) -> - renameExpr stack expr1 - renameExpr stack expr2 - | SSA.RelOp (_, _, expr1, expr2) -> - renameExpr stack expr1 - renameExpr stack expr2 - | SSA.Ite (expr1, _, expr2, expr3) -> - renameExpr stack expr1 - renameExpr stack expr2 - renameExpr stack expr3 - | SSA.Cast (_, _, expr) -> - renameExpr stack expr - | SSA.Extract (expr, _, _) -> - renameExpr stack expr - -let renameJmp stack = function - | SSA.IntraJmp _ -> () - | SSA.IntraCJmp (expr, _, _) -> - renameExpr stack expr - | SSA.InterJmp (expr) -> - renameExpr stack expr - | SSA.InterCJmp (cond, target1, target2) -> - renameExpr stack cond - renameExpr stack target1 - renameExpr stack target2 - -let introduceDef (count: VarCountMap) (stack: IDStack) (v: SSA.Variable) = - match v.Kind with - | SSA.RegVar (_) - | SSA.TempVar (_) - | SSA.MemVar - | SSA.PCVar (_) -> - count.[v.Kind] <- count.[v.Kind] + 1 - let i = count.[v.Kind] - stack.[v.Kind] <- i :: stack.[v.Kind] - v.Identifier <- i - -let renameStmt count stack = function - | SSA.LMark _ - | SSA.SideEffect _ -> () - | SSA.Jmp jmpTy -> renameJmp stack jmpTy - | SSA.Def (def, e) -> - renameExpr stack e - introduceDef count stack def - | SSA.Phi (def, _) -> - introduceDef count stack def - -let renamePhiAux (stack: IDStack) preds (parent: Vertex) = function - | SSA.Phi (def, nums) -> - let idx = - List.findIndex (fun (v: SSAVertex) -> - v.VData = parent.VData) preds - nums.[idx] <- List.head stack.[def.Kind] - | _ -> () - -let renamePhi g stack parent (succ: Vertex) = - succ.VData.Stmts - |> Array.iter (renamePhiAux stack (DiGraph.getPreds g succ) parent) - -let popStack (stack: IDStack) = function - | SSA.LMark _ - | SSA.SideEffect _ - | SSA.Jmp _ -> () - | SSA.Def (def, _) - | SSA.Phi (def, _) -> stack.[def.Kind] <- List.tail stack.[def.Kind] - -let rec rename g domTree count stack (v: Vertex) = - v.VData.Stmts |> Array.iter (renameStmt count stack) - DiGraph.getSuccs g v |> List.iter (renamePhi g stack v) - traverseChildren g domTree count stack (Map.find v domTree) - v.VData.Stmts |> Array.iter (popStack stack) - -and traverseChildren g domTree count stack = function - | child :: rest -> - rename g domTree count stack child - traverseChildren g domTree count stack rest - | [] -> () - -let renameVars g (defSites: DefSites) domCtxt = - let domTree, root = Dominator.dominatorTree domCtxt - let count = VarCountMap () - let stack = IDStack () - defSites.Keys |> Seq.iter (fun variable -> - count.[variable] <- 0 - stack.[variable] <- [0]) - rename g domTree count stack root |> ignore diff --git a/src/MiddleEnd.Tests/B2R2.MiddleEnd.Tests.fsproj b/src/MiddleEnd.Tests/B2R2.MiddleEnd.Tests.fsproj deleted file mode 100644 index b576289e..00000000 --- a/src/MiddleEnd.Tests/B2R2.MiddleEnd.Tests.fsproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - netcoreapp3.0 - false - - - - - - - - - - - - - - - - - - - diff --git a/src/MiddleEnd.Tests/CFG.Tests.fs b/src/MiddleEnd.Tests/CFG.Tests.fs deleted file mode 100644 index d135da95..00000000 --- a/src/MiddleEnd.Tests/CFG.Tests.fs +++ /dev/null @@ -1,347 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.Tests - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinGraph -open B2R2.BinEssence -open B2R2.Lens -open B2R2.BinIR.LowUIR -open B2R2.MiddleEnd -open Microsoft.VisualStudio.TestTools.UnitTesting - -module Utils = - type IRNode = Vertex - - let foldVertexNoFake m (v: IRNode) = - if v.VData.IsFakeBlock () then m - else Map.add v.VData.PPoint v m - - let foldEdge m (v1: IRNode) (v2: IRNode) e = - Map.add (v1.VData.PPoint, v2.VData.PPoint) e m - - let foldEdgeNoFake m (v1: IRNode) (v2: IRNode) e = - if v1.VData.IsFakeBlock () || v2.VData.IsFakeBlock () then m - else Map.add (v1.VData.PPoint, v2.VData.PPoint) e m - -[] -type CFGTest1 () = - - /// This is a raw x86-64 binary code generated from the following C code: - /// int foo(int a); - /// void bar(int a); - /// - /// void _start() - /// { - /// int x = 42; - /// - /// if (x * foo(1) % 42 == 0) { - /// x = 1; - /// } else { - /// x = foo(2) + x; - /// } - /// - /// bar(x); - /// } - /// - /// int foo(int a) - /// { - /// return a + 42; - /// } - /// - /// void bar(int a) - /// { - /// asm ( "mov $60, %rax" ); - /// asm ( "syscall" ); - /// } - let binary = - [| 0x55uy; 0x48uy; 0x89uy; 0xe5uy; 0x48uy; 0x83uy; 0xecuy; 0x10uy; 0xc7uy; - 0x45uy; 0xfcuy; 0x2auy; 0x00uy; 0x00uy; 0x00uy; 0xbfuy; 0x01uy; 0x00uy; - 0x00uy; 0x00uy; 0xe8uy; 0x49uy; 0x00uy; 0x00uy; 0x00uy; 0x0fuy; 0xafuy; - 0x45uy; 0xfcuy; 0x89uy; 0xc1uy; 0xbauy; 0x31uy; 0x0cuy; 0xc3uy; 0x30uy; - 0x89uy; 0xc8uy; 0xf7uy; 0xeauy; 0xc1uy; 0xfauy; 0x03uy; 0x89uy; 0xc8uy; - 0xc1uy; 0xf8uy; 0x1fuy; 0x29uy; 0xc2uy; 0x89uy; 0xd0uy; 0x6buy; 0xc0uy; - 0x2auy; 0x29uy; 0xc1uy; 0x89uy; 0xc8uy; 0x85uy; 0xc0uy; 0x75uy; 0x09uy; - 0xc7uy; 0x45uy; 0xfcuy; 0x01uy; 0x00uy; 0x00uy; 0x00uy; 0xebuy; 0x0duy; - 0xbfuy; 0x02uy; 0x00uy; 0x00uy; 0x00uy; 0xe8uy; 0x10uy; 0x00uy; 0x00uy; - 0x00uy; 0x01uy; 0x45uy; 0xfcuy; 0x8buy; 0x45uy; 0xfcuy; 0x89uy; 0xc7uy; - 0xe8uy; 0x12uy; 0x00uy; 0x00uy; 0x00uy; 0x90uy; 0xc9uy; 0xc3uy; 0x55uy; - 0x48uy; 0x89uy; 0xe5uy; 0x89uy; 0x7duy; 0xfcuy; 0x8buy; 0x45uy; 0xfcuy; - 0x83uy; 0xc0uy; 0x2auy; 0x5duy; 0xc3uy; 0x55uy; 0x48uy; 0x89uy; 0xe5uy; - 0x89uy; 0x7duy; 0xfcuy; 0x48uy; 0xc7uy; 0xc0uy; 0x3cuy; 0x00uy; 0x00uy; - 0x00uy; 0x0fuy; 0x05uy; 0x90uy; 0x5duy; 0xc3uy; |] - - let isa = ISA.Init Architecture.IntelX64 Endian.Little - let hdl = BinHandler.Init (isa, binary) - let ess = BinEssence.init hdl - let ess = Analyzer.run [ NoReturnAnalysis () ] ess - - [] - member __.``Boundary Test: Function Identification`` () = - let funcs = ess.CalleeMap.Entries - Assert.AreEqual (3, Seq.length funcs) - let expected = [ 0UL; 0x62UL; 0x71UL ] |> List.toArray - let actual = Seq.toArray funcs - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``Boundary Test: Leader Identification`` () = - let bbls = ess.BBLStore - let boundaries = bbls.Boundaries - Assert.AreEqual (8, bbls.VertexMap.Count) - [ (0x00UL, 0x19UL); (0x19UL, 0x3FUL); (0x3FUL, 0x48UL); (0x48UL, 0x52UL); - (0x52UL, 0x55UL); (0x55UL, 0x5FUL); (0x62UL, 0x71UL); (0x71UL, 0x81UL); ] - |> List.iter (fun r -> - Assert.IsTrue <| IntervalSet.contains (AddrRange r) boundaries) - - [] - member __.``Vertex Test: _start`` () = - let cfg, _ = ess.GetFunctionCFG (0x00UL) - Assert.AreEqual (9, DiGraph.getSize cfg) - let vMap = DiGraph.foldVertex cfg Utils.foldVertexNoFake Map.empty - Assert.AreEqual (6, vMap.Count) - let leaders = - [| ProgramPoint (0x00UL, 0); ProgramPoint (0x19UL, 0); - ProgramPoint (0x3FUL, 0); ProgramPoint (0x48UL, 0); - ProgramPoint (0x52UL, 0); ProgramPoint (0x55UL, 0); |] - let actual = leaders |> Array.map (fun l -> (Map.find l vMap).VData.Range) - let expected = - [| AddrRange (0x00UL, 0x19UL); AddrRange (0x19UL, 0x3FUL); - AddrRange (0x3FUL, 0x48UL); AddrRange (0x48UL, 0x52UL); - AddrRange (0x52UL, 0x55UL); AddrRange (0x55UL, 0x5FUL); |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``Edge Test: _start`` () = - let cfg, _ = ess.GetFunctionCFG (0x00UL) - let vMap = DiGraph.foldVertex cfg Utils.foldVertexNoFake Map.empty - let leaders = - [| ProgramPoint (0x00UL, 0); ProgramPoint (0x19UL, 0); - ProgramPoint (0x3FUL, 0); ProgramPoint (0x48UL, 0); - ProgramPoint (0x52UL, 0); ProgramPoint (0x55UL, 0); |] - let vertices = leaders |> Array.map (fun l -> Map.find l vMap) - let eMap = DiGraph.foldEdge cfg Utils.foldEdge Map.empty - Assert.AreEqual (11, eMap.Count) - let eMap = DiGraph.foldEdge cfg Utils.foldEdgeNoFake Map.empty - Assert.AreEqual (6, eMap.Count) - [ ProgramPoint (0x00UL, 0), ProgramPoint (0x19UL, 0); - ProgramPoint (0x19UL, 0), ProgramPoint (0x3FUL, 0); - ProgramPoint (0x19UL, 0), ProgramPoint (0x48UL, 0); - ProgramPoint (0x3FUL, 0), ProgramPoint (0x55UL, 0); - ProgramPoint (0x48UL, 0), ProgramPoint (0x52UL, 0); - ProgramPoint (0x52UL, 0), ProgramPoint (0x55UL, 0); ] - |> List.iter (fun x -> Assert.IsTrue <| Map.containsKey x eMap) - let actual = - [| cfg.FindEdgeData vertices.[0] vertices.[1] - cfg.FindEdgeData vertices.[1] vertices.[2] - cfg.FindEdgeData vertices.[1] vertices.[3] - cfg.FindEdgeData vertices.[2] vertices.[5] - cfg.FindEdgeData vertices.[3] vertices.[4] - cfg.FindEdgeData vertices.[4] vertices.[5] |] - let expected = - [| CallFallThroughEdge; InterCJmpFalseEdge; InterCJmpTrueEdge; - InterJmpEdge; CallFallThroughEdge; FallThroughEdge; |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``Vertex Test: foo`` () = - let cfg, _ = ess.GetFunctionCFG (0x62UL) - Assert.AreEqual (1, DiGraph.getSize cfg) - let vMap = DiGraph.foldVertex cfg Utils.foldVertexNoFake Map.empty - let leaders = [| ProgramPoint (0x62UL, 0) |] - let actual = leaders |> Array.map (fun l -> (Map.find l vMap).VData.Range) - let expected = [| AddrRange (0x62UL, 0x71UL) |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``Edge Test: foo`` () = - let cfg, _ = ess.GetFunctionCFG (0x62UL) - let eMap = DiGraph.foldEdge cfg Utils.foldEdge Map.empty - Assert.AreEqual (0, eMap.Count) - - [] - member __.``Vertex Test: bar`` () = - let cfg, _ = ess.GetFunctionCFG (0x71UL) - Assert.AreEqual (1, DiGraph.getSize cfg) - let vMap = DiGraph.foldVertex cfg Utils.foldVertexNoFake Map.empty - let leaders = [| ProgramPoint (0x71UL, 0) |] - let actual = leaders |> Array.map (fun l -> (Map.find l vMap).VData.Range) - let expected = [| AddrRange (0x71UL, 0x81UL) |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``Edge Test: bar`` () = - let cfg, _ = ess.GetFunctionCFG (0x71UL) - let eMap = DiGraph.foldEdge cfg Utils.foldEdge Map.empty - Assert.AreEqual (0, eMap.Count) - - [] - member __.``SSAGraph Vertex Test: _start`` () = - let cfg, root = ess.GetFunctionCFG (0x0UL) - let lens = SSALens.Init ess - let ssacfg, _ = lens.Filter (cfg, [root], ess) - Assert.AreEqual (9, DiGraph.getSize ssacfg) - -[] -type CFGTest2 () = - - /// This is a raw x86 binary code generated from the following C code: - /// static inline void *copy(void *d, const void *s, unsigned int n) { - /// asm volatile ("rep movsb" - /// : "=D" (d), - /// "=S" (s), - /// "=c" (n) - /// : "0" (d), - /// "1" (s), - /// "2" (n) - /// : "memory"); - /// return d; - /// } - /// - /// void _start(void) - /// { - /// char buf[32]; - /// copy(buf, "hello world", 32); - /// return; - /// } - let binary = - [| 0x57uy; 0x56uy; 0xb9uy; 0x20uy; 0x00uy; 0x00uy; 0x00uy; 0xe8uy; 0x18uy; - 0x00uy; 0x00uy; 0x00uy; 0x05uy; 0x34uy; 0x1euy; 0x00uy; 0x00uy; 0x83uy; - 0xecuy; 0x20uy; 0x89uy; 0xe7uy; 0x8duy; 0xb0uy; 0xe8uy; 0xe1uy; 0xffuy; - 0xffuy; 0xf3uy; 0xa4uy; 0x83uy; 0xc4uy; 0x20uy; 0x5euy; 0x5fuy; 0xc3uy; - 0x8buy; 0x04uy; 0x24uy; 0xc3uy; |] - - let isa = ISA.Init Architecture.IntelX86 Endian.Little - let hdl = BinHandler.Init (isa, binary) - let ess = BinEssence.init hdl - let ess = Analyzer.run [ NoReturnAnalysis () ] ess - - [] - member __.``Boundary Test: Function Identification`` () = - let funcs = ess.CalleeMap.Entries - Assert.AreEqual (2, Seq.length funcs) - let expected = [ 0UL; 0x24UL ] |> List.toArray - let actual = Seq.toArray funcs - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``Boundary Test: Leader Identification`` () = - let bbls = ess.BBLStore - let boundaries = bbls.Boundaries - Assert.AreEqual (7, bbls.VertexMap.Count) - [ (0x00UL, 0x0CUL); (0x0CUL, 0x1CUL); (0x1CUL, 0x1EUL); (0x1CUL, 0x1EUL); - (0x1CUL, 0x1EUL); (0x1EUL, 0x24UL); (0x24UL, 0x28UL); ] - |> List.iter (fun r -> - IntervalSet.findAll (AddrRange r) boundaries - |> List.isEmpty |> not |> Assert.IsTrue) - - [] - member __.``Vertex Test: _start`` () = - let cfg, _ = ess.GetFunctionCFG (0x00UL) - Assert.AreEqual (7, DiGraph.getSize cfg) - let vMap = DiGraph.foldVertex cfg Utils.foldVertexNoFake Map.empty - let leaders = - [| ProgramPoint (0x00UL, 0); ProgramPoint (0x0CUL, 0); - ProgramPoint (0x1CUL, 0); ProgramPoint (0x1CUL, 2); - ProgramPoint (0x1CUL, 8); ProgramPoint (0x1EUL, 0) |] - let actual = - leaders - |> Array.map (fun l -> - match (Map.find l vMap).VData.GetLastStmt () with - | IEMark _ -> 0 - | InterJmp _ -> 1 - | InterCJmp _ -> 2 - | Jmp _ -> 3 - | CJmp _ -> 4 - | _ -> -1) - let expected = - [| 1; 0; 4; 1; 1; 1 |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``Edge Test: _start`` () = - let cfg, _ = ess.GetFunctionCFG (0x00UL) - let vMap = DiGraph.foldVertex cfg Utils.foldVertexNoFake Map.empty - let leaders = - [| ProgramPoint (0x00UL, 0); ProgramPoint (0x0CUL, 0); - ProgramPoint (0x1CUL, 0); ProgramPoint (0x1CUL, 2); - ProgramPoint (0x1CUL, 8); ProgramPoint (0x1EUL, 0) |] - let vertices = leaders |> Array.map (fun l -> Map.find l vMap) - let eMap = DiGraph.foldEdge cfg Utils.foldEdge Map.empty - Assert.AreEqual (8, eMap.Count) - let eMap = DiGraph.foldEdge cfg Utils.foldEdgeNoFake Map.empty - Assert.AreEqual (6, eMap.Count) - [ (ProgramPoint (0x00UL, 0), ProgramPoint (0x0CUL, 0)); - (ProgramPoint (0x0CUL, 0), ProgramPoint (0x1CUL, 0)); - (ProgramPoint (0x1CUL, 0), ProgramPoint (0x1CUL, 2)); - (ProgramPoint (0x1CUL, 0), ProgramPoint (0x1CUL, 8)); - (ProgramPoint (0x1CUL, 2), ProgramPoint (0x1CUL, 0)); - (ProgramPoint (0x1CUL, 8), ProgramPoint (0x1EUL, 0)); ] - |> List.iter (fun x -> Assert.IsTrue <| Map.containsKey x eMap) - let actual = - [| cfg.FindEdgeData vertices.[0] vertices.[1] - cfg.FindEdgeData vertices.[1] vertices.[2] - cfg.FindEdgeData vertices.[2] vertices.[3] - cfg.FindEdgeData vertices.[2] vertices.[4] - cfg.FindEdgeData vertices.[3] vertices.[2] - cfg.FindEdgeData vertices.[4] vertices.[5] |] - let expected = - [| CallFallThroughEdge; FallThroughEdge; IntraCJmpFalseEdge; - IntraCJmpTrueEdge; InterJmpEdge; InterJmpEdge |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``DisasmLens Test: _start`` () = - let cfg, root = ess.GetFunctionCFG (0x00UL) - let lens = DisasmLens.Init ess - let cfg, _ = lens.Filter (cfg, [root], ess) - Assert.AreEqual (3, DiGraph.getSize cfg) - let vMap = DiGraph.foldVertex cfg (fun m v -> - Map.add v.VData.PPoint.Address v m) Map.empty - let leaders = [| 0x00UL; 0x1CUL; 0x1EUL |] - let vertices = leaders |> Array.map (fun l -> Map.find l vMap) - let disasmLens = [| 8; 1; 4 |] - Array.zip vertices disasmLens - |> Array.iter (fun (v, len) -> - Assert.AreEqual (len, v.VData.Disassemblies.Length)) - let eMap = DiGraph.foldEdge cfg (fun m v1 v2 e -> - let key = v1.VData.PPoint.Address, v2.VData.PPoint.Address - Map.add key e m) Map.empty - Assert.AreEqual (3, eMap.Count) - let actual = - [| DiGraph.findEdgeData cfg vertices.[0] vertices.[1] - DiGraph.findEdgeData cfg vertices.[1] vertices.[1] - DiGraph.findEdgeData cfg vertices.[1] vertices.[2] |] - let expected = - [| FallThroughEdge; InterJmpEdge; InterJmpEdge |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``SSAGraph Vertex Test: _start`` () = - let cfg, root = ess.GetFunctionCFG (0x0UL) - let lens = SSALens.Init ess - let ssacfg, _ = lens.Filter (cfg, [root], ess) - Assert.AreEqual (7, DiGraph.getSize ssacfg) diff --git a/src/MiddleEnd/Analyzer.fs b/src/MiddleEnd/Analyzer.fs deleted file mode 100644 index b941aff9..00000000 --- a/src/MiddleEnd/Analyzer.fs +++ /dev/null @@ -1,43 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.Analyzer - -let run analyses ess = - #if DEBUG - let startTime = System.DateTime.Now - #endif - let ess = - analyses - |> List.fold (fun ess (analysis: IAnalysis) -> - #if DEBUG - printfn "[*] %s started." analysis.Name - #endif - analysis.Run ess) ess - #if DEBUG - let endTime = System.DateTime.Now - endTime.Subtract(startTime).TotalSeconds - |> printfn "[*] All done in %f sec." - #endif - ess diff --git a/src/MiddleEnd/B2R2.MiddleEnd.fsproj b/src/MiddleEnd/B2R2.MiddleEnd.fsproj deleted file mode 100644 index f9cb28c7..00000000 --- a/src/MiddleEnd/B2R2.MiddleEnd.fsproj +++ /dev/null @@ -1,26 +0,0 @@ - - - - netstandard2.1 - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/MiddleEnd/BranchRecovery.fs b/src/MiddleEnd/BranchRecovery.fs deleted file mode 100644 index 16bf4b12..00000000 --- a/src/MiddleEnd/BranchRecovery.fs +++ /dev/null @@ -1,407 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd - -open B2R2 -open B2R2.BinFile -open B2R2.FrontEnd -open B2R2.BinIR -open B2R2.BinIR.SSA -open B2R2.BinGraph -open B2R2.BinEssence -open B2R2.Lens -open B2R2.DataFlow - -type IndirectBranchPattern = - | GOTIndexed of insAddr: Addr * baseAddr: Addr * indexAddr: Addr * rt: RegType - | FixedTab of insAddr: Addr * indexAddr: Addr * rt: RegType - | ConstAddr of insAddr: Addr * targetAddr: Addr - | UnknownFormat - -module private BranchRecoveryHelper = - let filterOutLinkageTables hdl calleeAddrs = - let tabAddrs = - hdl.FileInfo.GetLinkageTableEntries () - |> Seq.map (fun ent -> ent.TrampolineAddress) - |> Set.ofSeq - calleeAddrs - |> List.filter (fun addr -> not <| Set.contains addr tabAddrs) - - let rec computeFunctionBoundary acc = function - | [] -> acc - | [ addr ] -> Map.add addr (addr, 0UL) acc - | addr :: next :: addrs -> - let acc = Map.add addr (addr, next) acc - computeFunctionBoundary acc (next :: addrs) - - let computeCalleeAddrs ess = - ess.CalleeMap.Callees - |> Seq.choose (fun callee -> callee.Addr) - |> Seq.toList - |> filterOutLinkageTables ess.BinHandler - |> List.sort - - let hasIndirectBranch cfg = - DiGraph.foldVertex cfg (fun acc (v: Vertex) -> - (not <| v.VData.IsFakeBlock () && v.VData.HasIndirectBranch) - || acc) false - - let extractIndirectBranches cfg = - DiGraph.foldVertex cfg (fun acc (v: Vertex) -> - let len = v.VData.InsInfos.Length - if not <| v.VData.IsFakeBlock () - && v.VData.HasIndirectBranch - && len > 0 - then - let lastIns = v.VData.InsInfos.[len - 1].Instruction - let isCall = lastIns.IsCall () - (lastIns.Address, v.VData.GetLastStmt (), isCall) :: acc - else acc) [] - - let rec simplifyBinOp = function - | BinOp (BinOpType.ADD, _, Num v1, Num v2) -> Num (BitVector.add v1 v2) - | BinOp (BinOpType.SUB, _, Num v1, Num v2) -> Num (BitVector.sub v1 v2) - | BinOp (BinOpType.MUL, _, Num v1, Num v2) -> Num (BitVector.mul v1 v2) - | BinOp (BinOpType.ADD, rt, Num v1, BinOp (BinOpType.ADD, _, Num v2, e)) - | BinOp (BinOpType.ADD, rt, Num v1, BinOp (BinOpType.ADD, _, e, Num v2)) - | BinOp (BinOpType.ADD, rt, BinOp (BinOpType.ADD, _, Num v2, e), Num v1) - | BinOp (BinOpType.ADD, rt, BinOp (BinOpType.ADD, _, e, Num v2), Num v1) -> - simplifyBinOp (BinOp (BinOpType.ADD, rt, Num (BitVector.add v1 v2), e)) - | e -> e - - let simplifyExtract = function - | Extract (Cast (CastKind.ZeroExt, _, e'), rt, 0) as e -> - if AST.typeOf e' = rt then e' else e - | e -> e - - let rec extractExp cpstate expr = - match expr with - | Num _ -> expr - | Var v -> - match CPState.findReg cpstate v with - | Const bv -> Num bv - | PCThunk bv -> Num bv - | GOT bv -> Num bv - | _ -> - match Map.tryFind v cpstate.SSAEdges.Defs with - | Some (Def (_, e)) -> extractExp cpstate e - | _ -> expr - | Load (mem, rt, addr) -> - match extractExp cpstate addr with - | Num bv -> - let addr = BitVector.toUInt64 bv - match CPState.findMem cpstate mem rt addr with - | Const bv -> Num bv - | PCThunk bv -> Num bv - | GOT bv -> Num bv - | _ -> Load (mem, rt, Num bv) - | expr -> Load (mem, rt, expr) - | UnOp (op, rt, e) -> - let e = extractExp cpstate e - UnOp (op, rt, e) - | BinOp (op, rt, e1, e2) -> - let e1 = extractExp cpstate e1 - let e2 = extractExp cpstate e2 - simplifyBinOp (BinOp (op, rt, e1, e2)) - | RelOp (op, rt, e1, e2) -> - let e1 = extractExp cpstate e1 - let e2 = extractExp cpstate e2 - RelOp (op, rt, e1, e2) - | Ite (e1, rt, e2, e3) -> - let e1 = extractExp cpstate e1 - let e2 = extractExp cpstate e2 - let e3 = extractExp cpstate e3 - Ite (e1, rt, e2, e3) - | Cast (op, rt, e) -> - let e = extractExp cpstate e - Cast (op, rt, e) - | Extract (e, rt, pos) -> - let e = extractExp cpstate e - simplifyExtract (Extract (e, rt, pos)) - | _ -> expr - - let computeIndexAddr = function - | BinOp (BinOpType.ADD, _, Num idx, _) - | BinOp (BinOpType.ADD, _, _, Num idx) - | Num idx -> Some (BitVector.toUInt64 idx) - | _ -> None - - let computeCallInfo insAddr = function - | Num addr -> ConstAddr (insAddr, BitVector.toUInt64 addr) - | _ -> UnknownFormat - - let computeJmpInfo insAddr = function - | BinOp (BinOpType.ADD, _, Load (_, t, idxExpr), Num tbase) - | BinOp (BinOpType.ADD, _, Num tbase, Load (_, t, idxExpr)) - | BinOp (BinOpType.ADD, _, Cast (_, _, Load (_, t, idxExpr)), Num tbase) - | BinOp (BinOpType.ADD, _, Num tbase, Cast (_, _, Load (_, t, idxExpr))) -> - match computeIndexAddr idxExpr with - | Some tindex -> GOTIndexed (insAddr, BitVector.toUInt64 tbase, tindex, t) - | None -> UnknownFormat - | Load (_, t, (BinOp (BinOpType.ADD, _, Num i, _))) - | Load (_, t, (BinOp (BinOpType.ADD, _, _, Num i))) -> - FixedTab (insAddr, BitVector.toUInt64 i, t) - | Num addr -> ConstAddr (insAddr, BitVector.toUInt64 addr) - | _ -> UnknownFormat - - let computeIndBranchInfo cpstate insAddr isCall exp = - let exp = extractExp cpstate exp - //printfn "%x: %s %A" insAddr (Pp.expToString exp) isCall - if isCall then computeCallInfo insAddr exp - else computeJmpInfo insAddr exp - - let inline constIndBranchInfo host targets = - { HostFunctionAddr = host; TargetAddresses = targets; JumpTableInfo = None } - - let inline tblIndBranchInfo host targets bAddr sAddr eAddr rt = - let range = AddrRange (sAddr, eAddr) - let tbl = Some <| JumpTableInfo.Init bAddr range rt - { HostFunctionAddr = host; TargetAddresses = targets; JumpTableInfo = tbl } - - let partitionIndBranchInfo entry constBranches tblBranches needCPMap lst = - lst - |> List.fold (fun (constBranches, tblBranches) info -> - match info with - | ConstAddr (b, t) -> - if t <> 0UL then - let info = constIndBranchInfo entry (Set.singleton t) - Map.add b info constBranches, tblBranches - else constBranches, tblBranches - | GOTIndexed (insAddr, bAddr, iAddr, rt) -> - let info = tblIndBranchInfo entry Set.empty bAddr iAddr (iAddr + 1UL) rt - constBranches, Map.add insAddr info tblBranches - | FixedTab (insAddr, iAddr, rt) -> - let info = tblIndBranchInfo entry Set.empty 0UL iAddr (iAddr + 1UL) rt - constBranches, Map.add insAddr info tblBranches - | _ -> constBranches, tblBranches - ) (constBranches, tblBranches), needCPMap - - /// Read jump targets from a jump table. - let rec readTargets ess fStart fEnd blockAddr baseAddr maxAddr startAddr rt targets = - let hdl = (ess: BinEssence).BinHandler - match maxAddr with - | Some maxAddr when startAddr >= maxAddr -> targets, startAddr, ess - | _ -> - if hdl.FileInfo.IsValidAddr startAddr then - let size = RegType.toByteWidth rt - match BinHandler.TryReadInt (hdl, startAddr, size) with - | None -> targets, startAddr, ess - | Some offset -> - let target = baseAddr + uint64 offset - if target >= fStart && target <= fEnd then - match BinEssence.addEdge ess blockAddr target IndirectJmpEdge with - | Ok (ess', hasNewIndirectJump) -> - let targets = Set.add target targets - let nextAddr = startAddr + uint64 size - if not hasNewIndirectJump then - readTargets ess' fStart fEnd blockAddr baseAddr maxAddr nextAddr rt targets - else targets, nextAddr, ess' - | Error _ -> targets, startAddr, ess - else targets, startAddr, ess - else targets, startAddr, ess - - let getMaxAddr tableAddrs ess insAddr startAddr maxAddr = - match Map.tryFind insAddr ess.IndirectBranchMap with - | Some ({ JumpTableInfo = Some info }) -> - tableAddrs |> Set.remove info.JTRange.Min - | _ -> tableAddrs - |> Set.partition (fun addr -> addr <= startAddr) - |> snd - |> fun s -> - match Set.isEmpty s, maxAddr with - | true, None -> None - | false, None -> Set.minElement s |> Some - | true, Some _ -> maxAddr - | false, Some fromAnalysis -> - let fromApp = Set.minElement s - min fromAnalysis fromApp |> Some - - let getBlockAddr (ess: BinEssence) insAddr = - let v = ess.FindVertex insAddr |> Option.get - v.VData.PPoint.Address - - let computeTableAddrs ess = - ess.IndirectBranchMap - |> Map.fold (fun acc _ indInfo -> - match indInfo.JumpTableInfo with - | None -> acc - | Some info -> Set.add info.JTRange.Min acc - ) Set.empty - - let inline accJmpTableInfo acc targets entry insAddr bAddr sAddr eAddr t = - if Set.isEmpty targets then acc - else - let info = tblIndBranchInfo entry targets bAddr sAddr eAddr t - match Map.tryFind insAddr acc with - | None -> Map.add insAddr info acc - | Some info' -> if info = info' then acc else Map.add insAddr info acc - - let checkDefinedTable ess insAddr sAddr = - ess.IndirectBranchMap - |> Map.exists (fun addr indInfo -> - match indInfo.JumpTableInfo with - | None -> false - | Some info -> sAddr = info.JTRange.Min && insAddr <> addr) - - let inferGOTIndexedBranches ess boundaries oldTableBranches tableBranches constBranches needCPMap = - let tableAddrs = computeTableAddrs ess - let rec infer ess acc needCPMap = function - | [ (insAddr, { HostFunctionAddr = entry ; JumpTableInfo = Some i }) ] -> - let bAddr = i.JTBaseAddr - let t = i.JTEntrySize - if checkDefinedTable ess insAddr i.JTRange.Min then ess, acc, needCPMap - else - let sAddr = i.JTRange.Min - let lb, ub = Map.find entry boundaries (* function boundaries *) - let max = getMaxAddr tableAddrs ess insAddr sAddr None - let block = getBlockAddr ess insAddr - let targets, eAddr, ess = - readTargets ess lb ub block bAddr max sAddr t Set.empty - let acc = accJmpTableInfo acc targets lb insAddr bAddr sAddr eAddr t - let hasChanged = - match Map.tryFind insAddr oldTableBranches, Map.tryFind insAddr acc with - | None, None -> false - | Some info, Some info' -> - info <> info' - | _ -> true - let needCPMap = - if hasChanged then Map.add entry true needCPMap else needCPMap - ess, acc, needCPMap - | (insAddr, { HostFunctionAddr = entry ; JumpTableInfo = Some i1 }) :: - (((_, { JumpTableInfo = Some i2 }) :: _) as next) -> - let bAddr = i1.JTBaseAddr - let t = i1.JTEntrySize - if checkDefinedTable ess insAddr i1.JTRange.Min then - infer ess acc needCPMap next - else - let s1 = i1.JTRange.Min - let s2 = i2.JTRange.Min - let lb, ub = Map.find entry boundaries - let max = getMaxAddr tableAddrs ess insAddr s1 (Some s2) - let block = getBlockAddr ess insAddr - let targets, eAddr, ess = - readTargets ess lb ub block bAddr max s1 t Set.empty - let acc = accJmpTableInfo acc targets lb insAddr bAddr s1 eAddr t - let hasChanged = - match Map.tryFind insAddr oldTableBranches, Map.tryFind insAddr acc with - | None, None -> false - | Some info, Some info' -> - info <> info' - | _ -> true - let needCPMap = - if hasChanged then Map.add entry true needCPMap else needCPMap - infer ess acc needCPMap next - | _ -> ess, acc, needCPMap - tableBranches - |> Map.fold (fun acc insAddr info -> (insAddr, info) :: acc) [] - |> List.sortBy (fun (_, ind) -> - let info = Option.get ind.JumpTableInfo - info.JTRange.Min) - |> infer ess constBranches needCPMap - - let analyzeIndirectBranch ssaCFG cpstate entry constBranches tblBranches needCPMap = - extractIndirectBranches ssaCFG - |> List.map (fun (insAddr, stmt, isCall) -> - match stmt with - | Jmp (InterJmp exp) -> computeIndBranchInfo cpstate insAddr isCall exp - | _ -> UnknownFormat) - |> partitionIndBranchInfo entry constBranches tblBranches needCPMap - - let analyzeBranches ess ((constBranches, tblBranches), needCPMap) addr = - match Map.tryFind addr needCPMap with - | None | Some true -> - let needCPMap = Map.add addr false needCPMap - let irCFG, irRoot = (ess: BinEssence).GetFunctionCFG (addr, false) - if hasIndirectBranch irCFG then - let lens = SSALens.Init ess - let ssaCFG, ssaRoot = lens.Filter (irCFG, [irRoot], ess) - let cp = ConstantPropagation (ess.BinHandler, ssaCFG) - let cpstate = cp.Compute (List.head ssaRoot) - analyzeIndirectBranch - ssaCFG cpstate addr constBranches tblBranches needCPMap - else (constBranches, tblBranches), needCPMap - | _ -> (constBranches, tblBranches), needCPMap - - let toBranchInfo indMap = - indMap - |> Map.fold (fun (constBranches, tblBranches) iAddr indInfo -> - match indInfo.JumpTableInfo with - | Some _ -> constBranches, Map.add iAddr indInfo tblBranches - | None -> - Map.add iAddr indInfo constBranches, tblBranches) (Map.empty, Map.empty) - - let inferJumpTableRange ess callees oldTblBranches (constBranches, tblBranches) needCPMap = - let boundaries = computeFunctionBoundary Map.empty callees - inferGOTIndexedBranches ess boundaries oldTblBranches tblBranches constBranches needCPMap - - let calculateTable ess = - let callees = computeCalleeAddrs ess - let constBranches, tblBranches = - toBranchInfo ess.IndirectBranchMap - let ess, indmap, _ = - ((constBranches, tblBranches), Map.empty) - ||> inferJumpTableRange ess callees tblBranches - BinEssence.addIndirectBranchMap ess indmap - - let filterCalleeAddrs isTarget addrs = - match isTarget with - | Some isTarget -> addrs |> List.filter isTarget - | None -> addrs - - let rec recover (noReturn: IAnalysis) ess needCPMap isTarget = - let ess = noReturn.Run ess - let callees = computeCalleeAddrs ess |> filterCalleeAddrs isTarget - let indmap = ess.IndirectBranchMap - let constBranches, tblBranches = toBranchInfo indmap - let ess, indmap', needCPMap = - callees - |> List.fold (analyzeBranches ess) - ((constBranches, tblBranches), needCPMap) - ||> inferJumpTableRange ess callees tblBranches - let indmap' = Map.fold (fun acc k v -> Map.add k v acc) indmap indmap' - if indmap <> indmap' then - let ess = BinEssence.addIndirectBranchMap ess indmap' -#if DEBUG - printfn "[*] Go to the next phase ..." -#endif - recover noReturn ess needCPMap isTarget - else ess - -type BranchRecovery (enableNoReturn) = - let noReturn = - if enableNoReturn then NoReturnAnalysis () :> IAnalysis - else NoAnalysis () :> IAnalysis - - member __.CalculateTable ess = - BranchRecoveryHelper.calculateTable ess - - member __.RunWith ess isTarget = - BranchRecoveryHelper.recover noReturn ess Map.empty (Some isTarget) - - interface IAnalysis with - member __.Name = "Indirect Branch Recovery" - - member __.Run ess = - BranchRecoveryHelper.recover noReturn ess Map.empty None diff --git a/src/MiddleEnd/ConditionRetriever.fs b/src/MiddleEnd/ConditionRetriever.fs deleted file mode 100644 index b442981c..00000000 --- a/src/MiddleEnd/ConditionRetriever.fs +++ /dev/null @@ -1,217 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinIR -open B2R2.BinIR.SSA -open B2R2.BinGraph -open B2R2.BinEssence -open B2R2.Lens - -/// How do we compare vars? For example, in x86, there are two comparison -/// instructions: CMP vs. TEST. -type ComparisonKind = - | CompareAfterSubtract - | CompareAfterAnd - -/// Intermediate information about a comparison instruction. -type IntermediateComparisonInfo = ComparisonKind * Expr * BitVector - -/// Final information about a comparison instruction. -type ComparisonInfo = RelOpType * Expr * BitVector - -/// Retrieve a high-level condition from a given condition expression pattern. -[] -type ConditionRetriever () = - /// Find the corresponding comparison instruction from the given variable, and - /// return its operands. - abstract member FindComparison: - BinEssence - -> Vertex - -> Variable - -> IntermediateComparisonInfo option - - /// Pattern 1: CF (or ZF). - abstract member RetrievePattern1: - Variable -> IntermediateComparisonInfo -> ComparisonInfo option - - /// Pattern 2: (CF | ZF). - abstract member RetrievePattern2: - IntermediateComparisonInfo -> ComparisonInfo option - - /// Pattern 3: (ZF | (OF <> SF)). - abstract member RetrievePattern3: - IntermediateComparisonInfo -> ComparisonInfo option - - /// Pattern 4: (OF <> SF). - abstract member RetrievePattern4: - IntermediateComparisonInfo -> ComparisonInfo option - - /// Pattern 5: ((not ZF) & (OF = SF)). (negation of pattern 3) - abstract member RetrievePattern5: - IntermediateComparisonInfo -> ComparisonInfo option - - /// Pattern 6: (OF = SF). (negation of pattern 4) - abstract member RetrievePattern6: - IntermediateComparisonInfo -> ComparisonInfo option - - /// Find an address where myVar is defined. - member __.FindAddr myVar addr stmts = - match stmts with - | Def (v, _) :: _ when myVar = v -> addr - | Def (v, Num bv) :: stmts -> - if Variable.IsPC v then - __.FindAddr myVar (BitVector.toUInt64 bv) stmts - else - __.FindAddr myVar addr stmts - | _ :: stmts -> __.FindAddr myVar addr stmts - | [] -> addr - - /// Retrieve a condition based on the patterns defined in WYSINWYX: What You - /// See Is Not What You eXecute p. 24. - member __.Retrieve app vertex condExpr = - match condExpr with - | RelOp (RelOpType.EQ, 1, e, Num bv) -> - let n = BitVector.toUInt64 bv - if n = 0UL then - __.Retrieve app vertex e - |> Option.bind ConditionRetriever.Negate - elif n = 1UL then __.Retrieve app vertex e - else Utils.impossible () - | Var v -> - __.FindComparison app vertex v |> Option.bind (__.RetrievePattern1 v) - | BinOp (BinOpType.OR, 1, Var v, Var _) -> - __.FindComparison app vertex v |> Option.bind __.RetrievePattern2 - | BinOp (BinOpType.OR, 1, Var v, - RelOp (RelOpType.NEQ, _, Var _, Var _)) -> - __.FindComparison app vertex v |> Option.bind __.RetrievePattern3 - | RelOp (RelOpType.NEQ, 1, Var v, Var _) -> - __.FindComparison app vertex v |> Option.bind __.RetrievePattern4 - | BinOp (BinOpType.AND, 1, RelOp (RelOpType.EQ, _, Var v, Num bv), - RelOp (RelOpType.EQ, _, Var _, Var _)) -> - if BitVector.toUInt64 bv = 0UL then - __.FindComparison app vertex v |> Option.bind __.RetrievePattern5 - else Utils.impossible () - | RelOp (RelOpType.EQ, 1, Var v, Var _) -> - __.FindComparison app vertex v |> Option.bind __.RetrievePattern6 - | _ -> None - - static member Negate = function - | (RelOpType.EQ, v, bv) -> Some (RelOpType.NEQ, v, bv) - | (RelOpType.NEQ, v, bv) -> Some (RelOpType.EQ, v, bv) - | (RelOpType.GT, v, bv) -> Some (RelOpType.LE, v, bv) - | (RelOpType.GE, v, bv) -> Some (RelOpType.LT, v, bv) - | (RelOpType.SGT, v, bv) -> Some (RelOpType.SLE, v, bv) - | (RelOpType.SGE, v, bv) -> Some (RelOpType.SLT, v, bv) - | (RelOpType.LT, v, bv) -> Some (RelOpType.GE, v, bv) - | (RelOpType.LE, v, bv) -> Some (RelOpType.GT, v, bv) - | (RelOpType.SLT, v, bv) -> Some (RelOpType.SGE, v, bv) - | (RelOpType.SLE, v, bv) -> Some (RelOpType.SGT, v, bv) - | _ -> None - - static member Init (isa: ISA) = - match isa.Arch with - | Arch.IntelX86 - | Arch.IntelX64 -> IntelConditionRetriever () :> ConditionRetriever - | _ -> DefaultRetriever () :> ConditionRetriever - -and DefaultRetriever () = - inherit ConditionRetriever () - override __.FindComparison _ _ _ = None - override __.RetrievePattern1 _ _ = None - override __.RetrievePattern2 _ = None - override __.RetrievePattern3 _ = None - override __.RetrievePattern4 _ = None - override __.RetrievePattern5 _ = None - override __.RetrievePattern6 _ = None - -and IntelConditionRetriever () = - inherit ConditionRetriever () - - /// XXX: Two operands used to compare are first two expressions appeared at - /// specific address - let rec findTwoOperands addr isTarget first = function - | Def (v, Num bv) :: stmts -> - (* The second operand should be bitvector *) - if isTarget && Option.isSome first then Option.get first, bv - elif Variable.IsPC v then - let addr_ = BitVector.toUInt64 bv - findTwoOperands addr (addr = addr_) first stmts - else findTwoOperands addr isTarget first stmts - | Def (_, e) :: stmts -> - (* We are at a right address, but none of operands are found until now *) - if isTarget && Option.isNone first then - findTwoOperands addr isTarget (Some e) stmts - else findTwoOperands addr isTarget first stmts - | _ :: stmts -> findTwoOperands addr isTarget first stmts - | [] -> Utils.impossible () - - override __.FindComparison ess v condVar = - let ppoint = v.VData.PPoint - let stmts = Array.toList v.VData.Stmts - let addr = __.FindAddr condVar ppoint.Address stmts - let ins = ess.InstrMap.[addr].Instruction :?> Intel.IntelInstruction - match ins.Info.Opcode, ins.Info.Operands with - | Intel.Opcode.CMP, Intel.TwoOperands (Intel.OprMem _, Intel.OprImm _) - | Intel.Opcode.CMP, Intel.TwoOperands (Intel.OprReg _, Intel.OprImm _) - | Intel.Opcode.SUB, Intel.TwoOperands (Intel.OprMem _, Intel.OprImm _) - | Intel.Opcode.SUB, Intel.TwoOperands (Intel.OprReg _, Intel.OprImm _) -> - let oprnd1, oprnd2 = - findTwoOperands addr (ppoint.Address = addr) None stmts - Some (CompareAfterSubtract, oprnd1, oprnd2) - | _ -> None - - override __.RetrievePattern1 v info = - match v.Kind, info with - | RegVar (_, rid, _), (CompareAfterSubtract, e, bv) -> - if rid = Intel.Register.toRegID Intel.Register.CF then - Some (RelOpType.SLT, e, bv) - elif rid = Intel.Register.toRegID Intel.Register.ZF then - Some (RelOpType.EQ, e, bv) - else None - | _, _ -> None - - override __.RetrievePattern2 info = - match info with - | CompareAfterSubtract, e, bv -> Some (RelOpType.LE, e, bv) - | _ -> None - - override __.RetrievePattern3 info = - match info with - | CompareAfterSubtract, e, bv -> Some (RelOpType.SLE, e, bv) - | _ -> None - - override __.RetrievePattern4 info = - match info with - | CompareAfterSubtract, e, bv -> Some (RelOpType.SLT, e, bv) - | _ -> None - - override __.RetrievePattern5 info = - __.RetrievePattern3 info |> Option.bind ConditionRetriever.Negate - - override __.RetrievePattern6 info = - __.RetrievePattern4 info |> Option.bind ConditionRetriever.Negate diff --git a/src/MiddleEnd/EVMCodeCopyAnalysis.fs b/src/MiddleEnd/EVMCodeCopyAnalysis.fs deleted file mode 100644 index 0d6e88f7..00000000 --- a/src/MiddleEnd/EVMCodeCopyAnalysis.fs +++ /dev/null @@ -1,67 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.LowUIR -open B2R2.FrontEnd -open B2R2.BinEssence - -type EVMCodeCopyAnalysis () = - let findCodeCopy stmts = - stmts - |> Array.tryPick (fun stmt -> - match stmt with - | Store (_, Num dst, - BinOp (BinOpType.APP, _len, - FuncName "code", - BinOp (BinOpType.CONS, _, Num src, _, _, _), _, _)) -> - let dstAddr = BitVector.toUInt64 dst - let srcAddr = BitVector.toUInt64 src - let offset = srcAddr - dstAddr - (srcAddr, ParsingContext.InitEVM offset) |> Some - | _ -> None) - - let recoverCopiedCode (ess: BinEssence) = - ess.InstrMap - |> Seq.fold (fun ess (KeyValue (_, ins)) -> - match ins.Stmts |> findCodeCopy with - | None -> ess - | Some (addr, ctxt) -> - match ess.CalleeMap.Find addr with - | None -> - match BinEssence.addEntry ess (addr, ctxt) with - | Ok ess -> ess - | Error _ -> Utils.impossible () - | Some _ -> ess) ess - - interface IAnalysis with - member __.Name = "EVM Code Copy Analysis" - - member __.Run ess = - match ess.BinHandler.FileInfo.ISA.Arch with - | Architecture.EVM -> recoverCopiedCode ess - | _ -> ess diff --git a/src/MiddleEnd/EmulationHelper.fs b/src/MiddleEnd/EmulationHelper.fs deleted file mode 100644 index 4ae7bdfe..00000000 --- a/src/MiddleEnd/EmulationHelper.fs +++ /dev/null @@ -1,83 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.EmulationHelper - -open B2R2 -open B2R2.FrontEnd -open B2R2.ConcEval -open B2R2.BinGraph -open B2R2.BinEssence -open System.Collections.Generic - -let defZero t = Def (BitVector.zero t) -let stackAddr t = Def (BitVector.ofInt32 0x1000000 t) - -let obtainStackDef hdl = - match hdl.RegisterBay.StackPointer with - | Some r -> Some (r, hdl.ISA.WordSize |> WordSize.toRegType |> stackAddr) - | None -> None - -let obtainFramePointerDef hdl = - match hdl.RegisterBay.FramePointer with - | Some r -> Some (r, hdl.ISA.WordSize |> WordSize.toRegType |> defZero) - | None -> None - -let initRegs hdl = - [ obtainStackDef hdl; obtainFramePointerDef hdl ] - |> List.choose id - -let memoryReader hdl _pc addr = - let fileInfo = hdl.FileInfo - if fileInfo.IsValidAddr addr then - let v = BinHandler.ReadBytes (hdl, addr, 1) - Some <| v.[0] - else None - -let eval (ess: BinEssence) (blk: Vertex) st stopFn = - let visited = HashSet () - let rec evalLoop (blk: Vertex) st stopFn = - if visited.Contains blk.VData.PPoint then None - else - visited.Add blk.VData.PPoint |> ignore - let st' = - blk.VData.GetIRStatements () - |> Array.concat - |> Evaluator.evalBlock st 0 - if stopFn blk.VData.LastInstruction then Some st' - else - match ess.FindVertex st'.PC with - | None -> None - | Some v -> evalLoop v st' stopFn - evalLoop blk st stopFn - -let readMem (st: EvalState) addr endian size = - let addr = BitVector.toUInt64 addr - try st.Memory.Read st.PC addr endian size |> BitVector.toUInt64 |> Some - with InvalidMemException -> None - -let readReg st regID = - match EvalState.GetReg st regID with - | Def v -> Some v - | Undef -> None diff --git a/src/MiddleEnd/IAnalysis.fs b/src/MiddleEnd/IAnalysis.fs deleted file mode 100644 index 53635378..00000000 --- a/src/MiddleEnd/IAnalysis.fs +++ /dev/null @@ -1,37 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd - -open B2R2.BinEssence - -/// CFG analysis that we perform in the middle-end. An analysis includes -/// no-return analysis, libc start address analysis, switch-case recovery -/// analysis, etc. -type IAnalysis = - /// Name of the analysis. - abstract Name: string - - /// Run the analysis. - abstract Run: BinEssence -> BinEssence diff --git a/src/MiddleEnd/LibcAnalysis.fs b/src/MiddleEnd/LibcAnalysis.fs deleted file mode 100644 index d3ede3b5..00000000 --- a/src/MiddleEnd/LibcAnalysis.fs +++ /dev/null @@ -1,116 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinEssence -open B2R2.ConcEval -open B2R2.MiddleEnd.EmulationHelper - -module private LibcAnalysisHelper = - let retrieveAddrsForx86 (ess: BinEssence) st = - let esp = (Intel.Register.ESP |> Intel.Register.toRegID) - match EvalState.GetReg st esp with - | Def sp -> - let p1 = BitVector.add (BitVector.ofInt32 4 32) sp - let p4 = BitVector.add (BitVector.ofInt32 16 32) sp - let p5 = BitVector.add (BitVector.ofInt32 20 32) sp - let p6 = BitVector.add (BitVector.ofInt32 24 32) sp - [ readMem st p1 Endian.Little 32 - readMem st p4 Endian.Little 32 - readMem st p5 Endian.Little 32 - readMem st p6 Endian.Little 32 ] - |> List.choose id - |> List.filter (fun addr -> - ess.InstrMap.ContainsKey addr |> not) - |> function - | [] -> ess - | addrs -> - let ctxt = ess.BinHandler.DefaultParsingContext - let entries = addrs |> List.map (fun addr -> addr, ctxt) - match BinEssence.addEntries ess entries with - | Ok ess -> ess - | _ -> Utils.impossible () - | Undef -> ess - - let retrieveAddrsForx64 (ess: BinEssence) st = - [ readReg st (Intel.Register.RDI |> Intel.Register.toRegID) - readReg st (Intel.Register.RCX |> Intel.Register.toRegID) - readReg st (Intel.Register.R8 |> Intel.Register.toRegID) - readReg st (Intel.Register.R9 |> Intel.Register.toRegID) ] - |> List.choose id - |> List.map BitVector.toUInt64 - |> List.filter (fun addr -> - ess.InstrMap.ContainsKey addr |> not) - |> function - | [] -> ess - | addrs -> - let ctxt = ess.BinHandler.DefaultParsingContext - let entries = addrs |> List.map (fun addr -> addr, ctxt) - match BinEssence.addEntries ess entries with - | Ok ess -> ess - | _ -> Utils.impossible () - - let retrieveLibcStartAddresses ess = function - | None -> ess - | Some st -> - match ess.BinHandler.ISA.Arch with - | Arch.IntelX86 -> retrieveAddrsForx86 ess st - | Arch.IntelX64 -> retrieveAddrsForx64 ess st - | _ -> ess - - let analyzeLibcStartMain (ess: BinEssence) callerAddr = - match ess.FindFunctionVertex callerAddr with - | None -> ess - | Some root -> - let hdl = ess.BinHandler - let st = EvalState (memoryReader hdl, true) - let rootAddr = root.VData.PPoint.Address - let st = initRegs hdl |> EvalState.PrepareContext st 0 rootAddr - try - eval ess root st (fun last -> last.Address = callerAddr) - |> retrieveLibcStartAddresses ess - with _ -> ess - - let recoverAddrsFromLibcStartMain ess = - match ess.CalleeMap.Find "__libc_start_main" with - | Some callee -> - match List.tryExactlyOne <| Set.toList callee.Callers with - | None -> ess - | Some caller -> analyzeLibcStartMain ess caller - | None -> ess - - let recoverLibcEntries ess = - match ess.BinHandler.FileInfo.FileFormat with - | FileFormat.ELFBinary -> recoverAddrsFromLibcStartMain ess - | _ -> ess - -type LibcAnalysis () = - interface IAnalysis with - member __.Name = "LibC Analysis" - - member __.Run ess = - LibcAnalysisHelper.recoverLibcEntries ess diff --git a/src/MiddleEnd/NoAnalysis.fs b/src/MiddleEnd/NoAnalysis.fs deleted file mode 100644 index e8d495b9..00000000 --- a/src/MiddleEnd/NoAnalysis.fs +++ /dev/null @@ -1,30 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd - -type NoAnalysis () = - interface IAnalysis with - member __.Name = "No Analysis" - member __.Run ess = ess diff --git a/src/MiddleEnd/NoReturn.fs b/src/MiddleEnd/NoReturn.fs deleted file mode 100644 index 41ab10c4..00000000 --- a/src/MiddleEnd/NoReturn.fs +++ /dev/null @@ -1,279 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd - -open B2R2 -open B2R2.BinIR -open B2R2.FrontEnd -open B2R2.ConcEval -open B2R2.BinGraph -open B2R2.BinEssence -open B2R2.Lens -open B2R2.MiddleEnd.EmulationHelper - -module private NoReturnHelper = - - let isKnownNoReturnFunction = function - | "__assert_fail" - | "__stack_chk_fail" - | "abort" - | "_abort" - | "exit" - | "_exit" -> true - | _ -> false - - let hasError ess (v: Vertex) = - if v.VData.IsFakeBlock () then - let target = v.VData.PPoint.Address - match ess.CalleeMap.Find target with - | Some callee when callee.CalleeName = "error" -> true - | _ -> false - else false - - let hasNoRet noretAddrs (v: Vertex) = - if v.VData.IsFakeBlock () then - Set.contains v.VData.PPoint.Address noretAddrs - else false - - let stmtHandler (bblAddr: Addr ref) = function - | LowUIR.ISMark (addr, _) -> bblAddr := addr - | _ -> () - - let sideEffectHandler _eff st = - EvalState.NextStmt st - - let checkExitSyscall reg exitSyscall exitGrpSyscall st = - match readReg st reg with - | None -> false - | Some v -> - let n = BitVector.toInt32 v - n = exitSyscall || n = exitGrpSyscall - - let retrieveSyscallState (hdl: BinHandler) = function - | Some st when hdl.FileInfo.FileFormat = FileFormat.ELFBinary - || hdl.FileInfo.FileFormat = FileFormat.RawBinary -> - let arch = hdl.ISA.Arch - let exitSyscall = LinuxSyscall.toNumber arch LinuxSyscall.Exit - let exitGrpSyscall = LinuxSyscall.toNumber arch LinuxSyscall.ExitGroup - let reg = CallingConvention.returnRegister hdl - checkExitSyscall reg exitSyscall exitGrpSyscall st - | _ -> false - - let existSyscall cfg = - DiGraph.foldVertex cfg (fun acc (v: Vertex) -> - if v.VData.IsFakeBlock () then acc - else - match v.VData.GetLastStmt () with - | LowUIR.SideEffect SysCall -> true - | _ -> acc) false - - let findExitSyscalls hdl ess cfg (root: Vertex) = - if existSyscall cfg then - let addr = root.VData.PPoint.Address - let st = EvalState (memoryReader hdl, true) - let st = initRegs hdl |> EvalState.PrepareContext st 0 addr - let bblAddr = ref 0UL - st.Callbacks.StmtEvalEventHandler <- stmtHandler bblAddr - st.Callbacks.SideEffectEventHandler <- sideEffectHandler - try - let isExit = - eval ess root st (fun last -> last.IsInterrupt ()) - |> retrieveSyscallState hdl - if isExit then Some !bblAddr else None - with _ -> None - else None - - let collectExitSyscallFallThroughs ess cfg root edges = - let hdl = ess.BinHandler - match findExitSyscalls hdl ess cfg root with - | Some addr -> - match DiGraph.tryFindVertexBy cfg (fun (v: Vertex) -> - not (v.VData.IsFakeBlock ()) - && v.VData.PPoint.Address <= addr - && (v.VData.LastInstruction.Address - + uint64 v.VData.LastInstruction.Length) > addr) with - | None -> edges - | Some v -> - DiGraph.getSuccs cfg v |> List.fold (fun acc w -> (v, w) :: acc) edges - | None -> edges - - let checkFirstArgumentX86 st = - let esp = (Intel.Register.ESP |> Intel.Register.toRegID) - match EvalState.GetReg st esp with - | Def sp -> - let p = BitVector.add (BitVector.ofInt32 4 32) sp - match readMem st p Endian.Little 32 with - | Some v -> v <> 0UL - | None -> false - | Undef -> false - - let checkFirstArgumentX64 st = - match readReg st (Intel.Register.RDI |> Intel.Register.toRegID) with - | Some bv -> BitVector.toUInt64 bv <> 0UL - | None -> false - - let checkFirstArgument hdl = function - | None -> false - | Some st -> - match hdl.ISA.Arch with - | Arch.IntelX86 -> checkFirstArgumentX86 st - | Arch.IntelX64 -> checkFirstArgumentX64 st - | _ -> false - - let isNoReturnError ess (v: Vertex) = - let hdl = ess.BinHandler - let st = EvalState (memoryReader hdl, true) - let addr = v.VData.PPoint.Address - let lastAddr = v.VData.LastInstruction.Address - let st = initRegs hdl |> EvalState.PrepareContext st 0 addr - try - eval ess v st (fun last -> last.Address = lastAddr) - |> checkFirstArgument hdl - with _ -> false - - let collectEdgesToFallThrough cfg edges (v: Vertex) = - DiGraph.getPreds cfg v - |> List.fold (fun acc pred -> - match cfg.FindEdgeData pred v with - | RetEdge | CallFallThroughEdge -> (pred, v) :: acc - | _ -> acc) edges - - let collectErrorFallThroughs ess cfg edges = - DiGraph.foldVertex cfg (fun acc v -> - if hasError ess v then v :: acc else acc) [] - |> List.fold (fun acc v -> - if List.exists (isNoReturnError ess) <| DiGraph.getPreds cfg v then - List.fold (collectEdgesToFallThrough cfg) acc <| DiGraph.getSuccs cfg v - else acc) edges - - let collectNoRetFallThroughs cfg noretAddrs edges = - DiGraph.foldVertex cfg (fun acc v -> - if hasNoRet noretAddrs v then v :: acc else acc) [] - |> List.fold (fun edges v -> - DiGraph.getSuccs cfg v - |> List.fold (collectEdgesToFallThrough cfg) edges) edges - - let collectNoRetFallThroughEdges ess cfg root noretAddrs = - [] - |> collectExitSyscallFallThroughs ess cfg root - |> collectErrorFallThroughs ess cfg - |> collectNoRetFallThroughs cfg noretAddrs - - let rec removeUnreachables cfg root = - let g = DiGraph.clone cfg - let g = - DiGraph.foldVertex g (fun acc (v: Vertex) -> - if v.VData.IsFakeBlock () then v :: acc else acc) [] - |> List.fold DiGraph.removeVertex g - let reachables = - Traversal.foldPreorder cfg root (fun acc v -> v :: acc) [] - let cfg = - DiGraph.foldVertex g (fun acc v -> - if List.contains v reachables then acc else v :: acc) [] - |> List.map (fun v -> DiGraph.findVertexByData cfg v.VData) - |> List.fold DiGraph.removeVertex cfg - DiGraph.foldVertex cfg (fun acc v -> - let isUnreachable = - v.VData.IsFakeBlock () && DiGraph.getPreds cfg v |> List.length = 0 - if isUnreachable then v :: acc else acc) [] - |> List.fold DiGraph.removeVertex cfg - - let modifyCFG (ess: BinEssence) noretAddrs addr = - let cfg, root = ess.GetFunctionCFG (addr, false) - let cfg = - collectNoRetFallThroughEdges ess cfg root noretAddrs - |> List.fold (fun cfg (src, dst) -> DiGraph.removeEdge cfg src dst) cfg - removeUnreachables cfg root - - let isAlreadyVisited noretAddrs (v: Vertex) = - Set.contains v.VData.PPoint.Address noretAddrs - - let isNoReturn ess noretAddrs (v: Vertex) = - let addr = v.VData.PPoint.Address - if v.VData.IsExternal then isKnownNoReturnFunction v.VData.Name - else - let cfg = modifyCFG ess noretAddrs addr - cfg.FoldVertex (fun acc (v: Vertex) -> - if List.length <| DiGraph.getSuccs cfg v > 0 then acc - elif v.VData.IsFakeBlock () then - let target = v.VData.PPoint.Address - let targetV = ess.CalleeMap.Find target |> Option.get - if Set.contains target noretAddrs then acc - elif isKnownNoReturnFunction targetV.CalleeName then acc - elif targetV.CalleeName = "error" then acc - else false - elif v.VData.LastInstruction.IsInterrupt () then acc - else false) true - - let rec findLoop ess cg noretVertices = function - | [] -> noretVertices - | v :: vs -> - let noretAddrs = - noretVertices - |> Set.map (fun (v: Vertex) -> v.VData.PPoint.Address) - if isAlreadyVisited noretAddrs v then - findLoop ess cg noretVertices vs - elif isNoReturn ess noretAddrs v then - DiGraph.getPreds cg v @ vs - |> findLoop ess cg (Set.add v noretVertices) - else findLoop ess cg noretVertices vs - - let getNoReturnFunctions ess noretVertices = - let noretFuncs = ess.NoReturnInfo.NoReturnFuncs - noretVertices - |> Set.fold (fun acc (v: Vertex) -> - let addr = v.VData.PPoint.Address - match ess.CalleeMap.Find (addr) with - | None -> acc - | Some _ -> Set.add addr acc) noretFuncs - - let getNoReturnCallSites ess noretFuncs = - let callsites = ess.NoReturnInfo.NoReturnCallSites - ess.CalleeMap.Entries - |> Set.fold (fun acc addr -> - let cfg, root = ess.GetFunctionCFG (addr, false) - collectNoRetFallThroughEdges ess cfg root noretFuncs - |> List.filter (fun (src, dst) -> cfg.FindEdgeData src dst <> RetEdge) - |> List.map (fun (src, _) -> src.VData.PPoint) - |> Set.ofList - |> Set.union acc) callsites - - let findNoReturnEdges ess = - let lens = CallGraphLens.Init () - let cg, _ = lens.Filter (ess.SCFG, [], ess) - let noretFuncs = - DiGraph.foldVertex cg (fun acc v -> - if List.length <| DiGraph.getSuccs cg v = 0 then v :: acc else acc) [] - |> findLoop ess cg Set.empty - |> getNoReturnFunctions ess - let noretCallsites = getNoReturnCallSites ess noretFuncs - BinEssence.addNoReturnInfo ess noretFuncs noretCallsites - -type NoReturnAnalysis () = - interface IAnalysis with - member __.Name = "No-Return Analysis" - - member __.Run ess = - NoReturnHelper.findNoReturnEdges ess diff --git a/src/MiddleEnd/SpeculativeGapCompletion.fs b/src/MiddleEnd/SpeculativeGapCompletion.fs deleted file mode 100644 index 7af301f2..00000000 --- a/src/MiddleEnd/SpeculativeGapCompletion.fs +++ /dev/null @@ -1,114 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd - -open B2R2 -open B2R2.FrontEnd -open B2R2.BinEssence - -module private SpeculativeGapCompletionHelper = - /// XXX: Should be fixed - let findGaps (ess: BinEssence) sAddr eAddr = - ess.InstrMap.Keys - |> Seq.filter (fun addr -> addr >= sAddr && addr < eAddr) - |> Seq.sort - |> Seq.fold (fun (gaps, prevAddr) addr -> - let nextAddr = - addr + uint64 ess.InstrMap.[addr].Instruction.Length - if prevAddr >= addr then gaps, nextAddr - else AddrRange (prevAddr, addr) :: gaps, nextAddr - ) ([], sAddr) - |> fun (gaps, nextAddr) -> - if nextAddr >= eAddr then gaps - else AddrRange (nextAddr, eAddr) :: gaps - - let rec shiftUntilValid ess entries (gap: AddrRange) = - let entry = [ gap.Min, ess.BinHandler.DefaultParsingContext ] - match BinEssence.initByEntries ess.BinHandler entry with - | Ok _ -> AddrRange (gap.Min, gap.Max) :: entries - | Error _ -> - if gap.Min + 1UL = gap.Max then entries - else - let gap' = AddrRange (gap.Min + 1UL, gap.Max) - shiftUntilValid ess entries gap' - - let shiftByOne entries (gap: AddrRange) = - let nextAddr = gap.Min + 1UL - if gap.Max <= nextAddr then entries - else AddrRange (nextAddr, gap.Max) :: entries - - let shiftGaps fn gaps = - gaps |> List.fold fn [] - - let updateResults branchRecovery ess ess' = - let ctxt = ess'.BinHandler.DefaultParsingContext - let entries = - ess'.CalleeMap.Entries |> Set.toList |> List.map (fun a -> a, ctxt) - match BinEssence.addEntries ess entries with - | Ok ess -> - ess'.IndirectBranchMap - |> BinEssence.addIndirectBranchMap ess - |> (branchRecovery: BranchRecovery).CalculateTable - | Error _ -> ess - - let rec recoverGaps branchRecovery ess gaps = - match shiftGaps (shiftUntilValid ess) gaps with - | [] -> ess - | gaps -> - let ctxt = ess.BinHandler.DefaultParsingContext - let ents = gaps |> List.map (fun g -> g.Min, ctxt) - match BinEssence.initByEntries ess.BinHandler ents with - | Ok partial -> - let isTarget addr = - ess.IndirectBranchMap - |> Map.exists (fun _ { HostFunctionAddr = entry } -> entry = addr) - |> not - let ess = - isTarget - |> (branchRecovery: BranchRecovery).RunWith partial - |> updateResults branchRecovery ess - gaps - |> List.map (fun gap -> findGaps ess gap.Min gap.Max) - |> List.concat - |> recoverGaps branchRecovery ess - | Error _ -> - recoverGaps branchRecovery ess (shiftGaps shiftByOne gaps) - - let run branchRecovery ess = - ess.BinHandler.FileInfo.GetTextSections () - |> Seq.map (fun sec -> - let sAddr, eAddr = sec.Address, sec.Address + sec.Size - findGaps ess sAddr eAddr) - |> List.concat - |> recoverGaps branchRecovery ess - -type SpeculativeGapCompletion (enableNoReturn) = - let branchRecovery = BranchRecovery (enableNoReturn) - - interface IAnalysis with - member __.Name = "Speculative Gap Completion" - - member __.Run ess = - SpeculativeGapCompletionHelper.run branchRecovery ess diff --git a/src/NameMangling.Tests/B2R2.NameMangling.Tests.fsproj b/src/NameMangling.Tests/B2R2.NameMangling.Tests.fsproj deleted file mode 100644 index f412be77..00000000 --- a/src/NameMangling.Tests/B2R2.NameMangling.Tests.fsproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - netcoreapp3.0 - false - - - - - - - - - - - - - - - - - - - - diff --git a/src/NameMangling/ItaniumDemangler.fs b/src/NameMangling/ItaniumDemangler.fs deleted file mode 100644 index 393b4b6f..00000000 --- a/src/NameMangling/ItaniumDemangler.fs +++ /dev/null @@ -1,38 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.NameMangling - -module ItaniumDemangler = - let isItaniumMangled (str: string) = - str.Length > 2 && str.[0 .. 1] = "_Z" - - let demangle (str: string) = - let parser = ItaniumParser () - match parser.Run str.[2 ..] with - | FParsec.CharParsers.Success (result, _, pos) -> - if pos.Column = int64(str.Length) - 1L then - Some <| ItaniumInterpreter.interpret result - else None - | FParsec.CharParsers.Failure (_, _, _) -> None diff --git a/src/NameMangling/MSDemangler.fs b/src/NameMangling/MSDemangler.fs deleted file mode 100644 index 546f1f96..00000000 --- a/src/NameMangling/MSDemangler.fs +++ /dev/null @@ -1,39 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.NameMangling - -module MSDemangler = - let isMSMangled (str: string) = - let str = str.Trim () - str.Length <> 0 && str.StartsWith "?" && str.Contains "@" - - let demangle (str: string) = - let parser = MSParser () - match parser.Run str.[1 ..] with - | FParsec.CharParsers.Success (result, _, _) -> - let result = MSInterpreter.interpret result - Some <| result.Trim () - | FParsec.CharParsers.Failure (_, _, _) -> - None diff --git a/src/Peripheral/Assembly.Tests/B2R2.Peripheral.Assembly.Tests.fsproj b/src/Peripheral/Assembly.Tests/B2R2.Peripheral.Assembly.Tests.fsproj new file mode 100644 index 00000000..38fd915b --- /dev/null +++ b/src/Peripheral/Assembly.Tests/B2R2.Peripheral.Assembly.Tests.fsproj @@ -0,0 +1,30 @@ + + + + net5.0 + false + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Assembler.Tests/Intel.Tests.fs b/src/Peripheral/Assembly.Tests/Intel.Tests.fs similarity index 91% rename from src/Assembler.Tests/Intel.Tests.fs rename to src/Peripheral/Assembly.Tests/Intel.Tests.fs index 67a5ff25..816ba581 100644 --- a/src/Assembler.Tests/Intel.Tests.fs +++ b/src/Peripheral/Assembly.Tests/Intel.Tests.fs @@ -22,16 +22,16 @@ SOFTWARE. *) -namespace B2R2.Assembler.Tests +namespace B2R2.Peripheral.Assembly.Tests open Microsoft.VisualStudio.TestTools.UnitTesting open B2R2 -open B2R2.Assembler.Intel +open B2R2.Peripheral.Assembly.Intel [] type X86Tests () = let isa = ISA.Init Arch.IntelX86 Endian.Little - let asm = AsmParser (isa, 0UL) + let asm = IntelAsmParser (isa, 0UL) [] member __.``Basic Test``() = @@ -46,7 +46,7 @@ cond: done: ret """ - let result = asm.Run str + let result = asm.Assemble str |> Result.get let expectation = [ [| 0x3buy; 0xc9uy |] [| 0x75uy; 0x04uy |] diff --git a/src/Assembler.Tests/LowUIR.Tests.fs b/src/Peripheral/Assembly.Tests/LowUIR.Tests.fs similarity index 70% rename from src/Assembler.Tests/LowUIR.Tests.fs rename to src/Peripheral/Assembly.Tests/LowUIR.Tests.fs index 54744909..7ae7434e 100644 --- a/src/Assembler.Tests/LowUIR.Tests.fs +++ b/src/Peripheral/Assembly.Tests/LowUIR.Tests.fs @@ -22,47 +22,48 @@ SOFTWARE. *) -namespace B2R2.Assembler.Tests +namespace B2R2.Peripheral.Assembly.Tests open Microsoft.VisualStudio.TestTools.UnitTesting open B2R2 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -open B2R2.Assembler.LowUIR +open B2R2.Peripheral.Assembly.LowUIR [] type LowUIRTests () = - let regbay = Intel.IntelRegisterBay (WordSize.Bit64) :> RegisterBay + let regbay = Intel.Basis.initRegBay (WordSize.Bit64) let p = LowUIRParser (ISA.DefaultISA, regbay) let size1Num = BitVector.T let size64Num = BitVector.cast size1Num 64 [] member __.``[IntelAssemblerLowUIR] Test Register Assignment ``() = - let result = p.Run "RAX := 0x1:I64" |> Array.head + let result = p.Parse "RAX := 0x1:I64" |> Result.get |> Array.head let regID = Intel.Register.toRegID (Intel.Register.RAX) - let answer = - Put (Var(64, regID, "RAX", EmptyRegisterSet ()),Num size64Num) + let regSet = Intel.IntelRegisterSet.singleton regID + let answer = AST.put (AST.var 64 regID "RAX" regSet) (AST.num size64Num) Assert.AreEqual (answer, result) [] member __.``[IntelAssemblerLowUIR] Test IEMark ``() = - let result = p.Run "=== IEMark (pc := 1)" |> Array.head - let answer = IEMark 1UL + let result = p.Parse "} // 1" |> Result.get |> Array.head + let answer = AST.iemark 1u Assert.AreEqual (answer, result) [] member __.``[IntelAssemblerLowUIR] Test Temporary Registers``() = - let result = p.Run "T_2:I1 := 1" |> Array.head - let answer = Put (TempVar(1,2), Num size1Num) + let result = p.Parse "T_2:I1 := 1" |> Result.get |> Array.head + let answer = AST.put (AST.tmpvar 1 2) (AST.num size1Num) Assert.AreEqual (answer, result) [] member __.``[IntelAssemblerLowUIR] Test Operation in Expression``() = - let result = p.Run "RAX := (0x1:I64 - 0x1:I64)" |> Array.head + let result = + p.Parse "RAX := (0x1:I64 - 0x1:I64)" |> Result.get |> Array.head let regID = Intel.Register.toRegID (Intel.Register.RAX) + let regSet = Intel.IntelRegisterSet.singleton regID let answer = - Put (Var (64, regID, "RAX", RegisterSet.empty), - Num (BitVector.cast BitVector.F 64)) + AST.put (AST.var 64 regID "RAX" regSet) + (AST.num (BitVector.cast BitVector.F 64)) Assert.AreEqual (answer, result) - diff --git a/src/Assembler.Tests/MIPS.Tests.fs b/src/Peripheral/Assembly.Tests/MIPS.Tests.fs similarity index 96% rename from src/Assembler.Tests/MIPS.Tests.fs rename to src/Peripheral/Assembly.Tests/MIPS.Tests.fs index fcce1fed..25e1539e 100644 --- a/src/Assembler.Tests/MIPS.Tests.fs +++ b/src/Peripheral/Assembly.Tests/MIPS.Tests.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -namespace B2R2.Assembler.Tests +namespace B2R2.Peripheral.Assembly.Tests open B2R2 -open B2R2.Assembler +open B2R2.Peripheral.Assembly open Microsoft.VisualStudio.TestTools.UnitTesting -open B2R2.FrontEnd.MIPS +open B2R2.FrontEnd.BinLifter.MIPS [] type MIPSTests () = diff --git a/src/Assembler/ARM32/ARM32AsmParser.fs b/src/Peripheral/Assembly/ARM32/ARM32AsmParser.fs similarity index 98% rename from src/Assembler/ARM32/ARM32AsmParser.fs rename to src/Peripheral/Assembly/ARM32/ARM32AsmParser.fs index fbad5f49..0766068a 100644 --- a/src/Assembler/ARM32/ARM32AsmParser.fs +++ b/src/Peripheral/Assembly/ARM32/ARM32AsmParser.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -namespace B2R2.Assembler.ARM32 +namespace B2R2.Peripheral.Assembly.ARM32 open B2R2 -open B2R2.FrontEnd.ARM32 -open B2R2.Assembler.ARM32.ParserHelper +open B2R2.FrontEnd.BinLifter.ARM32 +open B2R2.Peripheral.Assembly.ARM32.ParserHelper open FParsec open System diff --git a/src/Assembler/ARM32/ARM32ParserHelper.fs b/src/Peripheral/Assembly/ARM32/ARM32ParserHelper.fs similarity index 98% rename from src/Assembler/ARM32/ARM32ParserHelper.fs rename to src/Peripheral/Assembly/ARM32/ARM32ParserHelper.fs index 7cc22372..234f29e3 100644 --- a/src/Assembler/ARM32/ARM32ParserHelper.fs +++ b/src/Peripheral/Assembly/ARM32/ARM32ParserHelper.fs @@ -22,9 +22,9 @@ SOFTWARE. *) -module B2R2.Assembler.ARM32.ParserHelper +module B2R2.Peripheral.Assembly.ARM32.ParserHelper -open B2R2.FrontEnd.ARM32 +open B2R2.FrontEnd.BinLifter.ARM32 open FParsec type AssemblyLine = diff --git a/src/Assembler/ARM32/ARM32SecondPass.fs b/src/Peripheral/Assembly/ARM32/ARM32SecondPass.fs similarity index 95% rename from src/Assembler/ARM32/ARM32SecondPass.fs rename to src/Peripheral/Assembly/ARM32/ARM32SecondPass.fs index 5eeb4dab..97b01e04 100644 --- a/src/Assembler/ARM32/ARM32SecondPass.fs +++ b/src/Peripheral/Assembly/ARM32/ARM32SecondPass.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module B2R2.Assembler.ARM32.SecondPass +module B2R2.Peripheral.Assembly.ARM32.SecondPass open B2R2 -open B2R2.FrontEnd.ARM32 -open B2R2.Assembler.ARM32 +open B2R2.FrontEnd.BinLifter.ARM32 +open B2R2.Peripheral.Assembly.ARM32 let updateOperands insAddress operandList labelToAddress = let rec doChecking operands (mapping: Map) result = diff --git a/src/Peripheral/Assembly/ARM32/B2R2.Peripheral.Assembly.ARM32.fsproj b/src/Peripheral/Assembly/ARM32/B2R2.Peripheral.Assembly.ARM32.fsproj new file mode 100644 index 00000000..10be3612 --- /dev/null +++ b/src/Peripheral/Assembly/ARM32/B2R2.Peripheral.Assembly.ARM32.fsproj @@ -0,0 +1,24 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 ARM32 assembly library. + + + + + + + + + + + + + + + + diff --git a/src/Peripheral/Assembly/ARM32/README.md b/src/Peripheral/Assembly/ARM32/README.md new file mode 100644 index 00000000..2de01718 --- /dev/null +++ b/src/Peripheral/Assembly/ARM32/README.md @@ -0,0 +1,11 @@ +# B2R2.Peripheral.Assembly.ARM32 + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.Peripheral.Assembly.ARM32 Package? + +`B2R2.Peripheral.Assembly.ARM32` includes our ARM32 assembler. diff --git a/src/Assembler/Interface/Library.fs b/src/Peripheral/Assembly/AsmInterface/AsmInterface.fs similarity index 59% rename from src/Assembler/Interface/Library.fs rename to src/Peripheral/Assembly/AsmInterface/AsmInterface.fs index 4d5a19a3..4120c126 100644 --- a/src/Assembler/Interface/Library.fs +++ b/src/Peripheral/Assembly/AsmInterface/AsmInterface.fs @@ -22,20 +22,19 @@ SOFTWARE. *) -namespace B2R2.Assembler +namespace B2R2.Peripheral.Assembly open B2R2 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinInterface -type AsmInterface (isa: ISA, startAddress) = - let handler = BinHandler.Init (isa) +type AsmInterface (hdl: BinHandle, startAddress) = - /// Parse the given string input, and assemble a list of byte arrays, where - /// each array corresponds to a binary instruction. - member __.AssembleBin asm = - match isa.Arch with + let asmParser = + match hdl.ISA.Arch with | Architecture.IntelX64 - | Architecture.IntelX86 -> Intel.AsmParser(isa, startAddress).Run asm + | Architecture.IntelX86 -> + Intel.IntelAsmParser (hdl.ISA, startAddress) :> AsmParser | Architecture.MIPS1 | Architecture.MIPS2 | Architecture.MIPS3 @@ -47,19 +46,18 @@ type AsmInterface (isa: ISA, startAddress) = | Architecture.MIPS64 | _ -> raise InvalidISAException - /// Parse the given string input, and assemble an array of IR statements. - member __.AssembleLowUIR isFromLowUIR asm = - if isFromLowUIR then - LowUIR.LowUIRParser(isa, handler.RegisterBay).Run asm - else - let bs = __.AssembleBin asm |> Array.concat - let handler = BinHandler.UpdateCode handler startAddress bs - let rec loop ctxt addr acc = - match BinHandler.TryParseInstr handler ctxt addr with - | None -> List.rev acc - | Some ins -> - let stmts = BinHandler.LiftInstr handler ins - let ctxt = ins.NextParsingContext - loop ctxt (addr + uint64 ins.Length) (stmts :: acc) - loop handler.DefaultParsingContext 0UL [] - |> Array.concat + let uirParser = LowUIR.LowUIRParser (hdl.ISA, hdl.RegisterBay) + + new (isa: ISA, startAddress) = + AsmInterface (BinHandle.Init (isa), startAddress) + + /// Parse the given assembly input, and assemble a list of byte arrays, where + /// each array corresponds to a binary instruction. + member __.AssembleBin asm = asmParser.Assemble asm + + /// Parse the given string input, and lift it to an array of LowUIR + /// statements. If the given string represents LowUIR instructions, then we + /// simply parse the assembly instructions and return the corresponding AST. + member __.LiftLowUIR isFromLowUIR asm = + if isFromLowUIR then uirParser.Parse asm + else asmParser.Lift hdl asm startAddress diff --git a/src/Peripheral/Assembly/AsmInterface/B2R2.Peripheral.Assembly.AsmInterface.fsproj b/src/Peripheral/Assembly/AsmInterface/B2R2.Peripheral.Assembly.AsmInterface.fsproj new file mode 100644 index 00000000..1194b317 --- /dev/null +++ b/src/Peripheral/Assembly/AsmInterface/B2R2.Peripheral.Assembly.AsmInterface.fsproj @@ -0,0 +1,26 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 assembly main interface. + + + + + + + + + + + + + + + + + + diff --git a/src/Peripheral/Assembly/AsmInterface/README.md b/src/Peripheral/Assembly/AsmInterface/README.md new file mode 100644 index 00000000..21d162ff --- /dev/null +++ b/src/Peripheral/Assembly/AsmInterface/README.md @@ -0,0 +1,12 @@ +# B2R2.Peripheral.Assembly.AsmInterface + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.Peripheral.Assembly.AsmInterface Package? + +`B2R2.Peripheral.Assembly.AsmInterface` provides an interface for our binary +assembly module. diff --git a/src/Assembler/Core/AsmParser.fs b/src/Peripheral/Assembly/Core/AsmParser.fs similarity index 64% rename from src/Assembler/Core/AsmParser.fs rename to src/Peripheral/Assembly/Core/AsmParser.fs index a250014c..47475d5f 100644 --- a/src/Assembler/Core/AsmParser.fs +++ b/src/Peripheral/Assembly/Core/AsmParser.fs @@ -22,9 +22,26 @@ SOFTWARE. *) -namespace B2R2.Assembler +namespace B2R2.Peripheral.Assembly + +open B2R2.FrontEnd.BinInterface /// Assembly code parser interface. -type AsmParser = - /// Run parsing from a given string, and returns binary code (in byte array). - abstract Run: string -> byte [] +[] +type AsmParser () = + /// Run parsing from a given assembly string, and assemble binary code. + abstract Assemble: string -> Result + + /// Run parsing from a given assembly string, and lift it to LowUIR code. + member __.Lift hdl asm addr = + __.Assemble asm + |> Result.bind (fun bins -> + bins + |> List.fold (fun acc bs -> + let hdl = BinHandle.UpdateCode hdl addr bs + let ins = BinHandle.ParseInstr (hdl, addr) + BinHandle.LiftInstr hdl ins :: acc + ) [] + |> List.rev + |> Array.concat + |> Ok) diff --git a/src/Peripheral/Assembly/Core/B2R2.Peripheral.Assembly.Core.fsproj b/src/Peripheral/Assembly/Core/B2R2.Peripheral.Assembly.Core.fsproj new file mode 100644 index 00000000..affd1f04 --- /dev/null +++ b/src/Peripheral/Assembly/Core/B2R2.Peripheral.Assembly.Core.fsproj @@ -0,0 +1,27 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 assembly core library. + + + + + + + + + + + + + + + + + + + diff --git a/src/Peripheral/Assembly/Core/README.md b/src/Peripheral/Assembly/Core/README.md new file mode 100644 index 00000000..f582eb29 --- /dev/null +++ b/src/Peripheral/Assembly/Core/README.md @@ -0,0 +1,12 @@ +# B2R2.Peripheral.Assembly.Core + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.Peripheral.Assembly.Core Package? + +`B2R2.Peripheral.Assembly.Core` defines basic types and values for B2R2 +assembler modules. diff --git a/src/ConcEval/Types.fs b/src/Peripheral/Assembly/Core/Utils.fs similarity index 69% rename from src/ConcEval/Types.fs rename to src/Peripheral/Assembly/Core/Utils.fs index 1b0508b4..57d16528 100644 --- a/src/ConcEval/Types.fs +++ b/src/Peripheral/Assembly/Core/Utils.fs @@ -22,17 +22,20 @@ SOFTWARE. *) -namespace B2R2.ConcEval - -open B2R2 - -/// Raised when undefined expression is encountered. -exception UndefExpException - -/// Raised when an invalid memory access. -exception InvalidMemException - -/// A value is either defined or undefined. -type EvalValue = - | Undef - | Def of BitVector +module B2R2.Peripheral.Assembly.Utils + +open FParsec + +#if DEBUG +/// This is a useful function to debug parsers. +let () (p: Parser<_,_>) label : Parser<_,_> = + fun stream -> + printfn "%A: Entering %s" stream.Position label + let reply = p stream + printfn "%A: Leaving %s (%A)" stream.Position label reply.Status + if reply.Status = ReplyStatus.Ok then printfn "%A" reply.Result else () + reply +#endif + +let pBetweenParen p = + between (pchar '(' >>. spaces) (spaces .>> pchar ')' .>> spaces) p diff --git a/src/Peripheral/Assembly/Intel/B2R2.Peripheral.Assembly.Intel.fsproj b/src/Peripheral/Assembly/Intel/B2R2.Peripheral.Assembly.Intel.fsproj new file mode 100644 index 00000000..619ed868 --- /dev/null +++ b/src/Peripheral/Assembly/Intel/B2R2.Peripheral.Assembly.Intel.fsproj @@ -0,0 +1,29 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 Intel assembly library. + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Assembler/Intel/IntelAsmMain.fs b/src/Peripheral/Assembly/Intel/IntelAsmMain.fs similarity index 97% rename from src/Assembler/Intel/IntelAsmMain.fs rename to src/Peripheral/Assembly/Intel/IntelAsmMain.fs index b051cb7e..eb502402 100644 --- a/src/Assembler/Intel/IntelAsmMain.fs +++ b/src/Peripheral/Assembly/Intel/IntelAsmMain.fs @@ -22,12 +22,13 @@ SOFTWARE. *) -module B2R2.Assembler.Intel.AsmMain +module B2R2.Peripheral.Assembly.Intel.AsmMain open System open B2R2 -open B2R2.FrontEnd.Intel -open B2R2.Assembler.Intel.AsmOpcode +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.Peripheral.Assembly.Intel.ParserHelper +open B2R2.Peripheral.Assembly.Intel.AsmOpcode type AssemblyInfo = { Index : int @@ -46,7 +47,7 @@ type UserState = { CurIndex: int } -let encodeInstruction ins ctxt = +let encodeInstruction (ins: AsmInsInfo) ctxt = match ins.Opcode with | Opcode.AAA -> aaa ctxt ins.Operands | Opcode.AAD -> aad ctxt ins.Operands @@ -331,7 +332,7 @@ let finalize arch parserState realLenArr baseAddr myIdx comp = yield! getImm imm |] | _ -> comp |> Array.map normalToByte -let assemble parserState isa (baseAddr: Addr) (instrs: InsInfo list) = +let assemble parserState isa (baseAddr: Addr) (instrs: AsmInsInfo list) = let ctxt = EncContext (isa.Arch) let components = instrs |> List.map (fun ins -> encodeInstruction ins ctxt) let maxLenArr = computeMaxLen components diff --git a/src/Assembler/Intel/IntelAsmOpcode.fs b/src/Peripheral/Assembly/Intel/IntelAsmOpcode.fs similarity index 88% rename from src/Assembler/Intel/IntelAsmOpcode.fs rename to src/Peripheral/Assembly/Intel/IntelAsmOpcode.fs index ed44b514..b161e6d8 100644 --- a/src/Assembler/Intel/IntelAsmOpcode.fs +++ b/src/Peripheral/Assembly/Intel/IntelAsmOpcode.fs @@ -22,12 +22,13 @@ SOFTWARE. *) -module internal B2R2.Assembler.Intel.AsmOpcode +module internal B2R2.Peripheral.Assembly.Intel.AsmOpcode open B2R2 -open B2R2.FrontEnd.Intel -open B2R2.Assembler.Intel.AsmPrefix -open B2R2.Assembler.Intel.AsmOperands +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.Peripheral.Assembly.Intel.ParserHelper +open B2R2.Peripheral.Assembly.Intel.AsmPrefix +open B2R2.Peripheral.Assembly.Intel.AsmOperands let no32Arch arch = if arch = Arch.IntelX86 then raise InvalidISAException else () @@ -204,13 +205,13 @@ let aaa (ctxt: EncContext) = function let aad (ctxt: EncContext) = function | NoOperand -> no64Arch ctxt.Arch; [| Normal 0xD5uy; Normal 0x0Auy |] - | OneOperand (OprImm imm) -> + | OneOperand (OprImm (imm, _)) -> no64Arch ctxt.Arch; [| Normal 0xD5uy; yield! immediate imm 8 |] | _ -> raise NotEncodableException let aam (ctxt: EncContext) = function | NoOperand -> no64Arch ctxt.Arch; [| Normal 0xD4uy; Normal 0x0Auy |] - | OneOperand (OprImm imm) -> + | OneOperand (OprImm (imm, _)) -> no64Arch ctxt.Arch; [| Normal 0xD4uy; yield! immediate imm 8 |] | _ -> raise NotEncodableException @@ -221,70 +222,70 @@ let aas (ctxt: EncContext) = function let adc (ctxt: EncContext) ins = match ins.Operands with (* Reg (fixed) - Imm (Priority 1) *) - | TwoOperands (OprReg Register.AL, OprImm imm) -> + | TwoOperands (OprReg Register.AL, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x14uy |] imm 8 - | TwoOperands (OprReg Register.AX, OprImm imm) -> + | TwoOperands (OprReg Register.AX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x15uy |] imm 16 - | TwoOperands (OprReg Register.EAX, OprImm imm) -> + | TwoOperands (OprReg Register.EAX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x15uy |] imm 32 - | TwoOperands (OprReg Register.RAX, OprImm imm) -> + | TwoOperands (OprReg Register.RAX, OprImm (imm, _)) -> no32Arch ctxt.Arch encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x15uy |] imm 32 (* Reg - Imm (Priority 0) *) - | TwoOperands (OprReg r, OprImm imm) when isReg16 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] r 0b010uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] r 0b010uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r && isInt8 imm -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] r 0b010uy imm 8 (* Mem - Imm (Priority 0) *) - | TwoOperands (Label _, OprImm imm) when isInt8 imm -> + | TwoOperands (Label _, OprImm (imm, _)) when isInt8 imm -> encLI ctxt ins 0b010uy imm 8 [||] [| 0x83uy |] - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] b s d 0b010uy imm 8 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] b s d 0b010uy imm 8 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) when isInt8 imm -> no32Arch ctxt.Arch encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] b s d 0b010uy imm 8 (* Reg - Imm (Priority 1) *) - | TwoOperands (OprReg r, OprImm imm) when isReg8 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg8 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] r 0b010uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] r 0b010uy imm 16 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] r 0b010uy imm 32 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] r 0b010uy imm 32 (* Mem - Imm (Priority 1) *) - | TwoOperands (Label _, OprImm imm) -> + | TwoOperands (Label _, OprImm (imm, _)) -> encLI ctxt ins 0b010uy imm 32 [| 0x80uy |] [| 0x81uy |] // FIXME - | TwoOperands (OprMem (b, s, d, 8), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 8), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] b s d 0b010uy imm 8 - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] b s d 0b010uy imm 16 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] b s d 0b010uy imm 32 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) -> no32Arch ctxt.Arch; encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] b s d 0b010uy imm 32 @@ -339,70 +340,70 @@ let adc (ctxt: EncContext) ins = let add (ctxt: EncContext) ins = match ins.Operands with (* Reg (fixed) - Imm (Priority 1) *) - | TwoOperands (OprReg Register.AL, OprImm imm) -> + | TwoOperands (OprReg Register.AL, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x04uy |] imm 8 - | TwoOperands (OprReg Register.AX, OprImm imm) -> + | TwoOperands (OprReg Register.AX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x05uy |] imm 16 - | TwoOperands (OprReg Register.EAX, OprImm imm) -> + | TwoOperands (OprReg Register.EAX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x05uy |] imm 32 - | TwoOperands (OprReg Register.RAX, OprImm imm) -> + | TwoOperands (OprReg Register.RAX, OprImm (imm, _)) -> no32Arch ctxt.Arch encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x05uy |] imm 32 (* Reg - Imm (Priority 0) *) - | TwoOperands (OprReg r, OprImm imm) when isReg16 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] r 0b000uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] r 0b000uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r && isInt8 imm -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] r 0b000uy imm 8 (* Mem - Imm (Priority 0) *) - | TwoOperands (Label _, OprImm imm) when isInt8 imm -> + | TwoOperands (Label _, OprImm (imm, _)) when isInt8 imm -> encLI ctxt ins 0b000uy imm 8 [||] [| 0x83uy |] - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] b s d 0b000uy imm 8 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] b s d 0b000uy imm 8 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) when isInt8 imm -> no32Arch ctxt.Arch encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] b s d 0b000uy imm 8 (* Reg - Imm (Priority 1) *) - | TwoOperands (OprReg r, OprImm imm) when isReg8 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg8 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] r 0b000uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] r 0b000uy imm 16 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] r 0b000uy imm 32 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] r 0b000uy imm 32 (* Mem - Imm (Priority 1) *) - | TwoOperands (Label _, OprImm imm) -> + | TwoOperands (Label _, OprImm (imm, _)) -> encLI ctxt ins 0b000uy imm 32 [| 0x80uy |] [| 0x81uy |] // FIXME - | TwoOperands (OprMem (b, s, d, 8), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 8), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] b s d 0b000uy imm 8 - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] b s d 0b000uy imm 16 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] b s d 0b000uy imm 32 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) -> no32Arch ctxt.Arch; encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] b s d 0b000uy imm 32 @@ -497,70 +498,70 @@ let addss (ctxt: EncContext) ins = let logAnd (ctxt: EncContext) ins = match ins.Operands with (* Reg (fixed) - Imm *) - | TwoOperands (OprReg Register.AL, OprImm imm) -> + | TwoOperands (OprReg Register.AL, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x24uy |] imm 8 - | TwoOperands (OprReg Register.AX, OprImm imm) -> + | TwoOperands (OprReg Register.AX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x25uy |] imm 16 - | TwoOperands (OprReg Register.EAX, OprImm imm) -> + | TwoOperands (OprReg Register.EAX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x25uy |] imm 32 - | TwoOperands (OprReg Register.RAX, OprImm imm) -> + | TwoOperands (OprReg Register.RAX, OprImm (imm, _)) -> no32Arch ctxt.Arch encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x25uy |] imm 32 (* Reg - Imm (Priority 0) *) - | TwoOperands (OprReg r, OprImm imm) when isReg16 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] r 0b100uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] r 0b100uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r && isInt8 imm -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] r 0b100uy imm 8 (* Mem - Imm (Priority 0) *) - | TwoOperands (Label _, OprImm imm) when isInt8 imm -> + | TwoOperands (Label _, OprImm (imm, _)) when isInt8 imm -> encLI ctxt ins 0b100uy imm 8 [||] [| 0x83uy |] - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] b s d 0b100uy imm 8 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] b s d 0b100uy imm 8 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) when isInt8 imm -> no32Arch ctxt.Arch encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] b s d 0b100uy imm 8 (* Reg - Imm (Priority 1) *) - | TwoOperands (OprReg r, OprImm imm) when isReg8 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg8 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] r 0b100uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] r 0b100uy imm 16 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] r 0b100uy imm 32 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] r 0b100uy imm 32 (* Mem - Imm (Priority 1) *) - | TwoOperands (Label _, OprImm imm) -> + | TwoOperands (Label _, OprImm (imm, _)) -> encLI ctxt ins 0b100uy imm 32 [| 0x80uy |] [| 0x81uy |] // FIXME - | TwoOperands (OprMem (b, s, d, 8), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 8), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] b s d 0b100uy imm 8 - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] b s d 0b100uy imm 16 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] b s d 0b100uy imm 32 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) -> no32Arch ctxt.Arch; encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] b s d 0b100uy imm 32 @@ -680,25 +681,25 @@ let bt (ctxt: EncContext) ins = no32Arch ctxt.Arch encMR ins ctxt.Arch ctxt.PrefNormal ctxt.RexWAndMR [| 0x0Fuy; 0xA3uy |] b s d r - | TwoOperands (OprReg r, OprImm imm) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x0Fuy; 0xBAuy |] r 0b100uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x0Fuy; 0xBAuy |] r 0b100uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x0Fuy; 0xBAuy |] r 0b100uy imm 8 - | TwoOperands (Label _, OprImm imm) -> + | TwoOperands (Label _, OprImm (imm, _)) -> encLI ctxt ins 0b100uy imm 32 [||] [| 0x0Fuy; 0xBAuy |] // FIXME - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x0Fuy; 0xBAuy |] b s d 0b100uy imm 8 - | TwoOperands (OprMem (b, s, d, 32), OprImm i) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (i, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x0Fuy; 0xBAuy |] b s d 0b100uy i 8 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) -> no32Arch ctxt.Arch encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x0Fuy; 0xBAuy |] b s d 0b100uy imm 8 @@ -800,70 +801,70 @@ let cmovz ctxt ins = cmovcc ctxt ins [| 0x0Fuy; 0x44uy |] let cmp (ctxt: EncContext) ins = match ins.Operands with (* Reg (fixed) - Imm (Priority 1) *) - | TwoOperands (OprReg Register.AL, OprImm imm) -> + | TwoOperands (OprReg Register.AL, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x3Cuy |] imm 8 - | TwoOperands (OprReg Register.AX, OprImm imm) -> + | TwoOperands (OprReg Register.AX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x3Duy |] imm 16 - | TwoOperands (OprReg Register.EAX, OprImm imm) -> + | TwoOperands (OprReg Register.EAX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x3Duy |] imm 32 - | TwoOperands (OprReg Register.RAX, OprImm imm) -> + | TwoOperands (OprReg Register.RAX, OprImm (imm, _)) -> no32Arch ctxt.Arch encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x3Duy |] imm 32 (* Reg - Imm (Priority 0) *) - | TwoOperands (OprReg r, OprImm imm) when isReg16 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] r 0b111uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] r 0b111uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r && isInt8 imm -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] r 0b111uy imm 8 (* Mem - Imm (Priority 0) *) - | TwoOperands (Label _, OprImm imm) when isInt8 imm -> + | TwoOperands (Label _, OprImm (imm, _)) when isInt8 imm -> encLI ctxt ins 0b111uy imm 8 [||] [| 0x83uy |] - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] b s d 0b111uy imm 8 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] b s d 0b111uy imm 8 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) when isInt8 imm -> no32Arch ctxt.Arch encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] b s d 0b111uy imm 8 (* Reg - Imm (Priority 1) *) - | TwoOperands (OprReg r, OprImm imm) when isReg8 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg8 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] r 0b111uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] r 0b111uy imm 16 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] r 0b111uy imm 32 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] r 0b111uy imm 32 (* Mem - Imm (Priority 1) *) - | TwoOperands (Label _, OprImm imm) -> + | TwoOperands (Label _, OprImm (imm, _)) -> encLI ctxt ins 0b111uy imm 32 [| 0x80uy |] [| 0x81uy |] // FIXME - | TwoOperands (OprMem (b, s, d, 8), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 8), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] b s d 0b111uy imm 8 - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] b s d 0b111uy imm 16 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] b s d 0b111uy imm 32 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) -> no32Arch ctxt.Arch; encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] b s d 0b111uy imm 32 @@ -1400,58 +1401,58 @@ let imul (ctxt: EncContext) ins = | TwoOperands (OprReg r, OprMem (b, s, d, 64)) when isReg64 r -> encRM ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x0Fuy; 0xAFuy |] r b s d - | ThreeOperands (OprReg r1, OprReg r2, OprImm imm) + | ThreeOperands (OprReg r1, OprReg r2, OprImm (imm, _)) when isReg16 r1 && isReg16 r2 && isInt8 imm -> encRRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x6Buy |] r1 r2 imm 8 - | ThreeOperands (OprReg r, Label _, OprImm imm) when isInt8 imm -> + | ThreeOperands (OprReg r, Label _, OprImm (imm, _)) when isInt8 imm -> encRLI ctxt ins r [| 0x6Buy |] imm 8 - | ThreeOperands (OprReg r, OprMem (b, s, d, 16), OprImm imm) + | ThreeOperands (OprReg r, OprMem (b, s, d, 16), OprImm (imm, _)) when isReg16 r && isInt8 imm -> encRMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x6Buy |] r b s d imm 8 - | ThreeOperands (OprReg r1, OprReg r2, OprImm imm) + | ThreeOperands (OprReg r1, OprReg r2, OprImm (imm, _)) when isReg32 r1 && isReg32 r2 && isInt8 imm -> encRRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x6Buy |] r1 r2 imm 8 - | ThreeOperands (OprReg r, OprMem (b, s, d, 32), OprImm imm) + | ThreeOperands (OprReg r, OprMem (b, s, d, 32), OprImm (imm, _)) when isReg32 r && isInt8 imm -> encRMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x6Buy |] r b s d imm 8 - | ThreeOperands (OprReg r1, OprReg r2, OprImm imm) + | ThreeOperands (OprReg r1, OprReg r2, OprImm (imm, _)) when isReg64 r1 && isReg64 r2 && isInt8 imm -> no32Arch ctxt.Arch encRRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x6Buy |] r1 r2 imm 8 - | ThreeOperands (OprReg r, OprMem (b, s, d, 64), OprImm imm) + | ThreeOperands (OprReg r, OprMem (b, s, d, 64), OprImm (imm, _)) when isReg64 r && isInt8 imm -> no32Arch ctxt.Arch encRMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x6Buy |] r b s d imm 8 - | ThreeOperands (OprReg r1, OprReg r2, OprImm imm) + | ThreeOperands (OprReg r1, OprReg r2, OprImm (imm, _)) when isReg16 r1 && isReg16 r2 -> encRRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x69uy |] r1 r2 imm 16 - | ThreeOperands (OprReg r, Label _, OprImm imm) -> + | ThreeOperands (OprReg r, Label _, OprImm (imm, _)) -> encRLI ctxt ins r [| 0x69uy |] imm 32 // FIXME - | ThreeOperands (OprReg r, OprMem (b, s, d, 16), OprImm imm) + | ThreeOperands (OprReg r, OprMem (b, s, d, 16), OprImm (imm, _)) when isReg16 r -> encRMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x69uy |] r b s d imm 16 - | ThreeOperands (OprReg r1, OprReg r2, OprImm imm) + | ThreeOperands (OprReg r1, OprReg r2, OprImm (imm, _)) when isReg32 r1 && isReg32 r2 -> encRRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x69uy |] r1 r2 imm 32 - | ThreeOperands (OprReg r, OprMem (b, s, d, 32), OprImm imm) + | ThreeOperands (OprReg r, OprMem (b, s, d, 32), OprImm (imm, _)) when isReg32 r -> encRMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x69uy |] r b s d imm 32 - | ThreeOperands (OprReg r1, OprReg r2, OprImm imm) + | ThreeOperands (OprReg r1, OprReg r2, OprImm (imm, _)) when isReg64 r1 && isReg64 r2 -> no32Arch ctxt.Arch encRRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x69uy |] r1 r2 imm 32 - | ThreeOperands (OprReg r, OprMem (b, s, d, 64), OprImm imm) + | ThreeOperands (OprReg r, OprMem (b, s, d, 64), OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRMI ins ctxt.Arch @@ -1534,21 +1535,9 @@ let jmp (ctxt: EncContext) ins = | OneOperand (OprDirAddr (Relative rel)) when isInt8 rel -> encD ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xEBuy |] rel 8 - | OneOperand (OprDirAddr (Relative rel)) - when isInt16 rel && ctxt.Arch = Arch.IntelX86 -> - encD ins ctxt.Arch - ctxt.Pref66 ctxt.RexNormal [| 0xE9uy |] rel 16 | OneOperand (OprDirAddr (Relative rel)) when isInt32 rel -> encD ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xE9uy |] rel 32 - | OneOperand (OprReg r) when isReg16 r -> - no64Arch ctxt.Arch (* N.S. *) - encR ins ctxt.Arch - ctxt.Pref66 ctxt.RexNormal [| 0xFFuy |] r 0b100uy - | OneOperand (OprMem (b, s, d, 16)) -> - no64Arch ctxt.Arch (* N.S. *) - encM ins ctxt.Arch - ctxt.Pref66 ctxt.RexNormal [| 0xFFuy |] b s d 0b100uy | OneOperand (OprReg r) when isReg32 r -> no64Arch ctxt.Arch (* N.S. *) encR ins ctxt.Arch @@ -1654,36 +1643,36 @@ let mov (ctxt: EncContext) ins = encRM ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x8Buy |] r b s d (* Reg - Imm (Opcode reg field) *) - | TwoOperands (OprReg r, OprImm imm) when isReg8 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg8 r -> encOI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal 0xB0uy r imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r -> encOI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal 0xB8uy r imm 16 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r -> encOI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal 0xB8uy r imm 32 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r && isInt32 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r && isInt32 imm -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0xC7uy |] r 0b000uy imm 32 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encOI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW 0xB8uy r imm 64 (* Mem - Imm *) - | TwoOperands (Label _, OprImm imm) -> + | TwoOperands (Label _, OprImm (imm, _)) -> encLI ctxt ins 0b000uy imm 32 [| 0xC6uy |] [| 0xC7uy |] // FIXME - | TwoOperands (OprMem (b, s, d, 8), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 8), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xC6uy |] b s d 0b000uy imm 8 - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xC7uy |] b s d 0b000uy imm 16 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xC7uy |] b s d 0b000uy imm 32 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) -> no32Arch ctxt.Arch; encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0xC7uy |] b s d 0b000uy imm 32 @@ -2017,70 +2006,70 @@ let not (ctxt: EncContext) ins = let logOr (ctxt: EncContext) ins = match ins.Operands with (* Reg (fixed) - Imm *) - | TwoOperands (OprReg Register.AL, OprImm imm) -> + | TwoOperands (OprReg Register.AL, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x0Cuy |] imm 8 - | TwoOperands (OprReg Register.AX, OprImm imm) -> + | TwoOperands (OprReg Register.AX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x0Duy |] imm 16 - | TwoOperands (OprReg Register.EAX, OprImm imm) -> + | TwoOperands (OprReg Register.EAX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x0Duy |] imm 32 - | TwoOperands (OprReg Register.RAX, OprImm imm) -> + | TwoOperands (OprReg Register.RAX, OprImm (imm, _)) -> no32Arch ctxt.Arch encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x0Duy |] imm 32 (* Reg - Imm (Priority 0) *) - | TwoOperands (OprReg r, OprImm imm) when isReg16 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] r 0b001uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] r 0b001uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r && isInt8 imm -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] r 0b001uy imm 8 (* Mem - Imm (Priority 0) *) - | TwoOperands (Label _, OprImm imm) when isInt8 imm -> + | TwoOperands (Label _, OprImm (imm, _)) when isInt8 imm -> encLI ctxt ins 0b001uy imm 8 [||] [| 0x83uy |] - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] b s d 0b001uy imm 8 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] b s d 0b001uy imm 8 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) when isInt8 imm -> no32Arch ctxt.Arch encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] b s d 0b001uy imm 8 (* Reg - Imm (Priority 1) *) - | TwoOperands (OprReg r, OprImm imm) when isReg8 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg8 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] r 0b001uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] r 0b001uy imm 16 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] r 0b001uy imm 32 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] r 0b001uy imm 32 (* Mem - Imm (Priority 1) *) - | TwoOperands (Label _, OprImm imm) -> + | TwoOperands (Label _, OprImm (imm, _)) -> encLI ctxt ins 0b001uy imm 32 [| 0x80uy |] [| 0x81uy |] // FIXME - | TwoOperands (OprMem (b, s, d, 8), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 8), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] b s d 0b001uy imm 8 - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] b s d 0b001uy imm 16 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] b s d 0b001uy imm 32 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) -> no32Arch ctxt.Arch; encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] b s d 0b001uy imm 32 @@ -2155,22 +2144,22 @@ let paddd (ctxt: EncContext) ins = let palignr (ctxt: EncContext) ins = match ins.Operands with (* Reg - Reg - Imm8 *) - | ThreeOperands (OprReg r1, OprReg r2, OprImm imm) + | ThreeOperands (OprReg r1, OprReg r2, OprImm (imm, _)) when isMMXReg r1 && isMMXReg r2 -> encRRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x0Fuy; 0x3Auy; 0x0Fuy |] r1 r2 imm 8 - | ThreeOperands (OprReg r1, OprReg r2, OprImm imm) + | ThreeOperands (OprReg r1, OprReg r2, OprImm (imm, _)) when isXMMReg r1 && isXMMReg r2 -> encRRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x0Fuy; 0x3Auy; 0x0Fuy |] r1 r2 imm 8 (* Reg - Mem - Imm8 *) - | ThreeOperands (OprReg r, OprMem (b, s, d, 64), OprImm imm) + | ThreeOperands (OprReg r, OprMem (b, s, d, 64), OprImm (imm, _)) when isMMXReg r -> encRMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x0Fuy; 0x3Auy; 0x0Fuy |] r b s d imm 8 - | ThreeOperands (OprReg r, OprMem (b, s, d, 128), OprImm imm) + | ThreeOperands (OprReg r, OprMem (b, s, d, 128), OprImm (imm, _)) when isXMMReg r -> encRMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x0Fuy; 0x3Auy; 0x0Fuy |] r b s d imm 8 @@ -2209,11 +2198,11 @@ let pop (ctxt: EncContext) ins = let pshufd (ctxt: EncContext) ins = match ins.Operands with - | ThreeOperands (OprReg r1, OprReg r2, OprImm imm) + | ThreeOperands (OprReg r1, OprReg r2, OprImm (imm, _)) when isXMMReg r1 && isXMMReg r2 -> encRRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x0Fuy; 0x70uy |] r1 r2 imm 8 - | ThreeOperands (OprReg r, OprMem (b, s, d, 128), OprImm imm) + | ThreeOperands (OprReg r, OprMem (b, s, d, 128), OprImm (imm, _)) when isXMMReg r -> encRMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x0Fuy; 0x70uy |] r b s d imm 8 @@ -2265,13 +2254,13 @@ let push (ctxt: EncContext) ins = no32Arch ctxt.Arch encM ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xFFuy |] b s d 0b110uy - | OneOperand (OprImm imm) when isInt8 imm -> + | OneOperand (OprImm (imm, _)) when isInt8 imm -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x6Auy |] imm 8 - | OneOperand (OprImm imm) when isInt16 imm -> + | OneOperand (OprImm (imm, _)) when isInt16 imm -> encI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x68uy |] imm 16 - | OneOperand (OprImm imm) when isUInt32 imm -> // FIXME + | OneOperand (OprImm (imm, _)) when isUInt32 imm -> // FIXME encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x68uy |] imm 32 | o -> printfn "%A" o; raise NotEncodableException @@ -2294,10 +2283,10 @@ let pxor (ctxt: EncContext) ins = let rotateOrShift (ctxt: EncContext) ins regConstr = match ins.Operands with - | TwoOperands (OprReg r, OprImm (1L as imm)) when isReg8 r -> + | TwoOperands (OprReg r, OprImm (1L as imm, _)) when isReg8 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xD0uy |] r regConstr imm 8 - | TwoOperands (OprMem (b, s, d, 8), OprImm (1L as imm)) -> + | TwoOperands (OprMem (b, s, d, 8), OprImm (1L as imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xD0uy |] b s d regConstr imm 8 | TwoOperands (OprReg r, OprReg Register.CL) when isReg8 r -> @@ -2306,18 +2295,18 @@ let rotateOrShift (ctxt: EncContext) ins regConstr = | TwoOperands (OprMem (b, s, d, 8), OprReg Register.CL) -> encMC ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xD2uy |] b s d regConstr - | TwoOperands (OprReg r, OprImm imm) when isReg8 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg8 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xC0uy |] r regConstr imm 8 - | TwoOperands (Label _, OprImm imm) -> + | TwoOperands (Label _, OprImm (imm, _)) -> encLI ctxt ins regConstr imm 8 [| 0xC0uy |] [| 0xC1uy |] - | TwoOperands (OprMem (b, s, d, 8), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 8), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xC0uy |] b s d regConstr imm 8 - | TwoOperands (OprReg r, OprImm (1L as imm)) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (1L as imm, _)) when isReg16 r -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xD1uy |] r regConstr imm 8 - | TwoOperands (OprMem (b, s, d, 16), OprImm (1L as imm)) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (1L as imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xD1uy |] b s d regConstr imm 8 | TwoOperands (OprReg r, OprReg Register.CL) when isReg16 r -> @@ -2326,16 +2315,16 @@ let rotateOrShift (ctxt: EncContext) ins regConstr = | TwoOperands (OprMem (b, s, d, 16), OprReg Register.CL) -> encMC ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xD3uy |] b s d regConstr - | TwoOperands (OprReg r, OprImm imm) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xC1uy |] r regConstr imm 8 - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xC1uy |] b s d regConstr imm 8 - | TwoOperands (OprReg r, OprImm (1L as imm)) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (1L as imm, _)) when isReg32 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xD1uy |] r regConstr imm 8 - | TwoOperands (OprMem (b, s, d, 32), OprImm (1L as imm)) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (1L as imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xD1uy |] b s d regConstr imm 8 | TwoOperands (OprReg r, OprReg Register.CL) when isReg32 r -> @@ -2344,17 +2333,17 @@ let rotateOrShift (ctxt: EncContext) ins regConstr = | TwoOperands (OprMem (b, s, d, 32), OprReg Register.CL) -> encMC ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xD3uy |] b s d regConstr - | TwoOperands (OprReg r, OprImm imm) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xC1uy |] r regConstr imm 8 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xC1uy |] b s d regConstr imm 8 - | TwoOperands (OprReg r, OprImm (1L as imm)) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (1L as imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0xD1uy |] r regConstr imm 8 - | TwoOperands (OprMem (b, s, d, 64), OprImm (1L as imm)) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (1L as imm, _)) -> no32Arch ctxt.Arch encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0xD1uy |] b s d regConstr imm 8 @@ -2366,11 +2355,11 @@ let rotateOrShift (ctxt: EncContext) ins regConstr = no32Arch ctxt.Arch encMC ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0xD3uy |] b s d regConstr - | TwoOperands (OprReg r, OprImm imm) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0xC1uy |] r regConstr imm 8 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) -> no32Arch ctxt.Arch encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0xC1uy |] b s d regConstr imm 8 @@ -2387,7 +2376,7 @@ let ret (ctxt: EncContext) ins = | OneOperand (OprDirAddr (Relative rel)) -> // FIXME encD ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xC2uy |] rel 16 - | OneOperand (OprImm imm) -> + | OneOperand (OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xC2uy |] imm 16 | o -> printfn "%A" o; raise NotEncodableException @@ -2403,70 +2392,70 @@ let sahf (ctxt: EncContext) = function let sbb (ctxt: EncContext) ins = match ins.Operands with (* Reg (fixed) - Imm (Priority 1) *) - | TwoOperands (OprReg Register.AL, OprImm imm) -> + | TwoOperands (OprReg Register.AL, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x1Cuy |] imm 8 - | TwoOperands (OprReg Register.AX, OprImm imm) -> + | TwoOperands (OprReg Register.AX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x1Duy |] imm 16 - | TwoOperands (OprReg Register.EAX, OprImm imm) -> + | TwoOperands (OprReg Register.EAX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x1Duy |] imm 32 - | TwoOperands (OprReg Register.RAX, OprImm imm) -> + | TwoOperands (OprReg Register.RAX, OprImm (imm, _)) -> no32Arch ctxt.Arch encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x1Duy |] imm 32 (* Reg - Imm (Priority 0) *) - | TwoOperands (OprReg r, OprImm imm) when isReg16 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] r 0b011uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] r 0b011uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r && isInt8 imm -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] r 0b011uy imm 8 (* Mem - Imm (Priority 0) *) - | TwoOperands (Label _, OprImm imm) when isInt8 imm -> + | TwoOperands (Label _, OprImm (imm, _)) when isInt8 imm -> encLI ctxt ins 0b011uy imm 8 [||] [| 0x83uy |] - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] b s d 0b011uy imm 8 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] b s d 0b011uy imm 8 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) when isInt8 imm -> no32Arch ctxt.Arch encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] b s d 0b011uy imm 8 (* Reg - Imm (Priority 1) *) - | TwoOperands (OprReg r, OprImm imm) when isReg8 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg8 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] r 0b011uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] r 0b011uy imm 16 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] r 0b011uy imm 32 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] r 0b011uy imm 32 (* Mem - Imm (Priority 1) *) - | TwoOperands (Label _, OprImm imm) -> + | TwoOperands (Label _, OprImm (imm, _)) -> encLI ctxt ins 0b011uy imm 32 [| 0x80uy |] [| 0x81uy |] // FIXME - | TwoOperands (OprMem (b, s, d, 8), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 8), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] b s d 0b011uy imm 8 - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] b s d 0b011uy imm 16 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] b s d 0b011uy imm 32 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) -> no32Arch ctxt.Arch; encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] b s d 0b011uy imm 32 @@ -2576,11 +2565,11 @@ let setz ctxt ins = setcc ctxt ins 0x94uy let shld (ctxt: EncContext) ins = match ins.Operands with - | ThreeOperands (OprReg r1, OprReg r2, OprImm imm) + | ThreeOperands (OprReg r1, OprReg r2, OprImm (imm, _)) when isReg16 r1 && isReg16 r2 -> encRRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x0Fuy; 0xA4uy |] r1 r2 imm 8 - | ThreeOperands (OprMem (b, s, d, 16), OprReg r, OprImm imm) + | ThreeOperands (OprMem (b, s, d, 16), OprReg r, OprImm (imm, _)) when isReg16 r -> encMRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x0Fuy; 0xA4uy |] b s d r imm 8 @@ -2592,11 +2581,11 @@ let shld (ctxt: EncContext) ins = when isReg16 r -> encMR ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x0Fuy; 0xA5uy |] b s d r - | ThreeOperands (OprReg r1, OprReg r2, OprImm imm) + | ThreeOperands (OprReg r1, OprReg r2, OprImm (imm, _)) when isReg32 r1 && isReg32 r2 -> encRRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexMR [| 0x0Fuy; 0xA4uy |] r2 r1 imm 8 - | ThreeOperands (OprMem (b, s, d, 32), OprReg r, OprImm imm) + | ThreeOperands (OprMem (b, s, d, 32), OprReg r, OprImm (imm, _)) when isReg32 r -> encMRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x0Fuy; 0xA4uy |] b s d r imm 8 @@ -2608,12 +2597,12 @@ let shld (ctxt: EncContext) ins = when isReg32 r -> encMR ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x0Fuy; 0xA5uy |] b s d r - | ThreeOperands (OprReg r1, OprReg r2, OprImm imm) + | ThreeOperands (OprReg r1, OprReg r2, OprImm (imm, _)) when isReg64 r1 && isReg64 r2 -> no32Arch ctxt.Arch encRRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x0Fuy; 0xA4uy |] r1 r2 imm 8 - | ThreeOperands (OprMem (b, s, d, 64), OprReg r, OprImm imm) + | ThreeOperands (OprMem (b, s, d, 64), OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encMRI ins ctxt.Arch @@ -2662,70 +2651,70 @@ let stosw (ctxt: EncContext) ins = let sub (ctxt: EncContext) ins = match ins.Operands with (* Reg (fixed) - Imm (Priority 1) *) - | TwoOperands (OprReg Register.AL, OprImm imm) -> + | TwoOperands (OprReg Register.AL, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x2Cuy |] imm 8 - | TwoOperands (OprReg Register.AX, OprImm imm) -> + | TwoOperands (OprReg Register.AX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x2Duy |] imm 16 - | TwoOperands (OprReg Register.EAX, OprImm imm) -> + | TwoOperands (OprReg Register.EAX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x2Duy |] imm 32 - | TwoOperands (OprReg Register.RAX, OprImm imm) -> + | TwoOperands (OprReg Register.RAX, OprImm (imm, _)) -> no32Arch ctxt.Arch encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x2Duy |] imm 32 (* Reg - Imm (Priority 0) *) - | TwoOperands (OprReg r, OprImm imm) when isReg16 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] r 0b101uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] r 0b101uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r && isInt8 imm -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] r 0b101uy imm 8 (* Mem - Imm (Priority 0) *) - | TwoOperands (Label _, OprImm imm) when isInt8 imm -> + | TwoOperands (Label _, OprImm (imm, _)) when isInt8 imm -> encLI ctxt ins 0b101uy imm 8 [||] [| 0x83uy |] - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] b s d 0b101uy imm 8 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] b s d 0b101uy imm 8 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) when isInt8 imm -> no32Arch ctxt.Arch encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] b s d 0b101uy imm 8 (* Reg - Imm (Priority 1) *) - | TwoOperands (OprReg r, OprImm imm) when isReg8 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg8 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] r 0b101uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] r 0b101uy imm 16 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] r 0b101uy imm 32 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] r 0b101uy imm 32 (* Mem - Imm (Priority 1) *) - | TwoOperands (Label _, OprImm imm) -> + | TwoOperands (Label _, OprImm (imm, _)) -> encLI ctxt ins 0b101uy imm 32 [| 0x80uy |] [| 0x81uy |] // FIXME - | TwoOperands (OprMem (b, s, d, 8), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 8), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] b s d 0b101uy imm 8 - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] b s d 0b101uy imm 16 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] b s d 0b101uy imm 32 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) -> no32Arch ctxt.Arch; encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] b s d 0b011uy imm 32 @@ -2800,46 +2789,46 @@ let subss (ctxt: EncContext) ins = let test (ctxt: EncContext) ins = match ins.Operands with (* Reg (fixed) - Imm *) - | TwoOperands (OprReg Register.AL, OprImm imm) -> + | TwoOperands (OprReg Register.AL, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xA8uy |] imm 8 - | TwoOperands (OprReg Register.AX, OprImm imm) -> + | TwoOperands (OprReg Register.AX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xA9uy |] imm 16 - | TwoOperands (OprReg Register.EAX, OprImm imm) -> + | TwoOperands (OprReg Register.EAX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xA9uy |] imm 32 - | TwoOperands (OprReg Register.RAX, OprImm imm) -> + | TwoOperands (OprReg Register.RAX, OprImm (imm, _)) -> no32Arch ctxt.Arch encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0xA9uy |] imm 32 (* Reg - Imm *) - | TwoOperands (OprReg r, OprImm imm) when isReg8 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg8 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xF6uy |] r 0b000uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xF7uy |] r 0b000uy imm 16 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xF7uy |] r 0b000uy imm 32 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0xF7uy |] r 0b000uy imm 32 (* Mem - Imm *) - | TwoOperands (Label _, OprImm imm) -> + | TwoOperands (Label _, OprImm (imm, _)) -> encLI ctxt ins 0b000uy imm 32 [| 0xF6uy |] [| 0xF7uy |] // FIXME - | TwoOperands (OprMem (b, s, d, 8), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 8), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xF6uy |] b s d 0b000uy imm 8 - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xF7uy |] b s d 0b000uy imm 16 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xF7uy |] b s d 0b000uy imm 32 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) -> no32Arch ctxt.Arch; encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0xF7uy |] b s d 0b000uy imm 32 @@ -2940,20 +2929,20 @@ let vaddss (ctxt: EncContext) ins = let vpalignr (ctxt: EncContext) ins = match ins.Operands with (* Reg - Reg - Reg - Imm8 *) - | FourOperands (OprReg r1, OprReg r2, OprReg r3, OprImm imm) + | FourOperands (OprReg r1, OprReg r2, OprReg r3, OprImm (imm, _)) when isXMMReg r1 && isXMMReg r2 && isXMMReg r3 -> encVexRRRI ins ctxt.Arch (Some r2) ctxt.VEX128n66n0F3A [| 0x0Fuy |] r1 r3 imm 8 - | FourOperands (OprReg r1, OprReg r2, OprReg r3, OprImm imm) + | FourOperands (OprReg r1, OprReg r2, OprReg r3, OprImm (imm, _)) when isYMMReg r1 && isYMMReg r2 && isYMMReg r3 -> encVexRRRI ins ctxt.Arch (Some r2) ctxt.VEX256n66n0F3A [| 0x0Fuy |] r1 r3 imm 8 (* Reg - Reg - Mem - Imm8 *) - | FourOperands (OprReg r1, OprReg r2, OprMem (b, s, d, 128), OprImm imm) + | FourOperands (OprReg r1, OprReg r2, OprMem (b, s, d, 128), OprImm (imm, _)) when isXMMReg r1 && isXMMReg r2 -> encVexRRMI ins ctxt.Arch (Some r2) ctxt.VEX128n66n0F3A [| 0x0Fuy |] r1 b s d imm 8 - | FourOperands (OprReg r1, OprReg r2, OprMem (b, s, d, 256), OprImm imm) + | FourOperands (OprReg r1, OprReg r2, OprMem (b, s, d, 256), OprImm (imm, _)) when isYMMReg r1 && isYMMReg r2 -> encVexRRMI ins ctxt.Arch (Some r2) ctxt.VEX256n66n0F3A [| 0x0Fuy |] r1 b s d imm 8 @@ -2979,66 +2968,66 @@ let xchg (ctxt: EncContext) ins = let xor (ctxt: EncContext) ins = match ins.Operands with (* Reg (fixed) - Imm (Priority 1). *) - | TwoOperands (OprReg Register.AL, OprImm imm) -> + | TwoOperands (OprReg Register.AL, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x34uy |] imm 8 - | TwoOperands (OprReg Register.AX, OprImm imm) -> + | TwoOperands (OprReg Register.AX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x35uy |] imm 16 - | TwoOperands (OprReg Register.EAX, OprImm imm) -> + | TwoOperands (OprReg Register.EAX, OprImm (imm, _)) -> encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x35uy |] imm 32 - | TwoOperands (OprReg Register.RAX, OprImm imm) -> + | TwoOperands (OprReg Register.RAX, OprImm (imm, _)) -> no32Arch ctxt.Arch encI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x35uy |] imm 32 (* Reg - Imm (Priority 0) *) - | TwoOperands (OprReg r, OprImm imm) when isReg16 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] r 0b110uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r && isInt8 imm -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] r 0b110uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r && isInt8 imm -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r && isInt8 imm -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] r 0b110uy imm 8 (* Mem - Imm (Priority 0) *) - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x83uy |] b s d 0b110uy imm 8 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) when isInt8 imm -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x83uy |] b s d 0b110uy imm 8 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) when isInt8 imm -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) when isInt8 imm -> no32Arch ctxt.Arch encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x83uy |] b s d 0b110uy imm 8 (* Reg - Imm (Priority 1) *) - | TwoOperands (OprReg r, OprImm imm) when isReg8 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg8 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] r 0b110uy imm 8 - | TwoOperands (OprReg r, OprImm imm) when isReg16 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg16 r -> encRI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] r 0b110uy imm 16 - | TwoOperands (OprReg r, OprImm imm) when isReg32 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg32 r -> encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] r 0b110uy imm 32 - | TwoOperands (OprReg r, OprImm imm) when isReg64 r -> + | TwoOperands (OprReg r, OprImm (imm, _)) when isReg64 r -> no32Arch ctxt.Arch encRI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] r 0b110uy imm 32 (* Mem - Imm (Priority 1) *) - | TwoOperands (OprMem (b, s, d, 8), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 8), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x80uy |] b s d 0b110uy imm 8 - | TwoOperands (OprMem (b, s, d, 16), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 16), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0x81uy |] b s d 0b110uy imm 16 - | TwoOperands (OprMem (b, s, d, 32), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 32), OprImm (imm, _)) -> encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0x81uy |] b s d 0b110uy imm 32 - | TwoOperands (OprMem (b, s, d, 64), OprImm imm) -> + | TwoOperands (OprMem (b, s, d, 64), OprImm (imm, _)) -> no32Arch ctxt.Arch; encMI ins ctxt.Arch ctxt.PrefNormal ctxt.RexW [| 0x81uy |] b s d 0b110uy imm 32 diff --git a/src/Assembler/Intel/IntelAsmOperands.fs b/src/Peripheral/Assembly/Intel/IntelAsmOperands.fs similarity index 98% rename from src/Assembler/Intel/IntelAsmOperands.fs rename to src/Peripheral/Assembly/Intel/IntelAsmOperands.fs index c85de9c8..15760c31 100644 --- a/src/Assembler/Intel/IntelAsmOperands.fs +++ b/src/Peripheral/Assembly/Intel/IntelAsmOperands.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.Assembler.Intel.AsmOperands +module internal B2R2.Peripheral.Assembly.Intel.AsmOperands open System open B2R2 -open B2R2.FrontEnd.Intel +open B2R2.FrontEnd.BinLifter.Intel let regTo3Bit = function | Register.AL | Register.AX | Register.EAX | Register.RAX | Register.BND0 diff --git a/src/Assembler/Intel/IntelAsmParser.fs b/src/Peripheral/Assembly/Intel/IntelAsmParser.fs similarity index 89% rename from src/Assembler/Intel/IntelAsmParser.fs rename to src/Peripheral/Assembly/Intel/IntelAsmParser.fs index d6e253f2..5fc1d737 100644 --- a/src/Assembler/Intel/IntelAsmParser.fs +++ b/src/Peripheral/Assembly/Intel/IntelAsmParser.fs @@ -22,19 +22,21 @@ SOFTWARE. *) -namespace B2R2.Assembler.Intel +namespace B2R2.Peripheral.Assembly.Intel open B2R2 -open B2R2.FrontEnd.Intel -open B2R2.Assembler.Intel.ParserHelper -open B2R2.Assembler.Intel.AsmMain +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.Peripheral.Assembly +open B2R2.Peripheral.Assembly.Intel.ParserHelper +open B2R2.Peripheral.Assembly.Intel.AsmMain open FParsec open System /// Label name to relative index of instructions. type LabelDefs = Map -type AsmParser (isa, baseAddr: Addr) = +type IntelAsmParser (isa, baseAddr: Addr) = + inherit AsmParser () let mutable inferredPrefix = Prefix.PrxNone let defaultRegType = isa.WordSize |> WordSize.toRegType @@ -168,7 +170,7 @@ type AsmParser (isa, baseAddr: Addr) = let pAbsoluteAddress = pImm |>> int16 .>> spaces .>> pchar ';' .>> spaces .>>. pAddr - |>> (fun (sel, addr) -> Absolute (sel, addr, dummyRegType)) + |>> (fun (sel, addr) -> Absolute (sel, addr, 0 (* dummy *))) let pJumpTarget = attempt pAbsoluteAddress <|> (pImm |>> Relative) @@ -179,7 +181,9 @@ type AsmParser (isa, baseAddr: Addr) = let pOprDirAddr opc = check opc Helper.isBranch >>. pJumpTarget |>> OprDirAddr - let pOprImm = pImm |>> OprImm + (* We just put dummy regsize here, as immediates will be replaced according to + the decoding rules anyways. *) + let pOprImm = pImm |>> fun i -> OprImm (i, 32) let pSizedLabel sz = let sz = Option.defaultValue defaultRegType sz @@ -205,8 +209,7 @@ type AsmParser (isa, baseAddr: Addr) = let pInsInfo = opt pPrefix >>. spaces >>. (pOpcode >>= operands) |>> (fun (opcode, operands) -> - newInfo inferredPrefix REXPrefix.NOREX None - opcode operands dummyInsSize) + newInfo inferredPrefix REXPrefix.NOREX None opcode operands) let pInstructionLine = incrementIndex >>. opt pLabelDef >>. spaces >>. pInsInfo .>> resetPrefix @@ -219,10 +222,10 @@ type AsmParser (isa, baseAddr: Addr) = let statements = sepEndBy statement terminator .>> (eof "") - member __.Run assembly = + override __.Assemble assembly = let st = { LabelMap = Map.empty; CurIndex = -1 } - match runParserOnString statements st "IntelAsm" assembly with + match runParserOnString statements st "" assembly with | Success (result, us, _) -> - filterInstructionLines result |> assemble us isa baseAddr + filterInstructionLines result |> assemble us isa baseAddr |> Result.Ok | Failure (str, _, _) -> - failwithf "Assembly failed: %s" str + Result.Error (str) diff --git a/src/Assembler/Intel/IntelAsmPrefix.fs b/src/Peripheral/Assembly/Intel/IntelAsmPrefix.fs similarity index 98% rename from src/Assembler/Intel/IntelAsmPrefix.fs rename to src/Peripheral/Assembly/Intel/IntelAsmPrefix.fs index de4639a6..712523e0 100644 --- a/src/Assembler/Intel/IntelAsmPrefix.fs +++ b/src/Peripheral/Assembly/Intel/IntelAsmPrefix.fs @@ -22,10 +22,11 @@ SOFTWARE. *) -module internal B2R2.Assembler.Intel.AsmPrefix +module internal B2R2.Peripheral.Assembly.Intel.AsmPrefix open B2R2 -open B2R2.FrontEnd.Intel +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.Peripheral.Assembly.Intel.ParserHelper let isReg8 reg = Register.toRegType reg = 8 let isReg16 reg = Register.toRegType reg = 16 diff --git a/src/Assembler/Intel/IntelAsmTypes.fs b/src/Peripheral/Assembly/Intel/IntelAsmTypes.fs similarity index 98% rename from src/Assembler/Intel/IntelAsmTypes.fs rename to src/Peripheral/Assembly/Intel/IntelAsmTypes.fs index cd39da7d..fc2f7d98 100644 --- a/src/Assembler/Intel/IntelAsmTypes.fs +++ b/src/Peripheral/Assembly/Intel/IntelAsmTypes.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -namespace B2R2.Assembler.Intel +namespace B2R2.Peripheral.Assembly.Intel open B2R2 -open B2R2.FrontEnd.Intel +open B2R2.FrontEnd.BinLifter.Intel exception NotEncodableException diff --git a/src/Assembler/Intel/IntelParserHelper.fs b/src/Peripheral/Assembly/Intel/IntelParserHelper.fs similarity index 85% rename from src/Assembler/Intel/IntelParserHelper.fs rename to src/Peripheral/Assembly/Intel/IntelParserHelper.fs index 1eaff4ec..bd9eb972 100644 --- a/src/Assembler/Intel/IntelParserHelper.fs +++ b/src/Peripheral/Assembly/Intel/IntelParserHelper.fs @@ -22,15 +22,23 @@ SOFTWARE. *) -module B2R2.Assembler.Intel.ParserHelper +module B2R2.Peripheral.Assembly.Intel.ParserHelper open B2R2 -open B2R2.FrontEnd.Intel +open B2R2.FrontEnd.BinLifter.Intel + +type AsmInsInfo = { + Prefixes: Prefix + REXPrefix: REXPrefix + VEXInfo: VEXInfo option + Opcode: Opcode + Operands: Operands +} /// AssemblyLine is either a label or an instruction. type AssemblyLine = | LabelDefLine - | InstructionLine of InsInfo + | InstructionLine of AsmInsInfo let checkIfInstructionLine = function | InstructionLine ins -> Some ins @@ -77,23 +85,9 @@ let prefixFromRegString (str: string) = | "ss" -> Prefix.PrxSS | _ -> Utils.impossible () -let dummyRegType = 0 - -let dummyMemorySize = - { EffOprSize = dummyRegType - EffAddrSize = dummyRegType - EffRegSize = dummyRegType } - -let dummyInsSize = - { MemSize = dummyMemorySize - RegSize = dummyRegType - OperationSize = dummyRegType - SizeCond = Sz64 } - -let newInfo prfxs rexPrfx vexInfo opc operands size = +let newInfo prfxs rexPrfx vexInfo opc operands = { Prefixes = prfxs REXPrefix = rexPrfx VEXInfo = vexInfo Opcode = opc - Operands = operands - InsSize = size } + Operands = operands } diff --git a/src/Peripheral/Assembly/Intel/README.md b/src/Peripheral/Assembly/Intel/README.md new file mode 100644 index 00000000..c1da69ec --- /dev/null +++ b/src/Peripheral/Assembly/Intel/README.md @@ -0,0 +1,11 @@ +# B2R2.Peripheral.Assembly.Intel + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.Peripheral.Assembly.Intel Package? + +`B2R2.Peripheral.Assembly.Intel` includes our Intel assembler. diff --git a/src/Peripheral/Assembly/LowUIR/B2R2.Peripheral.Assembly.LowUIR.fsproj b/src/Peripheral/Assembly/LowUIR/B2R2.Peripheral.Assembly.LowUIR.fsproj new file mode 100644 index 00000000..32e613e4 --- /dev/null +++ b/src/Peripheral/Assembly/LowUIR/B2R2.Peripheral.Assembly.LowUIR.fsproj @@ -0,0 +1,30 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 LowUIR assembly library. + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Peripheral/Assembly/LowUIR/LowUIRParser.fs b/src/Peripheral/Assembly/LowUIR/LowUIRParser.fs new file mode 100644 index 00000000..2c8b980e --- /dev/null +++ b/src/Peripheral/Assembly/LowUIR/LowUIRParser.fs @@ -0,0 +1,364 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.Peripheral.Assembly.LowUIR + +open FParsec +open System +open System.Numerics +open System.Globalization +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.Peripheral.Assembly.Utils +open B2R2.Peripheral.Assembly.LowUIR.Helper + +type Parser<'t> = Parser<'t, RegType> + +type LowUIRParser (isa, regbay: RegisterBay) = + + let isAllowedFirstCharForID c = isAsciiLetter c + + let isAllowedCharForID c = isAsciiLetter c || isDigit c + + let pIdentifier = + many1Satisfy2L isAllowedFirstCharForID isAllowedCharForID "identifier" + + let ws = spaces + + let numberFormat = + NumberLiteralOptions.AllowMinusSign ||| + NumberLiteralOptions.AllowBinary ||| + NumberLiteralOptions.AllowHexadecimal ||| + NumberLiteralOptions.AllowOctal ||| + NumberLiteralOptions.AllowPlusSign + + let pNumber = + numberLiteral numberFormat "number" + |>> fun n -> + let s = n.String + if s.StartsWith ("0x") then + BigInteger.Parse ("0" + s.Substring (2), NumberStyles.AllowHexSpecifier) + else BigInteger.Parse (s) + |> BitVector.ofBInt + + let pRegType = + (anyOf "IiFf") >>. pint32 |>> RegType.fromBitWidth + + let pBitVector = + pNumber + .>>. opt (pchar ':' >>. ws >>. pRegType) + >>= (fun (toBV, typ) -> + match typ with + | None -> getUserState |>> (fun t -> toBV t) + | Some typ -> preturn (toBV typ)) + + let pUnaryOperator = + [ "-"; "~"; "sqrt"; "cos"; "sin"; "tan"; "atan" ] + |> List.map pstring |> List.map attempt |> choice |>> UnOpType.ofString + + let pCastType = + [ "sext"; "zext"; "float"; "round"; "ceil"; "floor"; "trunc"; "fext" ] + |> List.map pstring |> List.map attempt |> choice |>> CastKind.ofString + + let pExpr, pExprRef = createParserForwardedToRef () + + let pNum = pBitVector |>> AST.num + + let regnames = regbay.GetAllRegNames () + + let pVar = + List.map pstringCI regnames + |> List.map attempt + |> choice + |>> regbay.StrToRegExpr + + let pTempVar = + pstring "T_" >>. pint32 .>> ws + .>> pchar ':' .>> ws .>>. pRegType + |>> (fun (num, typ) -> AST.tmpvar typ num) + + let pUnOp = + pUnaryOperator .>> ws .>>. pExpr + |>> (fun (op, e1) -> AST.unop op e1) + + let pLoad = + pchar '[' >>. pExpr .>> ws .>> pchar ']' .>> ws + .>> pchar ':' .>> ws .>>. pRegType + |>> (fun (e, typ) -> AST.load isa.Endian typ e) + + let pCast = + pCastType .>> ws .>> pchar ':' .>> ws .>>. pRegType .>> ws + .>> pchar '(' .>> ws .>>. pExpr .>> ws .>> pchar ')' + |>> (fun ((kind, typ), expr) -> AST.cast kind typ expr) + + let toExtractExpr ((expr, n), pos) = + AST.extract expr (RegType.fromBitWidth (n + 1 - pos)) pos + + let pExtractNoParen = + (pVar <|> pTempVar <|> pLoad <|> pNum <|> pCast) + .>> ws .>> pchar '[' .>> ws + .>>. pint32 .>> ws .>> pchar ':' .>> ws .>>. pint32 .>> ws + .>> pchar ']' + |>> toExtractExpr + + let pComment = + let isComment c = + isLetter c || isDigit c || Char.IsWhiteSpace c || c = '.' + many1Satisfy isComment + + let pUndefinedExpr = + pstring "??" >>. ws + >>. pchar '(' >>. ws >>. pComment .>> ws .>> pchar ')' + >>= fun comment -> + getUserState |>> (fun rt -> AST.undef rt comment) + + let pNil = pstringCI "nil" |>> (fun _ -> AST.nil) + + let pPrimaryValue = + [ attempt pExtractNoParen .>> ws + pVar .>> ws + pTempVar .>> ws + pUnOp .>> ws + pLoad .>> ws + pNum .>> ws + pCast .>> ws + pUndefinedExpr .>> ws + pNil .>> ws ] |> choice + + let pFLog = + pstring "lg" >>. ws + >>. pchar '(' >>. ws + >>. pExpr .>> ws .>> pchar ',' .>> ws + .>>. pExpr .>> ws .>> pchar ')' + |>> (fun (e1, e2) -> AST.binop BinOpType.FLOG e1 e2) + + let initInfix (opp: OperatorPrecedenceParser<_, _, _>) ops = + ops |> List.iter (fun (initializer, op, prec, assoc) -> + opp.AddOperator (InfixOperator(op, ws, prec, assoc, initializer))) + + let initTernary (opp: OperatorPrecedenceParser<_, _, _>) args = + args |> fun (initializer, opl, opr, assoc) -> + opp.AddOperator (TernaryOperator(opl, ws, opr, ws, 1, assoc, initializer)) + + let opp = OperatorPrecedenceParser () + let pOps = opp.ExpressionParser + + let pExtractPattern = + pchar '[' >>. ws + >>. pint32 .>> ws .>> pchar ':' .>> ws .>>. pint32 .>> ws + .>> pchar ']' + + let pParenOrExtract = + pBetweenParen pOps .>>. opt pExtractPattern + |>> (fun (e, extract) -> + match extract with + | Some (n, pos) -> + AST.extract e (RegType.fromBitWidth (n + 1 - pos)) pos + | None -> e) + + let term = + attempt pParenOrExtract + <|> pPrimaryValue + <|> pFLog + + let () = + opp.TermParser <- term + pExprRef := pOps + + [ AST.binop BinOpType.ADD, "+", 3, Associativity.Left + AST.binop BinOpType.SUB, "-", 3, Associativity.Left + AST.binop BinOpType.MUL, "*", 4, Associativity.Left + AST.binop BinOpType.DIV, "/", 4, Associativity.Left + AST.binop BinOpType.SDIV, "?/", 4, Associativity.Left + AST.binop BinOpType.MOD, "%", 4, Associativity.Left + AST.binop BinOpType.SMOD, "?%", 4, Associativity.Left + AST.binop BinOpType.SHL, "<<", 4, Associativity.Left + AST.binop BinOpType.SHR, ">>", 4, Associativity.Left + AST.binop BinOpType.SAR, "?>>", 4, Associativity.Left + AST.binop BinOpType.AND, "&", 4, Associativity.Left + AST.binop BinOpType.OR, "|", 4, Associativity.Left + AST.binop BinOpType.XOR, "^", 4, Associativity.Left + AST.binop BinOpType.CONCAT, "++", 4, Associativity.Left + AST.binop BinOpType.APP, "-|", 5, Associativity.Right + AST.binop BinOpType.CONS, "::", 4, Associativity.Right + AST.binop BinOpType.FADD, "+.", 4, Associativity.Left + AST.binop BinOpType.FSUB, "-.", 4, Associativity.Left + AST.binop BinOpType.FMUL, "*.", 4, Associativity.Left + AST.binop BinOpType.FDIV, "/.", 4, Associativity.Left + AST.binop BinOpType.FPOW, "^^", 4, Associativity.Left ] + |> initInfix opp + + [ AST.relop RelOpType.EQ, "=", 1, Associativity.Left + AST.relop RelOpType.NEQ, "!=", 1, Associativity.Left + AST.relop RelOpType.GT, ">", 2, Associativity.Left + AST.relop RelOpType.GE, ">=", 2, Associativity.Left + AST.relop RelOpType.SGT, "?>", 2, Associativity.Left + AST.relop RelOpType.SGE, "?>=", 2, Associativity.Left + AST.relop RelOpType.LT, "<", 2, Associativity.Left + AST.relop RelOpType.LE, "<=", 2, Associativity.Left + AST.relop RelOpType.SLT, "?<", 2, Associativity.Left + AST.relop RelOpType.SLE, "?<=", 2, Associativity.Left + AST.relop RelOpType.FGT, ">.", 2, Associativity.Left + AST.relop RelOpType.FGE, ">=.", 2, Associativity.Left + AST.relop RelOpType.FLT, "<.", 2, Associativity.Left + AST.relop RelOpType.FLE, "<=.", 2, Associativity.Left ] + |> initInfix opp + + (AST.ite, "?", ":", Associativity.Right) + |> initTernary opp + + let pISMark = + ws + >>. pchar '(' + >>. ws >>. puint32 .>> ws + .>> pchar ')' + .>> ws .>> pchar '{' + |>> AST.ismark + + let pIEMark = + ws + >>. pchar '}' >>. ws + >>. pstring "//" >>. ws >>. puint32 .>> ws + |>> AST.iemark + + let pLMark = + ws >>. pchar ':' >>. pIdentifier + |>> (fun name -> AST.symbol name 0 |> AST.lmark) + + let pPut = + ws + >>. ((attempt pTempVar <|> pVar) >>= updateExpectedType) + .>> ws .>> pstring ":=" .>> ws .>>. pExpr + |>> (fun (dest, value) -> AST.assign dest value) + + let pStore = + ws + >>. pchar '[' .>> ws >>. pExpr .>> ws .>> pchar ']' .>> ws + .>> pstring ":=" .>> ws .>>. pExpr + |>> (fun (e1, e2) -> AST.store isa.Endian e1 e2) + + let pJmp = + ws >>. pstring "jmp" >>. ws >>. pIdentifier + |>> (fun lab -> + AST.jmp (AST.name <| AST.symbol lab 0)) + + let pCJmp = + ws + >>. pstring "if" .>> ws >>. pExpr .>> ws + .>> pstring "then" .>> ws + .>> pstring "jmp" .>> ws .>>. pIdentifier .>> ws + .>> pstring "else" .>> ws .>> pstring "jmp" .>> ws .>>. pIdentifier + |>> (fun ((cond, tlab), flab) -> + let tlab = AST.name <| AST.symbol tlab 0 + let flab = AST.name <| AST.symbol flab 0 + AST.cjmp cond tlab flab) + + let pInterJmp = + pstring "ijmp" .>> ws >>. pExpr + |>> (fun expr -> + let rt = TypeCheck.typeOf expr + AST.interjmp expr InterJmpKind.Base) + + let pInterCJmp = + ws + >>. pstring "if" .>> ws >>. pExpr .>> ws + .>> pstring "then" .>> ws + .>> pstring "ijmp" .>> ws .>>. pExpr .>> ws + .>> pstring "else" .>> ws .>> pstring "ijmp" .>> ws .>>. pExpr + |>> (fun ((cond, tExp), fExp) -> + let rt = TypeCheck.typeOf tExp + AST.intercjmp cond tExp fExp) + + let pException = + pstringCI "Exception" + >>. ws >>. pchar '(' >>. ws >>. pIdentifier .>> ws .>> pchar ')' + |>> Exception + + let pSideEffectKind = + attempt (pstringCI "breakpoint" >>% Breakpoint) + <|> attempt (pstringCI "clk" >>% ClockCounter) + <|> attempt (pstringCI "fence" >>% Fence) + <|> attempt (pstringCI "delay" >>% Delay) + <|> attempt (pstringCI "terminate" >>% Terminate) + <|> attempt (pstringCI "int" >>. pint32 |>> Interrupt) + <|> attempt pException + <|> attempt (pstringCI "lock" >>% Lock) + <|> attempt (pstringCI "pid" >>% ProcessorID) + <|> attempt (pstringCI "syscall" >>% SysCall) + <|> attempt (pstringCI "undef" >>% UndefinedInstr) + <|> attempt (pstringCI "fp" >>% UnsupportedFP) + <|> attempt (pstringCI "privinstr" >>% UnsupportedPrivInstr) + <|> attempt (pstringCI "far" >>% UnsupportedFAR) + <|> attempt (pstringCI "cpu extension" >>% UnsupportedExtension) + <|> attempt (pstringCI "call " >>. pExpr |>> ExternalCall) + + let pSideEffect = + ws + >>. pstring "!!" .>> ws >>. pSideEffectKind + |>> AST.sideEffect + + let pStatement = + attempt pISMark + <|> attempt pIEMark + <|> attempt pLMark + <|> attempt pPut + <|> attempt pStore + <|> attempt pJmp + <|> attempt pCJmp + <|> attempt pInterJmp + <|> attempt pInterCJmp + <|> attempt pSideEffect + >>= typeCheck + + let pLines = + sepBy (restOfLine false) newline + + member private __.SeparateLines str = + match run pLines str with + | Success (lines, _, _) -> Result.Ok lines + | Failure (errStr, _, _) -> Result.Error (errStr) + + member private __.TryParseStmt line = + try runParserOnString pStatement 0 "" line + with e -> + let dummyPos = Position ("", 0L, 0L, 0L) + let nl = Environment.NewLine + let msg = e.Message + nl + e.StackTrace + nl + nl + "> " + line + Failure (msg, ParserError (dummyPos, 0, unexpected ""), 0) + + member private __.ParseLines acc lines = + match lines with + | line :: rest -> + if String.length line = 0 then __.ParseLines acc rest + else (* A LowUIR stmt always occupies a single line. *) + match __.TryParseStmt line with + | Success (stmt, _, _pos) -> __.ParseLines (stmt :: acc) rest + | Failure (errStr, _, _) -> Result.Error (errStr) + | [] -> Result.Ok (List.rev acc |> List.toArray) + + member __.Parse str = + __.SeparateLines str + |> Result.bind (__.ParseLines []) diff --git a/src/BinGraph.Tests/Types.fs b/src/Peripheral/Assembly/LowUIR/LowUIRParserHelper.fs similarity index 81% rename from src/BinGraph.Tests/Types.fs rename to src/Peripheral/Assembly/LowUIR/LowUIRParserHelper.fs index fcb96340..1220d597 100644 --- a/src/BinGraph.Tests/Types.fs +++ b/src/Peripheral/Assembly/LowUIR/LowUIRParserHelper.fs @@ -22,11 +22,15 @@ SOFTWARE. *) -namespace B2R2.BinGraph.Tests +module B2R2.Peripheral.Assembly.LowUIR.Helper -open B2R2.BinGraph +open B2R2.BinIR.LowUIR +open FParsec -type V (v, range) = - inherit RangedVertexData (range) - member __.Val : int = v - override __.ToString () = v.ToString () +let typeCheck st = + if TypeCheck.stmt st then preturn st + else fail "Type check failed." + +let updateExpectedType e = + updateUserState (fun _ -> TypeCheck.typeOf e) + >>. preturn e diff --git a/src/Peripheral/Assembly/LowUIR/README.md b/src/Peripheral/Assembly/LowUIR/README.md new file mode 100644 index 00000000..02c127c5 --- /dev/null +++ b/src/Peripheral/Assembly/LowUIR/README.md @@ -0,0 +1,11 @@ +# B2R2.Peripheral.Assembly.LowUIR + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.Peripheral.Assembly.LowUIR Package? + +`B2R2.Peripheral.Assembly.LowUIR` includes our LowUIR assembler. diff --git a/src/Peripheral/Assembly/MIPS/B2R2.Peripheral.Assembly.MIPS.fsproj b/src/Peripheral/Assembly/MIPS/B2R2.Peripheral.Assembly.MIPS.fsproj new file mode 100644 index 00000000..c0e35394 --- /dev/null +++ b/src/Peripheral/Assembly/MIPS/B2R2.Peripheral.Assembly.MIPS.fsproj @@ -0,0 +1,28 @@ + + + + net5.0 + LICENSE.md + b2r2-240x240.png + README.md + B2R2 MIPS assembly library. + + + + + + + + + + + + + + + + + + + + diff --git a/src/Assembler/MIPS/MIPSAsmParser.fs b/src/Peripheral/Assembly/MIPS/MIPSAsmParser.fs similarity index 97% rename from src/Assembler/MIPS/MIPSAsmParser.fs rename to src/Peripheral/Assembly/MIPS/MIPSAsmParser.fs index 3d84b045..cf5fc187 100644 --- a/src/Assembler/MIPS/MIPSAsmParser.fs +++ b/src/Peripheral/Assembly/MIPS/MIPSAsmParser.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -namespace B2R2.Assembler.MIPS +namespace B2R2.Peripheral.Assembly.MIPS open B2R2 -open B2R2.FrontEnd.MIPS -open B2R2.Assembler.MIPS.ParserHelper +open B2R2.FrontEnd.BinLifter.MIPS +open B2R2.Peripheral.Assembly.MIPS.ParserHelper open FParsec open System diff --git a/src/Assembler/MIPS/MIPSParserHelper.fs b/src/Peripheral/Assembly/MIPS/MIPSParserHelper.fs similarity index 97% rename from src/Assembler/MIPS/MIPSParserHelper.fs rename to src/Peripheral/Assembly/MIPS/MIPSParserHelper.fs index 706f1e8e..69984ce4 100644 --- a/src/Assembler/MIPS/MIPSParserHelper.fs +++ b/src/Peripheral/Assembly/MIPS/MIPSParserHelper.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module B2R2.Assembler.MIPS.ParserHelper +module B2R2.Peripheral.Assembly.MIPS.ParserHelper open B2R2 -open B2R2.FrontEnd.MIPS +open B2R2.FrontEnd.BinLifter.MIPS let extractOperands = function | [] -> NoOperand diff --git a/src/Assembler/MIPS/MIPSSecondPass.fs b/src/Peripheral/Assembly/MIPS/MIPSSecondPass.fs similarity index 96% rename from src/Assembler/MIPS/MIPSSecondPass.fs rename to src/Peripheral/Assembly/MIPS/MIPSSecondPass.fs index 5c24b5f7..4638ec41 100644 --- a/src/Assembler/MIPS/MIPSSecondPass.fs +++ b/src/Peripheral/Assembly/MIPS/MIPSSecondPass.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -module B2R2.Assembler.MIPS.SecondPass +module B2R2.Peripheral.Assembly.MIPS.SecondPass open B2R2 -open B2R2.FrontEnd.MIPS +open B2R2.FrontEnd.BinLifter.MIPS let updateOperands insAddress operandList labelToAddress = let rec doChecking operands (mapping: Map) result = diff --git a/src/Peripheral/Assembly/MIPS/README.md b/src/Peripheral/Assembly/MIPS/README.md new file mode 100644 index 00000000..a873359b --- /dev/null +++ b/src/Peripheral/Assembly/MIPS/README.md @@ -0,0 +1,11 @@ +# B2R2.Peripheral.Assembly.MIPS + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.Peripheral.Assembly.MIPS Package? + +`B2R2.Peripheral.Assembly.MIPS` includes our MIPS assembler. diff --git a/src/ROP/B2R2.ROP.fsproj b/src/ROP/B2R2.ROP.fsproj deleted file mode 100644 index 33680ed0..00000000 --- a/src/ROP/B2R2.ROP.fsproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - netstandard2.1 - false - false - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ROP/Simplify.fs b/src/ROP/Simplify.fs deleted file mode 100644 index 92ed5b8d..00000000 --- a/src/ROP/Simplify.fs +++ /dev/null @@ -1,231 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.ROP.Simplify - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.LowUIR - -let inline negNum x = BitVector.neg x |> Num - -let inline zeroNum ty = Num (BitVector.zero ty) - -let inline maxNum ty = - match ty with - | 8 -> BitVector.maxNum8 |> Num - | 16 -> BitVector.maxNum16 |> Num - | 32 -> BitVector.maxNum32 |> Num - | 64 -> BitVector.maxNum64 |> Num - | _ -> failwith "maxNum fail" - -let inline isZero x = - match x with - | Num n -> (BitVector.getValue n).IsZero - | _ -> false - -let inline isOne x = - match x with - | Num n -> (BitVector.getValue n).IsOne - | _ -> false - -let isFlippable x = (BitVector.isNegative x) && not (BitVector.isSignedMin x) - -let inline isMax ty e = - match e with - | Num n -> (BitVector.one ty |> BitVector.add n |> BitVector.getValue).IsZero - | _ -> false - -let inline binADD e1 e2 = AST.binop BinOpType.ADD e1 e2 - -let inline binSUB e1 e2 = AST.binop BinOpType.SUB e1 e2 - -let inline subNum n1 n2 = BitVector.sub n1 n2 |> Num - -let inline addNum n1 n2 = BitVector.add n1 n2 |> Num - -let rec simplify expr = - match expr with - | UnOp (op, e1, _, _) -> AST.unop op <| simplify e1 - | BinOp (op, ty, e1, e2, _, _) -> simplifyBinOp op ty e1 e2 - | RelOp (op, e1, e2, _, _) -> AST.relop op (simplify e1) (simplify e2) - | Load (endian, ty, e1, _, _) -> AST.load endian ty <| simplify e1 - | Ite (e1, e2, e3, _, _) -> AST.ite (simplify e1) (simplify e2) (simplify e3) - | Cast (kind, ty, e1, _, _) -> simplifyCast kind ty e1 - | expr -> expr (* Var, TempVar, Num, Name, PCVar *) - -and simplifyBinOp op ty e1 e2 = - match op, e1, e2 with - | BinOpType.XOR, e1, e2 when e1 = e2 -> zeroNum ty - | BinOpType.XOR, e1, e2 when isZero e1 -> simplify e2 - | BinOpType.XOR, e1, e2 when isZero e2 -> simplify e1 - | BinOpType.AND, e1, e2 when e1 = e2 -> simplify e1 - | BinOpType.AND, e1, e2 when isMax ty e1 -> simplify e2 - | BinOpType.AND, e1, e2 when isMax ty e2 -> simplify e1 - | BinOpType.AND, e1, e2 when isZero e1 || isZero e2 -> zeroNum ty - | BinOpType.OR, e1, e2 when e1 = e2 -> simplify e1 - | BinOpType.OR, e1, e2 when isZero e1 -> simplify e2 - | BinOpType.OR, e1, e2 when isZero e2 -> simplify e1 - | BinOpType.OR, e1, e2 when isMax ty e1 || isMax ty e2 -> maxNum ty - | op, e1, e2 when isZero e1 && (op = BinOpType.ADD || op = BinOpType.SUB) -> - simplify e2 - | op, e1, e2 when isZero e2 && (op = BinOpType.ADD || op = BinOpType.SUB) -> - simplify e1 - | BinOpType.ADD, Num (n1), e2 when isFlippable n1 -> - simplify (binSUB e2 (negNum n1)) - | BinOpType.ADD, e2, Num (n1) when isFlippable n1 -> - simplify (binSUB e2 (negNum n1)) - | BinOpType.SUB, e1, Num (n2) when isFlippable n2 -> - simplify (binADD e1 (negNum n2)) - | BinOpType.SUB, Num (n1), e2 when isFlippable n1 -> - simplify (binSUB e2 (negNum n1)) - (* ADD + ADD *) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, Num (n1), e2, _, _), - BinOp (BinOpType.ADD, _, Num (n3), e4, _, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, Num (n1), e2, _, _), - BinOp (BinOpType.ADD, _, e4, Num (n3), _, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, e2, Num (n1), _, _), - BinOp (BinOpType.ADD, _, Num (n3), e4, _, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, e2, Num (n1), _, _), - BinOp (BinOpType.ADD, _, e4, Num (n3), _, _) -> - simplify (binADD (binADD e2 e4) (addNum n1 n3)) - (* SUB + SUB *) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, Num (n1), e2, _, _), - BinOp (BinOpType.SUB, _, Num (n3), e4, _, _) -> - simplify (binSUB (addNum n1 n3) (binADD e2 e4)) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, Num (n1), e2, _, _), - BinOp (BinOpType.SUB, _, e3, Num (n4), _, _) -> - simplify (binADD (subNum n1 n4) (binSUB e3 e2)) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, e2, Num (n1), _, _), - BinOp (BinOpType.SUB, _, Num (n3), e4, _, _) -> - simplify (binADD (subNum n3 n1) (binSUB e2 e4)) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, e2, Num (n1), _, _), - BinOp (BinOpType.SUB, _, e4, Num (n3), _, _) -> - simplify (binSUB (binADD e2 e4) (addNum n1 n3)) - (* Num + Num *) - | BinOpType.ADD, Num (n1), Num (n2) -> addNum n1 n2 - (* ADD + Num, Num + ADD *) - | BinOpType.ADD, Num (n1), BinOp (BinOpType.ADD, _, Num (n2), e3, _, _) - | BinOpType.ADD, Num (n1), BinOp (BinOpType.ADD, _, e3, Num (n2), _, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, Num (n2), e3, _, _), Num (n1) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, e3, Num (n2), _, _), Num (n1) -> - simplify (binADD e3 (addNum n1 n2)) - (* Num + SUB, SUB + Num *) - | BinOpType.ADD, Num (n1), BinOp (BinOpType.SUB, _, Num (n2), e3, _, _) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, Num (n2), e3, _, _), Num (n1) -> - simplify (binSUB (addNum n1 n2) e3) - | BinOpType.ADD, Num (n1), BinOp (BinOpType.SUB, _, e2, Num (n3), _, _) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, e2, Num (n3), _, _), Num (n1) -> - simplify (binADD e2 (subNum n1 n3)) - (* SUB + ADD, ADD + SUB *) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, Num (n1), e2, _, _), - BinOp (BinOpType.ADD, _, Num (n3), e4, _, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, Num (n3), e4, _, _), - BinOp (BinOpType.SUB, _, Num (n1), e2, _, _) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, Num (n1), e2, _, _), - BinOp (BinOpType.ADD, _, e4, Num (n3), _, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, e4, Num (n3), _, _), - BinOp (BinOpType.SUB, _, Num (n1), e2, _, _) -> - simplify (binADD (addNum n1 n3) (binSUB e4 e2)) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, e1, Num (n2), _, _), - BinOp (BinOpType.ADD, _, Num (n3), e4, _, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, Num (n3), e4, _, _), - BinOp (BinOpType.SUB, _, e1, Num (n2), _, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, e4, Num (n3), _, _), - BinOp (BinOpType.SUB, _, e1, Num (n2), _, _) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, e1, Num (n2), _, _), - BinOp (BinOpType.ADD, _, e4, Num (n3), _, _) -> - simplify (binADD (subNum n3 n2) (binADD e1 e4)) - (* ADD - ADD *) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, Num (n1), e2, _, _), - BinOp (BinOpType.ADD, _, Num (n3), e4, _, _) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, Num (n1), e2, _, _), - BinOp (BinOpType.ADD, _, e4, Num (n3), _, _) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, Num (n1), _, _), - BinOp (BinOpType.ADD, _, Num (n3), e4, _, _) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, Num (n1), _, _), - BinOp (BinOpType.ADD, _, e4, Num (n3), _, _) -> - simplify (binADD (binSUB e2 e4) (subNum n1 n3)) - (* SUB - SUB *) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, Num (n1), e2, _, _), - BinOp (BinOpType.SUB, _, Num (n3), e4, _, _) -> - simplify (binSUB (subNum n1 n3) (binSUB e2 e4)) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, Num (n1), e2, _, _), - BinOp (BinOpType.SUB, _, e3, Num (n4), _, _) -> - simplify (binSUB (addNum n1 n4) (binADD e2 e3)) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, e2, Num (n1), _, _), - BinOp (BinOpType.SUB, _, Num (n3), e4, _, _) -> - simplify (binSUB (binADD e2 e4) (addNum n1 n3)) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, e2, Num (n1), _, _), - BinOp (BinOpType.SUB, _, e4, Num (n3), _, _) -> - simplify (binSUB (binSUB e2 e4) (subNum n1 n3)) - (* Num - Num *) - | BinOpType.SUB, Num (n1), Num (n2) -> subNum n1 n2 - (* ADD - Num, Num - ADD *) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, Num (n1), e2, _, _), Num (n3) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, Num (n1), _, _), Num (n3) -> - simplify (binADD (subNum n1 n3) e2) - | BinOpType.SUB, Num (n1), BinOp (BinOpType.ADD, _, Num (n2), e3, _, _) - | BinOpType.SUB, Num (n1), BinOp (BinOpType.ADD, _, e3, Num (n2), _, _) -> - simplify (binSUB (subNum n1 n2) e3) - (* SUB - Num, Num - SUB *) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, Num (n1), e2, _, _), Num (n3) -> - simplify (binSUB (subNum n1 n3) e2) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, e1, Num (n2), _, _), Num (n3) -> - simplify (binSUB e1 (addNum n2 n3)) - | BinOpType.SUB, Num (n1), BinOp (BinOpType.SUB, _, Num (n2), e3, _, _) -> - simplify (binADD e3 (subNum n1 n2)) - | BinOpType.SUB, Num (n1), BinOp (BinOpType.SUB, _, e2, Num (n3), _, _) -> - simplify (binSUB (addNum n1 n3) e2) - (* ADD - SUB, SUB - ADD *) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, Num (n1), e2, _, _), - BinOp (BinOpType.SUB, _, Num (n3), e4, _, _) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, Num (n1), _, _), - BinOp (BinOpType.SUB, _, Num (n3), e4, _, _) -> - simplify (binADD (subNum n1 n3) (binSUB e2 e4)) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, Num (n1), e2, _, _), - BinOp (BinOpType.SUB, _, e3, Num (n4), _, _) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, Num (n1), _, _), - BinOp (BinOpType.SUB, _, e3, Num (n4), _, _) -> - simplify (binADD (addNum n1 n4) (binSUB e2 e3)) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, e1, Num (n2), _, _), - BinOp (BinOpType.ADD, _, Num (n3), e4, _, _) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, e1, Num (n2), _, _), - BinOp (BinOpType.ADD, _, e4, Num (n3), _, _) -> - simplify (binSUB (binSUB e1 e4) (addNum n2 n3)) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, Num (n1), e2, _, _), - BinOp (BinOpType.ADD, _, Num (n3), e4, _, _) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, Num (n1), e2, _, _), - BinOp (BinOpType.ADD, _, e4, Num (n3), _, _) -> - simplify (binSUB (subNum n1 n3) (binADD e2 e4)) - | BinOpType.SUB, e1, e2 when e1 = e2 -> zeroNum ty - | BinOpType.MUL, e1, e2 when isOne e1 -> simplify e2 - | BinOpType.MUL, e1, e2 when isOne e2 -> simplify e1 - | BinOpType.MUL, e1, e2 when isZero e1 || isZero e2 -> zeroNum ty - | _, _, _ -> AST.binop op (simplify e1) (simplify e2) - -and simplifyCast kind ty e1 = - match kind, e1 with - | CastKind.ZeroExt, Num n -> BitVector.zext n ty |> Num - | _, _ -> AST.cast kind ty <| simplify e1 diff --git a/src/RearEnd/Assembler/B2R2.RearEnd.Assembler.fsproj b/src/RearEnd/Assembler/B2R2.RearEnd.Assembler.fsproj new file mode 100644 index 00000000..9aad8d1c --- /dev/null +++ b/src/RearEnd/Assembler/B2R2.RearEnd.Assembler.fsproj @@ -0,0 +1,26 @@ + + + + Exe + net5.0 + false + + + + + + + + + + + + + + + + + + + + diff --git a/src/Utilities/FileViewer/CmdOptions.fs b/src/RearEnd/Assembler/Cmd.fs similarity index 53% rename from src/Utilities/FileViewer/CmdOptions.fs rename to src/RearEnd/Assembler/Cmd.fs index 946443b4..935afb29 100644 --- a/src/Utilities/FileViewer/CmdOptions.fs +++ b/src/RearEnd/Assembler/Cmd.fs @@ -22,46 +22,71 @@ SOFTWARE. *) -module B2R2.Utilities.FileViewer.CmdOptions +namespace B2R2.RearEnd.Assembler -open B2R2 -open B2R2.Utilities open System +open B2R2 +open B2R2.RearEnd + +type AssemblerMode = + | LowUIRMode of ISA + | GeneralMode of ISA + +module private AssemblerMode = + let toLowUIRMode = function + | LowUIRMode isa + | GeneralMode isa -> LowUIRMode isa + + let changeISA isa = function + | LowUIRMode _ -> LowUIRMode isa + | GeneralMode _ -> GeneralMode isa -type FileViewerOpts () = - inherit CmdOpts () +type AssemblerOpts () = + inherit CmdOpts() - /// Specify ISA. This is only meaningful for universal (fat) binaries because - /// BinHandler will automatically detect file format by default. When a fat - /// binary is given, we need to choose which architecture to explorer with - /// this option. - member val ISA = ISA.DefaultISA with get, set + /// Mode + member val Mode = GeneralMode ISA.DefaultISA with get, set /// Base address member val BaseAddress: Addr = 0UL with get, set static member private ToThis (opts: CmdOpts) = match opts with - | :? FileViewerOpts as opts -> opts + | :? AssemblerOpts as opts -> opts | _ -> failwith "Invalid Opts." - /// "-a" or "--isa" option for specifying ISA. + /// "-l" or "--lowuir" option for LowUIR mode + static member OptLowUIR () = + let cb (opts: #CmdOpts) (_arg: string []) = + (AssemblerOpts.ToThis opts).Mode <- + AssemblerMode.toLowUIRMode (AssemblerOpts.ToThis opts).Mode + opts + CmdOpts.New ( descr = "Take in LowUIR assembly code as input (ignore ISA)", + callback = cb, short = "-l", long= "--lowuir" ) + + /// "-i" or "--isa" option for specifying ISA. static member OptISA () = let cb (opts: #CmdOpts) (arg: string []) = - (FileViewerOpts.ToThis opts).ISA <- ISA.OfString arg.[0]; opts - CmdOpts.New ( descr = "Specify (e.g., x86) for fat binaries", - extra = 1, callback = cb, short = "-a", long= "--isa" ) + (AssemblerOpts.ToThis opts).Mode <- + AssemblerMode.changeISA (ISA.OfString arg.[0]) + (AssemblerOpts.ToThis opts).Mode + opts + CmdOpts.New ( descr = "Specify (e.g., x86) from command line", + extra = 1, callback = cb, short = "-i", long= "--isa" ) /// "-r" or "--base-addr" option for specifying a base address. static member OptBaseAddr () = let cb (opts: #CmdOpts) (arg: string []) = - (FileViewerOpts.ToThis opts).BaseAddress <- Convert.ToUInt64 (arg.[0], 16) + (AssemblerOpts.ToThis opts).BaseAddress <- Convert.ToUInt64 (arg.[0], 16) opts CmdOpts.New ( descr = "Specify the base
in hex (default=0)", extra = 1, callback = cb, short = "-r", long = "--base-addr" ) -let spec: FileViewerOpts FsOptParse.Option list = - [ FileViewerOpts.OptISA () - FileViewerOpts.OptBaseAddr () - CmdOpts.OptVerbose () - CmdOpts.OptHelp () ] +module Cmd = + let spec: AssemblerOpts FsOptParse.Option list = + [ CmdOpts.OptVerbose () + CmdOpts.OptHelp () + + AssemblerOpts.OptLowUIR () + AssemblerOpts.OptISA () + AssemblerOpts.OptBaseAddr () ] diff --git a/src/RearEnd/Assembler/Program.fs b/src/RearEnd/Assembler/Program.fs new file mode 100644 index 00000000..d8720248 --- /dev/null +++ b/src/RearEnd/Assembler/Program.fs @@ -0,0 +1,107 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.RearEnd.Assembler.Program + +open System +open B2R2 +open B2R2.FrontEnd.BinInterface +open B2R2.RearEnd +open B2R2.BinIR.LowUIR +open B2R2.Peripheral.Assembly + +/// The console printer. +let internal out = ConsolePrinter () :> Printer + +let [] private normalPrompt = "> " + +let private printIns hdl addr bs = + let bCode = (BitConverter.ToString (bs)).Replace ("-", "") + let hdl = BinHandle.UpdateCode hdl addr bs + let ins = BinHandle.ParseInstr (hdl, addr) + out.PrintLine (sprintf "%08x: %-20s %s" addr bCode (ins.Disasm ())) + addr + uint64 (Array.length bs) + +let inline private printResult fn = function + | Ok res -> fn res + | Error err -> Printer.printErrorToConsole err + +let getAssemblyPrinter (opts: AssemblerOpts) = + match opts.Mode with + | GeneralMode (isa) -> + let hdl = BinHandle.Init (isa) + let baseAddr = opts.BaseAddress + let asm = AsmInterface (hdl, baseAddr) + fun str -> + asm.AssembleBin str + |> printResult (fun res -> + List.fold (printIns hdl) baseAddr res + |> ignore) + | LowUIRMode (isa) -> + let asm = AsmInterface (isa, opts.BaseAddress) + fun str -> + asm.LiftLowUIR true str + |> printResult (Array.iter (Pp.stmtToString >> out.PrintLine)) + +let rec private asmFromStdin (console: FsReadLine.Console) printer str = + match console.ReadLine () with + | "" -> asmFromStdin console printer str + | input when isNull input || input = "q" || input = "quit" -> + out.PrintLine ("Bye!") + out.Flush () + | input -> + let input = input.Trim () + let str = + if input.EndsWith (";;") then + console.UpdatePrompt normalPrompt + printer <| str + input.TrimEnd (';') + "" + else + console.UpdatePrompt " " + str + input + Environment.NewLine + asmFromStdin console printer str + +let showBasicInfo (opts: AssemblerOpts) = + match opts.Mode with + | GeneralMode (isa) -> + out.PrintLine [ Blue, ISA.ArchToString isa.Arch; Green, " General Mode" ] + | LowUIRMode (isa) -> + out.PrintLine [ Blue, ISA.ArchToString isa.Arch ; Green, " LowUIR Mode" ] + +let private asmFromFiles files printer = + files + |> List.iter (fun file -> IO.File.ReadAllText file |> printer) + +let asmMain files opts = + let printer = getAssemblyPrinter opts + if List.isEmpty files then + let console = FsReadLine.Console (normalPrompt, ["quit"]) + showBasicInfo opts + asmFromStdin console printer "" + else asmFromFiles files printer + +[] +let main args = + let opts = AssemblerOpts () + CmdOpts.ParseAndRun asmMain "assembler" "" Cmd.spec opts args diff --git a/src/RearEnd/BinDump/B2R2.RearEnd.BinDump.fsproj b/src/RearEnd/BinDump/B2R2.RearEnd.BinDump.fsproj new file mode 100644 index 00000000..05420099 --- /dev/null +++ b/src/RearEnd/BinDump/B2R2.RearEnd.BinDump.fsproj @@ -0,0 +1,20 @@ + + + + Exe + net5.0 + false + + + + + + + + + + + + + + diff --git a/src/RearEnd/BinDump/Cmd.fs b/src/RearEnd/BinDump/Cmd.fs new file mode 100644 index 00000000..b5f60d79 --- /dev/null +++ b/src/RearEnd/BinDump/Cmd.fs @@ -0,0 +1,233 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.BinDump + +open B2R2 +open B2R2.RearEnd +open System + +type OptOption = + | NoOptimize + | Optimize + +type BinDumpOpts () = + inherit CmdOpts () + /// ISA + member val ISA = ISA.DefaultISA with get, set + + /// Base address + member val BaseAddress: Addr option = None with get, set + + /// Input section name from command line. + member val InputSecName: string option = None with get, set + + /// Input hexstring from command line. + member val InputHexStr: byte [] = [||] with get, set + + /// ArchOperationMode + member val ArchOperationMode = ArchOperationMode.NoMode with get, set + + /// Whether to show addresses or not + member val ShowAddress = false with get, set + + /// Show symbols or not? + member val ShowSymbols = false with get, set + + /// Show LowUIR or not? + member val ShowLowUIR = false with get, set + + /// Show hexdump widely or not, 32 bytes (default 16 bytes) + member val ShowWide = false with get, set + + /// Show hexdump colored or not, just for files not hexstring + member val ShowColor = false with get, set + + /// Display only disassembly. + member val OnlyDisasm = false with get, set + + /// Perform basic block optimization or not? + member val DoOptimization = NoOptimize with get, set + + /// Discover binary file format or not? + member val AutoDetect = true with get, set + + static member private ToThis (opts: CmdOpts) = + match opts with + | :? BinDumpOpts as opts -> opts + | _ -> failwith "Invalid Opts." + + /// "-h" or "--help" option. + static member OptHelp () = + CmdOpts.New (descr = "Show this usage", help = true, long = "--help") + + /// "-i" or "--isa" option for specifying ISA. + static member OptISA () = + let cb opts (arg: string []) = + (BinDumpOpts.ToThis opts).ISA <- ISA.OfString arg.[0] + opts + CmdOpts.New (descr = "Specify (e.g., x86) from command line", + extra = 1, callback = cb, short = "-i", long = "--isa") + + /// "-r" or "--base-addr" option for specifying a base address. + static member OptBaseAddr () = + let cb opts (arg: string []) = + (BinDumpOpts.ToThis opts).BaseAddress <- + Some (Convert.ToUInt64 (arg.[0], 16)) + (BinDumpOpts.ToThis opts).ShowAddress <- true + opts + CmdOpts.New (descr = "Specify the base
in hex (default=0)", + extra = 1, callback = cb, short = "-r", long = "--base-addr") + + /// "--only-disasm" option for forcefully showing disassembly for all + /// sections. + static member OptOnlyDisasm () = + let cb opts (arg: string []) = + (BinDumpOpts.ToThis opts).OnlyDisasm <- true + opts + CmdOpts.New ( + descr = "Always display disassembly for all sections.", + callback = cb, long = "--only-disasm") + + /// "-S" or "--section" for displaying contents of a specific section. + static member OptDumpSection () = + let cb opts (arg: string []) = + (BinDumpOpts.ToThis opts).InputSecName <- Some arg.[0] + opts + CmdOpts.New ( + descr = "Display the contents of a specific section", + extra = 1, callback = cb, short = "-S", long = "--section") + + /// "-s" option for specifying an input hexstring. + static member OptInputHexString () = + let cb opts (arg: string []) = + (BinDumpOpts.ToThis opts).InputHexStr <- ByteArray.ofHexString arg.[0] + opts + CmdOpts.New (descr = "Specify an input from command line", + extra = 1, callback = cb, short = "-s") + + /// "-m" or "--mode" option for specifying ArchOperationMode. + static member OptArchMode () = + let cb opts (arg: string []) = + (BinDumpOpts.ToThis opts).ArchOperationMode <- + ArchOperationMode.ofString arg.[0] + opts + CmdOpts.New ( + descr = "Specify (e.g., thumb/arm) from cmdline", + extra = 1, callback = cb, short = "-m", long = "--mode") + + /// "--show-addr" option decides whether to show addresses of hexstring. + static member OptShowAddr () = + let cb opts _ = + (BinDumpOpts.ToThis opts).ShowAddress <- true + opts + CmdOpts.New (descr = "Show addresses of hexstring", + callback = cb, long = "--show-addr") + + /// "--show-symbols" option decides whether to show symbols in disassembly. + static member OptShowSymbols () = + let cb opts _ = + (BinDumpOpts.ToThis opts).ShowSymbols <- true + opts + CmdOpts.New (descr = "Show symbols while disassembling binary", + callback = cb, long = "--show-symbols") + + /// "--show-wide" option decides whether to show hexdump with 32 bytes. + static member OptShowWide () = + let cb opts _ = + (BinDumpOpts.ToThis opts).ShowWide <- true + opts + CmdOpts.New (descr = "Show hexdump with 32 bytes long", + callback = cb, long = "--show-wide") + + /// "--show-color" option decides whether to show colored hexdump. + static member OptShowColor () = + let cb opts _ = + (BinDumpOpts.ToThis opts).ShowColor <- true + opts + CmdOpts.New (descr = "Show colored hexdump", + callback = cb, long = "--show-color") + + /// "--lift" option decides whether to show LowUIR of excutable sections. + static member OptShowLowUIR () = + let cb opts _ = + (BinDumpOpts.ToThis opts).ShowLowUIR <- true + opts + CmdOpts.New (descr = "Show LowUIR of excutable sections", + callback = cb, long = "--lift") + + static member OptTransOptimization () = + let cb opts _ = + (BinDumpOpts.ToThis opts).DoOptimization <- Optimize + opts + CmdOpts.New (descr = "Perform bblock optimization for IL", + callback = cb, long = "--optimize") + + static member OptRawBinary () = + let cb opts _ = + (BinDumpOpts.ToThis opts).AutoDetect <- false + opts + CmdOpts.New (descr = "Turn off file format detection", + callback = cb, long = "--raw-binary") + +[] +module Cmd = + let spec: BinDumpOpts FsOptParse.Option list = + [ CmdOpts.New (descr = "[General options]", dummy = true) + CmdOpts.New (descr = "", dummy = true) + + BinDumpOpts.OptHelp () + CmdOpts.OptVerbose () + BinDumpOpts.OptISA () + BinDumpOpts.OptBaseAddr () + + CmdOpts.New (descr = "", dummy = true) + CmdOpts.New (descr = "[Input Configuration]", dummy = true) + CmdOpts.New (descr = "", dummy = true) + + BinDumpOpts.OptInputHexString () + BinDumpOpts.OptArchMode () + BinDumpOpts.OptRawBinary () + + CmdOpts.New (descr = "", dummy = true) + CmdOpts.New (descr = "[Output Configuration]", dummy = true) + CmdOpts.New (descr = "", dummy = true) + + BinDumpOpts.OptDumpSection () + BinDumpOpts.OptOnlyDisasm () + BinDumpOpts.OptShowAddr () + BinDumpOpts.OptShowSymbols () + BinDumpOpts.OptShowWide () + BinDumpOpts.OptShowColor () + BinDumpOpts.OptShowLowUIR () + + CmdOpts.New (descr = "", dummy = true) + CmdOpts.New (descr = "[Optional Configuration]", dummy = true) + CmdOpts.New (descr = "", dummy = true) + + BinDumpOpts.OptTransOptimization () + + CmdOpts.New (descr = "", dummy = true) ] + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/RearEnd/BinDump/DisasmLiftHelper.fs b/src/RearEnd/BinDump/DisasmLiftHelper.fs new file mode 100644 index 00000000..293751e2 --- /dev/null +++ b/src/RearEnd/BinDump/DisasmLiftHelper.fs @@ -0,0 +1,247 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.RearEnd.BinDump.DisasmLiftHelper + +open System.Collections.Generic +open B2R2 +open B2R2.BinIR +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinInterface + +/// The monotonic console printer. +let internal out = ConsoleCachedPrinter () :> Printer + +/// The colorful console printer. +let internal colorout = ConsolePrinter () :> Printer + +let [] illegalStr = "(illegal)" + +let getOptimizer (opts: BinDumpOpts) = + match opts.DoOptimization with + | NoOptimize -> id + | Optimize -> BinHandle.Optimize + +let makeFuncSymbolDic hdl = + let funcs = Dictionary () + hdl.FileInfo.GetFunctionSymbols () + |> Seq.iter (fun s -> funcs.Add (s.Address, s.Name) |> ignore) + hdl.FileInfo.GetFunctionAddresses () + |> Seq.iter (fun a -> + if funcs.ContainsKey a then () + else funcs.[a] <- Addr.toFuncName a) + funcs + +let makeLinkageTblSymbolDic hdl = + let funcs = Dictionary () + hdl.FileInfo.GetLinkageTableEntries () + |> Seq.iter (fun e -> + if e.TrampolineAddress = 0UL then () + else funcs.TryAdd (e.TrampolineAddress, e.FuncName) |> ignore) + funcs + +let makeArchModeDic hdl = + let modes = Dictionary () + match hdl.FileInfo.FileFormat, hdl.ISA.Arch with + | FileFormat.ELFBinary, Arch.ARMv7 + | FileFormat.ELFBinary, Arch.AARCH32 -> + hdl.FileInfo.GetSymbols () + |> Seq.iter (fun s -> + if s.ArchOperationMode <> ArchOperationMode.NoMode then + modes.[s.Address] <- s.ArchOperationMode + else ()) + | _ -> () + modes + +let getInstructionAlignment hdl = + match hdl.ISA.Arch with + | Arch.IntelX86 | Arch.IntelX64 -> 1 + | Arch.ARMv7 | Arch.AARCH32 -> + match hdl.Parser.OperationMode with + | ArchOperationMode.ThumbMode -> 2 + | _ -> 4 + | Arch.AARCH64 -> 4 + | Arch.MIPS1 | Arch.MIPS2 | Arch.MIPS3 | Arch.MIPS4 | Arch.MIPS5 + | Arch.MIPS32 | Arch.MIPS32R2 | Arch.MIPS32R6 + | Arch.MIPS64 | Arch.MIPS64R2 | Arch.MIPS64R6 -> 4 + | Arch.EVM -> 1 + | Arch.AVR -> 2 + | _ -> Utils.futureFeature () + +let convertToHexStr bytes = + bytes + |> Array.fold (fun s (b: byte) -> + if String.length s = 0 then b.ToString ("X2") + else s + " " + b.ToString ("X2")) "" + +let printLowUIR (lowUIRStr: string) bytes cfg = + let hexStr = convertToHexStr bytes |> String.wrapSqrdBracket + out.PrintRow (false, cfg, [ hexStr ]) + out.PrintRow (false, cfg, [ lowUIRStr ]) + +let printRegularDisasm disasmStr wordSize addr bytes cfg = + let hexStr = convertToHexStr bytes + let addrStr = Addr.toString wordSize addr + ":" + out.PrintRow (false, cfg, [ addrStr; hexStr; disasmStr ]) + +let regularDisPrinter (hdl: BinHandle) showSymbs bp ins cfg = + let disasmStr = BinHandle.DisasmInstr hdl false showSymbs ins + let wordSize = hdl.FileInfo.WordSize + let bytes = BinHandle.ReadBytes (hdl, bp=bp, nBytes=int ins.Length) + printRegularDisasm disasmStr wordSize bp.Addr bytes cfg + +let regularIRPrinter (hdl: BinHandle) optimizer bp ins cfg = + let stmts = optimizer (BinHandle.LiftInstr hdl ins) + let lowUIRStr = LowUIR.Pp.stmtsToString stmts + let bytes = BinHandle.ReadBytes (hdl, bp=bp, nBytes=int ins.Length) + printLowUIR lowUIRStr bytes cfg + +let convertToDisasmStr (words: AsmWord []) = + words + |> Array.choose (fun word -> + match word.AsmWordKind with + | AsmWordKind.Address -> None + | AsmWordKind.Mnemonic -> Some [ Green, word.AsmWordValue ] + | AsmWordKind.Variable -> Some [ Blue, word.AsmWordValue ] + | AsmWordKind.Value -> Some [ Red, word.AsmWordValue ] + | _ -> Some [ NoColor, word.AsmWordValue ]) + |> List.concat + +let printColorDisasm words wordSize addr bytes cfg = + out.Flush () + let hexStr = convertToHexStr bytes + let addrStr = Addr.toString wordSize addr + ":" + let disasStr = convertToDisasmStr words + colorout.PrintRow (false, cfg, + [ [ Green, addrStr ]; [ NoColor, hexStr ]; disasStr ]) + +let colorDisPrinter (hdl: BinHandle) _ bp (ins: Instruction) cfg = + let words = ins.Decompose (false) + let wordSize = hdl.FileInfo.WordSize + let bytes = BinHandle.ReadBytes (hdl, bp=bp, nBytes=int ins.Length) + printColorDisasm words wordSize bp.Addr bytes cfg + +let handleInvalidIns (hdl: BinHandle) bp isLift cfg = + let wordSize = hdl.FileInfo.WordSize + let align = getInstructionAlignment hdl + let bytes = BinHandle.ReadBytes (hdl, bp=bp, nBytes=align) + if isLift then printLowUIR illegalStr bytes cfg + else printRegularDisasm illegalStr wordSize bp.Addr bytes cfg + BinaryPointer.Advance bp align + +let printFuncSymbol (dict: Dictionary) addr = + match (dict: Dictionary).TryGetValue (addr) with + | true, name -> + out.PrintLineIfPrevLineWasNotEmpty () + out.PrintLine (String.wrapAngleBracket name) + | false, _ -> () + +let updateMode dict hdl addr = + match (dict: Dictionary).TryGetValue addr with + | true, mode -> hdl.Parser.OperationMode <- mode + | false, _ -> () + +type ISymbolPrinter = + abstract member PrintSymbol: Addr -> unit + +type IInstrPrinter = + abstract member PrintInstr: BinHandle -> BinaryPointer -> Instruction -> unit + +[] +type BinPrinter (hdl, cfg, isLift) = + abstract member PrintFuncSymbol: Addr -> unit + abstract member PrintInstr: BinHandle -> BinaryPointer -> Instruction -> unit + abstract member UpdateMode: BinHandle -> Addr -> unit + + member __.Print bp = + if BinaryPointer.IsValid bp then + __.PrintFuncSymbol bp.Addr + __.UpdateMode hdl bp.Addr + match BinHandle.TryParseInstr (hdl, bp=bp) with + | Ok (ins) -> + __.PrintInstr hdl bp ins + let bp' = BinaryPointer.Advance bp (int ins.Length) + __.Print bp' + | Error _ -> + __.Print (handleInvalidIns hdl bp isLift cfg) + else () + +[] +type BinFuncPrinter (hdl, cfg, isLift) = + inherit BinPrinter (hdl, cfg, isLift) + let dict = makeFuncSymbolDic hdl + override _.PrintFuncSymbol addr = printFuncSymbol dict addr + +[] +type BinTablePrinter (hdl, cfg, isLift) = + inherit BinPrinter (hdl, cfg, isLift) + let dict = makeLinkageTblSymbolDic hdl + override _.PrintFuncSymbol addr = printFuncSymbol dict addr + +type BinCodeDisasmPrinter (hdl, cfg, showSym, showColor) = + inherit BinFuncPrinter (hdl, cfg, false) + let disPrinter = if showColor then colorDisPrinter else regularDisPrinter + override _.PrintInstr hdl bp ins = disPrinter hdl showSym bp ins cfg + override _.UpdateMode _ _ = () + +type BinCodeIRPrinter (hdl, cfg, optimizer) = + inherit BinFuncPrinter (hdl, cfg, true) + override _.PrintInstr hdl bp ins = regularIRPrinter hdl optimizer bp ins cfg + override _.UpdateMode _ _ = () + +type BinTableDisasmPrinter (hdl, cfg) = + inherit BinTablePrinter (hdl, cfg, false) + override _.PrintInstr hdl bp ins = regularDisPrinter hdl true bp ins cfg + override _.UpdateMode _ _ = () + +type BinTableIRPrinter (hdl, cfg, optimizer) = + inherit BinTablePrinter (hdl, cfg, true) + override _.PrintInstr hdl bp ins = regularIRPrinter hdl optimizer bp ins cfg + override _.UpdateMode _ _ = () + +type ContextSensitiveCodeDisasmPrinter (hdl, cfg, showSym, showColor) = + inherit BinFuncPrinter (hdl, cfg, false) + let disPrinter = if showColor then colorDisPrinter else regularDisPrinter + let archmodes = makeArchModeDic hdl + override _.PrintInstr hdl bp ins = disPrinter hdl showSym bp ins cfg + override _.UpdateMode hdl addr = updateMode archmodes hdl addr + +type ContextSensitiveCodeIRPrinter (hdl, cfg, optimizer) = + inherit BinFuncPrinter (hdl, cfg, true) + let archmodes = makeArchModeDic hdl + override _.PrintInstr hdl bp ins = regularIRPrinter hdl optimizer bp ins cfg + override _.UpdateMode hdl addr = updateMode archmodes hdl addr + +type ContextSensitiveTableDisasmPrinter (hdl, cfg) = + inherit BinTablePrinter (hdl, cfg, false) + let archmodes = makeArchModeDic hdl + override _.PrintInstr hdl bp ins = regularDisPrinter hdl true bp ins cfg + override _.UpdateMode hdl addr = updateMode archmodes hdl addr + +type ContextSensitiveTableIRPrinter (hdl, cfg, optimizer) = + inherit BinTablePrinter (hdl, cfg, true) + let archmodes = makeArchModeDic hdl + override _.PrintInstr hdl bp ins = regularIRPrinter hdl optimizer bp ins cfg + override _.UpdateMode hdl addr = updateMode archmodes hdl addr diff --git a/src/RearEnd/BinDump/Program.fs b/src/RearEnd/BinDump/Program.fs new file mode 100644 index 00000000..34a096a3 --- /dev/null +++ b/src/RearEnd/BinDump/Program.fs @@ -0,0 +1,221 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.RearEnd.BinDump.Program + +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinInterface +open B2R2.RearEnd +open B2R2.RearEnd.BinDump.DisasmLiftHelper + +let [] private toolName = "bindump" +let [] private usageTail = "" + +let private printFileName (filepath: string) = + out.PrintLine (String.wrapSqrdBracket filepath) + out.PrintLine () + +let private getTableConfig hdl isLift = + if isLift then [ LeftAligned 10 ] + else + let addrWidth = WordSize.toByteWidth hdl.ISA.WordSize * 2 + let binaryWidth = + match hdl.ISA.Arch with + | Arch.IntelX86 | Arch.IntelX64 -> 36 + | _ -> 16 + [ LeftAligned addrWidth; LeftAligned binaryWidth; LeftAligned 10 ] + +let private isARM32 hdl = + match hdl.ISA.Arch with + | Arch.ARMv7 + | Arch.AARCH32 -> true + | _ -> false + +let private makeCodePrinter hdl cfg (opts: BinDumpOpts) = + let opti = getOptimizer opts + if isARM32 hdl then + if opts.ShowLowUIR then + ContextSensitiveCodeIRPrinter (hdl, cfg, opti) :> BinPrinter + else + let showSymb, showColor = opts.ShowSymbols, opts.ShowColor + ContextSensitiveCodeDisasmPrinter (hdl, cfg, showSymb, showColor) + :> BinPrinter + else + if opts.ShowLowUIR then BinCodeIRPrinter (hdl, cfg, opti) :> BinPrinter + else + let showSymb, showColor = opts.ShowSymbols, opts.ShowColor + BinCodeDisasmPrinter (hdl, cfg, showSymb, showColor) :> BinPrinter + +let private makeTablePrinter hdl cfg (opts: BinDumpOpts) = + let opti = getOptimizer opts + if isARM32 hdl then + if opts.ShowLowUIR then + ContextSensitiveTableIRPrinter (hdl, cfg, opti) :> BinPrinter + else + ContextSensitiveTableDisasmPrinter (hdl, cfg) :> BinPrinter + else + if opts.ShowLowUIR then BinTableIRPrinter (hdl, cfg, opti) :> BinPrinter + else BinTableDisasmPrinter (hdl, cfg) :> BinPrinter + +let private dumpRawBinary (hdl: BinHandle) (opts: BinDumpOpts) cfg = + let bp = hdl.FileInfo.ToBinaryPointer hdl.FileInfo.BaseAddress + let prn = makeCodePrinter hdl cfg opts + prn.Print bp + out.PrintLine () + +let printHexdump (opts: BinDumpOpts) sec hdl = + let bp = BinaryPointer.OfSection sec + let bytes = BinHandle.ReadBytes (hdl, bp=bp, nBytes=int sec.Size) + let chunkSize = if opts.ShowWide then 32 else 16 + HexDumper.dump chunkSize hdl.FileInfo.WordSize opts.ShowColor bp.Addr bytes + |> Array.iter out.PrintLine + +let private hasNoContent (sec: Section) (fi: FileInfo) = + match fi with + | :? ELFFileInfo as fi -> + match fi.ELF.SecInfo.SecByName.TryFind sec.Name with + | Some section -> section.SecType = ELF.SectionType.SHTNoBits + | None -> true + | _ -> false + +let dumpHex (opts: BinDumpOpts) (sec: Section) hdl = + if hasNoContent sec hdl.FileInfo then + out.PrintTwoCols "" "NOBITS section." + else printHexdump opts sec hdl + out.PrintLine () + +let private createBinHandleFromPath (opts: BinDumpOpts) filepath = + BinHandle.Init ( + opts.ISA, + opts.ArchOperationMode, + opts.AutoDetect, + opts.BaseAddress, + fileName=filepath) + +let private isRawBinary hdl = + match hdl.FileInfo.FileFormat with + | FileFormat.ELFBinary + | FileFormat.MachBinary + | FileFormat.PEBinary -> false + | _ -> true + +let private printCodeOrTable (printer: BinPrinter) sec = + printer.Print (BinaryPointer.OfSection sec) + out.PrintLine () + +let initHandleForTableOutput hdl = + match hdl.ISA.Arch with + (* For ARM PLTs, we just assume the ARM mode (if no symbol is given). *) + | Arch.ARMv7 + | Arch.AARCH32 -> hdl.Parser.OperationMode <- ArchOperationMode.ARMMode + | _ -> () + +let private dumpSections hdl (opts: BinDumpOpts) (sections: seq
) cfg = + let mymode = hdl.Parser.OperationMode + let codeprn = makeCodePrinter hdl cfg opts + let tableprn = makeTablePrinter hdl cfg opts + sections + |> Seq.iter (fun s -> + if s.Size > 0UL then + out.PrintSectionTitle (String.wrapParen s.Name) + match s.Kind with + | SectionKind.ExecutableSection -> + hdl.Parser.OperationMode <- mymode + printCodeOrTable codeprn s + | SectionKind.LinkageTableSection -> + initHandleForTableOutput hdl + printCodeOrTable tableprn s + | _ -> + if opts.OnlyDisasm then printCodeOrTable codeprn s + else dumpHex opts s hdl + else ()) + +let private dumpRegularFile hdl (opts: BinDumpOpts) cfg = + opts.ShowSymbols <- true + match opts.InputSecName with + | Some secname -> + dumpSections hdl opts (hdl.FileInfo.GetSections (secname)) cfg + | None -> + dumpSections hdl opts (hdl.FileInfo.GetSections ()) cfg + +let dumpFile (opts: BinDumpOpts) filepath = + opts.ShowAddress <- true + let hdl = createBinHandleFromPath opts filepath + let cfg = getTableConfig hdl opts.ShowLowUIR + printFileName hdl.FileInfo.FilePath + if isRawBinary hdl then dumpRawBinary hdl opts cfg + else dumpRegularFile hdl opts cfg + +let dumpFileMode files (opts: BinDumpOpts) = + match List.partition System.IO.File.Exists files with + | [], [] -> + Printer.printErrorToConsole "File(s) must be given." + CmdOpts.PrintUsage toolName usageTail Cmd.spec + | files, [] -> files |> List.iter (dumpFile opts) + | _, errs -> + Printer.printErrorToConsole ("File(s) " + errs.ToString() + " not found!") + +let private assertBinaryLength hdl hexstr = + let multiplier = getInstructionAlignment hdl + if (Array.length hexstr) % multiplier = 0 then () + else + Printer.printErrorToConsole <| + "The hex string length must be multiple of " + multiplier.ToString () + exit 1 + +let dumpHexStringMode (opts: BinDumpOpts) = + let hdl = BinHandle.Init (opts.ISA, + opts.ArchOperationMode, + false, + opts.BaseAddress, + opts.InputHexStr) + let cfg = getTableConfig hdl opts.ShowLowUIR + assertBinaryLength hdl opts.InputHexStr + opts.ShowColor <- true + let printer = makeCodePrinter hdl cfg opts + let baseAddr = defaultArg opts.BaseAddress 0UL + let bp = BinaryPointer (baseAddr, 0, opts.InputHexStr.Length) + printer.Print bp + out.PrintLine () + +let private dump files (opts: BinDumpOpts) = +#if DEBUG + let sw = System.Diagnostics.Stopwatch.StartNew () +#endif + CmdOpts.SanitizeRestArgs files + try + if Array.isEmpty opts.InputHexStr then dumpFileMode files opts + else dumpHexStringMode opts + finally + out.Flush () +#if DEBUG + sw.Stop () + eprintfn "Total dump time: %f sec." sw.Elapsed.TotalSeconds +#endif + +[] +let main args = + let opts = BinDumpOpts () + CmdOpts.ParseAndRun dump toolName usageTail Cmd.spec opts args diff --git a/src/Utilities/BinExplorer/B2R2.Utilities.BinExplorer.fsproj b/src/RearEnd/BinExplorer/B2R2.RearEnd.BinExplorer.fsproj similarity index 59% rename from src/Utilities/BinExplorer/B2R2.Utilities.BinExplorer.fsproj rename to src/RearEnd/BinExplorer/B2R2.RearEnd.BinExplorer.fsproj index 5f51132f..25ce6c6c 100644 --- a/src/Utilities/BinExplorer/B2R2.Utilities.BinExplorer.fsproj +++ b/src/RearEnd/BinExplorer/B2R2.RearEnd.BinExplorer.fsproj @@ -1,10 +1,9 @@ - + Exe - netcoreapp3.0 + net5.0 false - false @@ -32,25 +31,22 @@ - + - - - - - - - - - + + + + + + - + diff --git a/src/Utilities/BinExplorer/BinInfo.fs b/src/RearEnd/BinExplorer/BinInfo.fs similarity index 89% rename from src/Utilities/BinExplorer/BinInfo.fs rename to src/RearEnd/BinExplorer/BinInfo.fs index ca91fe4a..36d8a2ea 100644 --- a/src/Utilities/BinExplorer/BinInfo.fs +++ b/src/RearEnd/BinExplorer/BinInfo.fs @@ -22,10 +22,11 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer open B2R2 -open B2R2.BinFile +open B2R2.FrontEnd.BinFile +open B2R2.MiddleEnd.BinEssence type CmdBinInfo () = inherit Cmd () @@ -45,11 +46,11 @@ type CmdBinInfo () = override __.SubCommands = [] override __.CallBack _ ess _args = - let fileInfo = ess.BinHandler.FileInfo - let path = ess.BinHandler.FileInfo.FilePath - let isa = ess.BinHandler.ISA + let fileInfo = ess.BinHandle.FileInfo + let path = ess.BinHandle.FileInfo.FilePath + let isa = ess.BinHandle.ISA let machine = isa.Arch |> ISA.ArchToString - let fmt = ess.BinHandler.FileInfo.FileFormat |> FileFormat.toString + let fmt = ess.BinHandle.FileInfo.FileFormat |> FileFormat.toString let entry = fileInfo.EntryPoint |> FileInfo.EntryPointToString let textAddr = fileInfo.TextStartAddr let secNum = fileInfo.GetSections () |> Seq.length @@ -70,5 +71,6 @@ type CmdBinInfo () = sprintf "- Number of Dynamic Symbols: %d" dynamicSymNum sprintf "- NX bit: %s" nx |] + |> Array.map OutputNormal // vim: set tw=80 sts=2 sw=2: diff --git a/src/Utilities/BinExplorer/CLI.fs b/src/RearEnd/BinExplorer/CLI.fs similarity index 89% rename from src/Utilities/BinExplorer/CLI.fs rename to src/RearEnd/BinExplorer/CLI.fs index 8733f110..231cb663 100644 --- a/src/Utilities/BinExplorer/CLI.fs +++ b/src/RearEnd/BinExplorer/CLI.fs @@ -22,20 +22,21 @@ SOFTWARE. *) -module internal B2R2.Utilities.BinExplorer.CLI +module internal B2R2.RearEnd.BinExplorer.CLI open B2R2 +open B2R2.RearEnd.BinExplorer.CmdUtils -let cliPrinter arbiter () line = - Protocol.logString arbiter line - System.Console.WriteLine line +let cliPrinter arbiter () (output: OutString) = + out.PrintLine output + OutString.toString output |> Protocol.logString arbiter let handle cmds arbiter (line: string) acc printer = match line.Split (' ') |> Array.toList with | cmd :: args -> let ess = Protocol.getBinEssence arbiter let acc = Cmd.handle cmds ess cmd args |> Array.fold (printer arbiter) acc - printer arbiter acc "" + printer arbiter acc (OutputNormal "") | [] -> acc let rec cliLoop cmds arbiter (console: FsReadLine.Console) = diff --git a/src/Utilities/BinExplorer/CmdSpec.fs b/src/RearEnd/BinExplorer/CmdSpec.fs similarity index 97% rename from src/Utilities/BinExplorer/CmdSpec.fs rename to src/RearEnd/BinExplorer/CmdSpec.fs index 441c6b89..4503326f 100644 --- a/src/Utilities/BinExplorer/CmdSpec.fs +++ b/src/RearEnd/BinExplorer/CmdSpec.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module internal B2R2.Utilities.BinExplorer.CmdSpec +module internal B2R2.RearEnd.BinExplorer.CmdSpec /// Command specification in *alphabetic* order. The entries in this list /// should match with the KeyWords of help commands (in defaultCmds). diff --git a/src/Utilities/BinExplorer/CmdTypes.fs b/src/RearEnd/BinExplorer/CmdTypes.fs similarity index 95% rename from src/Utilities/BinExplorer/CmdTypes.fs rename to src/RearEnd/BinExplorer/CmdTypes.fs index 3cf4d5cd..ce1e7abb 100644 --- a/src/Utilities/BinExplorer/CmdTypes.fs +++ b/src/RearEnd/BinExplorer/CmdTypes.fs @@ -22,9 +22,10 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer -open B2R2.BinEssence +open B2R2 +open B2R2.MiddleEnd.BinEssence /// Raised when there are duplicate commands with the same name or alias. exception DuplicateCommandException @@ -50,7 +51,7 @@ type Cmd () = /// A command callback function. This function takes in an Agent (arbiter), a /// CmdMap, and a list of arguments as input, and produces some side effects. - abstract member CallBack: CmdMap -> BinEssence -> string list -> string [] + abstract member CallBack: CmdMap -> BinEssence -> string list -> OutString [] /// This is a mapping from a command name to the corresponding command (Cmd). and CmdMap = { @@ -67,7 +68,7 @@ module internal Cmd = let handle cmdMap binEssence cmd args = match Map.tryFind cmd cmdMap.CmdMap with - | None -> warnUnknown cmd + | None -> warnUnknown cmd |> Array.map OutputNormal | Some cmd -> cmd.CallBack cmdMap binEssence args module internal CmdMap = diff --git a/src/Utilities/BinExplorer/CmdUtils.fs b/src/RearEnd/BinExplorer/CmdUtils.fs similarity index 91% rename from src/Utilities/BinExplorer/CmdUtils.fs rename to src/RearEnd/BinExplorer/CmdUtils.fs index db3d0a46..b78a4509 100644 --- a/src/Utilities/BinExplorer/CmdUtils.fs +++ b/src/RearEnd/BinExplorer/CmdUtils.fs @@ -22,9 +22,13 @@ SOFTWARE. *) -module B2R2.Utilities.BinExplorer.CmdUtils +module B2R2.RearEnd.BinExplorer.CmdUtils open System +open B2R2 + +/// The console printer. +let internal out = ConsolePrinter () :> Printer let convHexString (str: string) = try Convert.ToUInt64 (str, 16) |> Some diff --git a/src/Utilities/BinExplorer/Credits.fs b/src/RearEnd/BinExplorer/Credits.fs similarity index 94% rename from src/Utilities/BinExplorer/Credits.fs rename to src/RearEnd/BinExplorer/Credits.fs index 1f61d9ba..337c6829 100644 --- a/src/Utilities/BinExplorer/Credits.fs +++ b/src/RearEnd/BinExplorer/Credits.fs @@ -22,9 +22,10 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer open B2R2 +open B2R2.RearEnd type CmdCredits () = inherit Cmd () @@ -41,5 +42,6 @@ type CmdCredits () = override __.CallBack _ _ _args = [| Attribution.copyright; |] + |> Array.map OutputNormal // vim: set tw=80 sts=2 sw=2: diff --git a/src/Utilities/BinExplorer/Demangle.fs b/src/RearEnd/BinExplorer/Demangle.fs similarity index 87% rename from src/Utilities/BinExplorer/Demangle.fs rename to src/RearEnd/BinExplorer/Demangle.fs index 62f0c980..c783aad2 100644 --- a/src/Utilities/BinExplorer/Demangle.fs +++ b/src/RearEnd/BinExplorer/Demangle.fs @@ -22,10 +22,11 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer open B2R2 -open B2R2.NameMangling +open B2R2.FrontEnd.NameMangling +open B2R2.RearEnd type CmdDemangle () = inherit Cmd () @@ -42,6 +43,7 @@ type CmdDemangle () = override __.CallBack _ _ args = let mangled = String.concat " " args - match Demangler.Demangle mangled |> Utils.tupleToOpt with - | None -> [| "[*] Invalid input." |] - | Some s -> [| s |] + match Demangler.demangle mangled with + | Ok s -> [| s |] + | Error _ -> [| "[*] Invalid input." |] + |> Array.map OutputNormal diff --git a/src/Utilities/BinExplorer/Disasm.fs b/src/RearEnd/BinExplorer/Disasm.fs similarity index 78% rename from src/Utilities/BinExplorer/Disasm.fs rename to src/RearEnd/BinExplorer/Disasm.fs index dae34651..30719221 100644 --- a/src/Utilities/BinExplorer/Disasm.fs +++ b/src/RearEnd/BinExplorer/Disasm.fs @@ -22,11 +22,12 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer open System -open B2R2.FrontEnd -open B2R2.BinEssence +open B2R2 +open B2R2.FrontEnd.BinInterface +open B2R2.MiddleEnd.BinEssence type CmdDisasm () = inherit Cmd () @@ -39,22 +40,18 @@ type CmdDisasm () = try Ok (count, Convert.ToUInt64 (str, 16)) with _ -> Error "[*] Invalid address is given." - let rec disasmLoop acc ctxt hdl addr count = + let rec disasmLoop acc hdl addr count = if count <= 0 then List.rev acc |> List.toArray else - match BinHandler.TryParseInstr hdl ctxt addr with - | Some ins -> - let d = ins.Disasm (true, true, hdl.FileInfo) - let ctxt = ins.NextParsingContext - disasmLoop (d :: acc) ctxt hdl (addr + uint64 ins.Length) (count - 1) - | None -> - let ctxt = hdl.DefaultParsingContext - disasmLoop ("(invalid)" :: acc) ctxt hdl (addr + 1UL) (count - 1) + match BinHandle.TryParseInstr (hdl, addr=addr) with + | Ok ins -> + let d = ins.Disasm (true, true, hdl.DisasmHelper) + disasmLoop (d :: acc) hdl (addr + uint64 ins.Length) (count - 1) + | Error _ -> + disasmLoop ("(invalid)" :: acc) hdl (addr + 1UL) (count - 1) let render (ess: BinEssence) = function - | Ok (count, addr: uint64) -> - let hdl = ess.BinHandler - disasmLoop [] hdl.DefaultParsingContext hdl addr count + | Ok (count, addr: uint64) -> disasmLoop [] ess.BinHandle addr count | Error str -> [| str |] let disasm ess count addr = @@ -81,5 +78,6 @@ type CmdDisasm () = | cnt :: addr :: _ -> disasm ess cnt addr | addr :: _ -> disasm ess "1" addr | _ -> [| __.CmdHelp |] + |> Array.map OutputNormal // vim: set tw=80 sts=2 sw=2: diff --git a/src/Utilities/BinExplorer/EvalExpr.fs b/src/RearEnd/BinExplorer/EvalExpr.fs similarity index 98% rename from src/Utilities/BinExplorer/EvalExpr.fs rename to src/RearEnd/BinExplorer/EvalExpr.fs index 2259f0b7..98bda367 100644 --- a/src/Utilities/BinExplorer/EvalExpr.fs +++ b/src/RearEnd/BinExplorer/EvalExpr.fs @@ -22,12 +22,14 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer + open FParsec open System.Numerics open SimpleArithHelper open SimpleArithConverter open B2R2 +open B2R2.RearEnd type SimpleArithEvaluator () = /// Concatenating given array of strings. Returning place of error when there @@ -138,3 +140,4 @@ type CmdEvalExpr (name, alias, descrSuffix, helpSuffix, outFormat) = match args with | [] -> [| __.CmdHelp |] | _ -> evaluator.Run args outFormat + |> Array.map OutputNormal diff --git a/src/Utilities/BinExplorer/HTTPServer.fs b/src/RearEnd/BinExplorer/HTTPServer.fs similarity index 71% rename from src/Utilities/BinExplorer/HTTPServer.fs rename to src/RearEnd/BinExplorer/HTTPServer.fs index ca9e855a..3f0fa3be 100644 --- a/src/Utilities/BinExplorer/HTTPServer.fs +++ b/src/RearEnd/BinExplorer/HTTPServer.fs @@ -22,18 +22,19 @@ SOFTWARE. *) -module internal B2R2.Utilities.BinExplorer.HTTPServer +module internal B2R2.RearEnd.BinExplorer.HTTPServer open System open System.Net open System.Runtime.Serialization open System.Runtime.Serialization.Json open B2R2 -open B2R2.FrontEnd -open B2R2.BinEssence -open B2R2.Lens -open B2R2.DataFlow -open B2R2.Visualization +open B2R2.FrontEnd.BinInterface +open B2R2.MiddleEnd.ControlFlowGraph +open B2R2.MiddleEnd.ControlFlowAnalysis +open B2R2.MiddleEnd.BinEssence +open B2R2.MiddleEnd.DataFlow +open B2R2.RearEnd.Visualization type CFGType = | DisasmCFG @@ -49,12 +50,24 @@ type JsonFuncInfo = { FuncName: string } +[] +type DataColoredHexAscii = { + [] + Color: string + [] + Hex: string + [] + Ascii: string +} + [] type JsonSegInfo = { [] SegAddr: Addr [] SegBytes: byte [] + [] + SegColoredHexAscii: DataColoredHexAscii [] } [] @@ -120,31 +133,29 @@ let answer (req: HttpListenerRequest) (resp: HttpListenerResponse) = function let handleBinInfo req resp arbiter = let ess = Protocol.getBinEssence arbiter - let txt = ess.BinHandler.FileInfo.FilePath + let txt = ess.BinHandle.FileInfo.FilePath let txt = "\"" + txt.Replace(@"\", @"\\") + "\"" Some (defaultEnc.GetBytes (txt)) |> answer req resp -let cfgToJSON cfgType ess g roots = +let cfgToJSON cfgType (ess: BinEssence) g root = match cfgType with | IRCFG -> - Visualizer.getJSONFromGraph g roots + Visualizer.getJSONFromGraph g [root] | DisasmCFG -> - let lens = DisasmLens.Init ess - let g, roots = lens.Filter (g, roots, ess) - Visualizer.getJSONFromGraph g roots + let g, root = DisasmLens.filter ess.CodeManager g root + Visualizer.getJSONFromGraph g [root] | SSACFG -> - let lens = SSALens.Init ess - let g, roots = lens.Filter (g, roots, ess) - Visualizer.getJSONFromGraph g roots + let struct (g, root) = SSACFG.ofIRCFG ess.BinHandle g root + Visualizer.getJSONFromGraph g [root] | _ -> failwith "Invalid CFG type" let handleRegularCFG req resp (name: string) (ess: BinEssence) cfgType = - match ess.CalleeMap.Find name with + match ess.CodeManager.FunctionMaintainer.TryFind name with | None -> answer req resp None - | Some callee -> + | Some func -> try - let cfg, root = ess.GetFunctionCFG (callee.Addr.Value) - let s = cfgToJSON cfgType ess cfg [root] + let cfg, root = BinEssence.getFunctionCFG ess func.Entry |> Result.get + let s = cfgToJSON cfgType ess cfg root Some (defaultEnc.GetBytes s) |> answer req resp with e -> #if DEBUG @@ -158,8 +169,7 @@ let handleCFG req resp arbiter cfgType name = match cfgType with | CallCFG -> try - let lens = CallGraphLens.Init () - let g, roots = lens.Filter (ess.SCFG, [], ess) + let g, roots = CallGraphLens.build ess let s = Visualizer.getJSONFromGraph g roots Some (defaultEnc.GetBytes s) |> answer req resp with e -> @@ -173,27 +183,35 @@ let handleCFG req resp arbiter cfgType name = let handleFunctions req resp arbiter = let ess = Protocol.getBinEssence arbiter let names = - ess.CalleeMap.InternalCallees - |> Seq.map (fun c -> { FuncID = c.CalleeID; FuncName = c.CalleeName }) + ess.CodeManager.FunctionMaintainer.RegularFunctions + |> Seq.map (fun c -> { FuncID = c.FunctionID; FuncName = c.FunctionName }) |> Seq.toArray Some (json<(JsonFuncInfo) []> names |> defaultEnc.GetBytes) |> answer req resp let handleHexview req resp arbiter = let ess = Protocol.getBinEssence arbiter - ess.BinHandler.FileInfo.GetSegments () + ess.BinHandle.FileInfo.GetSegments () |> Seq.map (fun seg -> - let bs = BinHandler.ReadBytes (ess.BinHandler, seg.Address, int (seg.Size)) - { SegAddr = seg.Address; SegBytes = bs }) + let bs = BinHandle.ReadBytes (ess.BinHandle, seg.Address, int (seg.Size)) + let coloredHex = bs |> Array.map ColoredSegment.byteToHex + let coloredAscii = bs |> Array.map ColoredSegment.byteToAscii + let cha = (* DataColoredHexAscii *) + Array.map2 (fun (c, h) (_, a) -> + { Color = Color.toString c + Hex = h + Ascii = a }) coloredHex coloredAscii + { SegAddr = seg.Address; SegBytes = bs; SegColoredHexAscii = cha }) |> json> |> defaultEnc.GetBytes |> Some |> answer req resp -let jsonPrinter _ acc line = acc + line + "\n" +let private myprinter _ acc output = + acc + OutString.toString output + Environment.NewLine let handleCommand req resp arbiter cmdMap (args: string) = - let result = CLI.handle cmdMap arbiter args "" jsonPrinter + let result = CLI.handle cmdMap arbiter args "" myprinter Some (json result |> defaultEnc.GetBytes) |> answer req resp let computeConnectedVars chain v = @@ -220,26 +238,30 @@ let handleDataflow req resp arbiter (args: string) = let args = args.Split ([|','|]) let entry = args.[0] |> uint64 let addr = args.[1] |> uint64 - let var = args.[2] |> ess.BinHandler.RegisterBay.RegIDFromString - try - let cfg, root = ess.GetFunctionCFG (entry) - let chain = DataFlowChain.init cfg root true - let v = { ProgramPoint = ProgramPoint (addr, 0); VarExpr = Regular var } - computeConnectedVars chain v - |> Set.toArray - |> Array.map (fun vp -> - { VarAddr = vp.ProgramPoint.Address - VarNames = getVarNames ess.BinHandler vp.VarExpr }) - |> json - |> defaultEnc.GetBytes - |> Some - |> answer req resp - with e -> + let tag = args.[2] (* either variable or value. *) + match tag with + | "variable" -> + let var = args.[3] |> ess.BinHandle.RegisterBay.RegIDFromString + try + let cfg, root = BinEssence.getFunctionCFG ess entry |> Result.get + let chain = DataFlowChain.init cfg root true + let v = { ProgramPoint = ProgramPoint (addr, 0); VarExpr = Regular var } + computeConnectedVars chain v + |> Set.toArray + |> Array.map (fun vp -> + { VarAddr = vp.ProgramPoint.Address + VarNames = getVarNames ess.BinHandle vp.VarExpr }) + |> json + |> defaultEnc.GetBytes + |> Some + |> answer req resp + with e -> #if DEBUG - printfn "%A" e; failwith "[FATAL]: Failed to obtain dataflow info" + printfn "%A" e; failwith "[FATAL]: Failed to obtain dataflow info" #else - answer req resp None + answer req resp None #endif + | _ -> answer req resp None let handleAJAX req resp arbiter cmdMap query args = match query with diff --git a/src/Utilities/BinExplorer/Help.fs b/src/RearEnd/BinExplorer/Help.fs similarity index 97% rename from src/Utilities/BinExplorer/Help.fs rename to src/RearEnd/BinExplorer/Help.fs index 24f46774..bee0aab3 100644 --- a/src/Utilities/BinExplorer/Help.fs +++ b/src/RearEnd/BinExplorer/Help.fs @@ -22,7 +22,9 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer + +open B2R2 type CmdHelp () = inherit Cmd () @@ -64,7 +66,7 @@ type CmdHelp () = match args with | [] -> generalHelp cmdMap | cmd :: _ -> specificHelp cmd cmdMap - + |> Array.map OutputNormal type CmdExit () = inherit Cmd () diff --git a/src/Utilities/BinExplorer/HexDump.fs b/src/RearEnd/BinExplorer/HexDump.fs similarity index 65% rename from src/Utilities/BinExplorer/HexDump.fs rename to src/RearEnd/BinExplorer/HexDump.fs index 330c11be..b19fac1b 100644 --- a/src/Utilities/BinExplorer/HexDump.fs +++ b/src/RearEnd/BinExplorer/HexDump.fs @@ -22,10 +22,12 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer open System -open B2R2.BinEssence +open B2R2 +open B2R2.MiddleEnd.BinEssence +open B2R2.RearEnd type CmdHexDump () = inherit Cmd () @@ -39,39 +41,9 @@ type CmdHexDump () = with _ -> Error "[*] Invalid byte count given." let readBytes (binEssence: BinEssence) (addr, count) = - try (addr, binEssence.BinHandler.ReadBytes (addr, count)) |> Ok + try (addr, binEssence.BinHandle.ReadBytes (addr=addr, nBytes=count)) |> Ok with _ -> Error "[*] Failed to read bytes." - let addSpace idx = - match idx with - | 0 -> "" - | 8 -> " " - | _ -> " " - - let dumpHex (bytes: byte []) = - bytes - |> Array.mapi (fun i b -> addSpace i + b.ToString ("X2")) - |> String.concat "" - - let isPrintable b = b >= 32uy && b <= 126uy - - let dumpASCII (bytes: byte []) = - bytes - |> Array.map (fun b -> if isPrintable b then (char b).ToString () else ".") - |> String.concat "" - - let dumpLine addr linenum bytes = - let addr = addr + uint64 (linenum * 16) - let hex = dumpHex bytes - let ascii = dumpASCII bytes - addr.ToString ("X16") + ": " + hex + " | " + ascii - - let hexdump = function - | Ok (addr, bytes: byte []) -> - Array.chunkBySize 16 bytes - |> Array.mapi (dumpLine addr) - | Error e -> [| e |] - override __.CmdName = "hexdump" override __.CmdAlias = [ "hd" ] @@ -87,10 +59,14 @@ type CmdHexDump () = override __.CallBack _ binEssence args = match args with | addr :: cnt :: _ -> - parseAddr addr - |> Result.bind (parseCount cnt) - |> Result.bind (readBytes binEssence) - |> hexdump - | _ -> [| __.CmdHelp |] + let result = + parseAddr addr + |> Result.bind (parseCount cnt) + |> Result.bind (readBytes binEssence) + match result with + | Ok (addr, bytes: byte []) -> + HexDumper.dump 16 binEssence.BinHandle.ISA.WordSize true addr bytes + | Error e -> [| OutputColored [ ColoredSegment (NoColor, e) ] |] + | _ -> [| __.CmdHelp |] |> Array.map OutputNormal // vim: set tw=80 sts=2 sw=2: diff --git a/src/Utilities/BinExplorer/List.fs b/src/RearEnd/BinExplorer/List.fs similarity index 85% rename from src/Utilities/BinExplorer/List.fs rename to src/RearEnd/BinExplorer/List.fs index f08474f4..640b503f 100644 --- a/src/Utilities/BinExplorer/List.fs +++ b/src/RearEnd/BinExplorer/List.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer open B2R2 -open B2R2.BinFile -open B2R2.FrontEnd -open B2R2.BinEssence +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinInterface +open B2R2.MiddleEnd.BinEssence type CmdList () = inherit Cmd () @@ -36,10 +36,10 @@ type CmdList () = Addr.toString hdl.ISA.WordSize addr + ": " + name let listFunctions ess = - ess.CalleeMap.InternalCallees - |> Seq.map (fun c -> Option.get c.Addr, c.CalleeID) + ess.CodeManager.FunctionMaintainer.RegularFunctions + |> Seq.map (fun c -> c.Entry, c.FunctionID) |> Seq.sortBy fst - |> Seq.map (createFuncString ess.BinHandler) + |> Seq.map (createFuncString ess.BinHandle) |> Seq.toArray let createSegmentString handler (seg: Segment) = @@ -50,7 +50,7 @@ type CmdList () = + " (" + seg.Size.ToString () + ") (" + FileInfo.PermissionToString seg.Permission + ")" - let listSegments (handler: BinHandler) = + let listSegments (handler: BinHandle) = handler.FileInfo.GetSegments () |> Seq.map (createSegmentString handler) |> Seq.toArray @@ -64,7 +64,7 @@ type CmdList () = + " (" + sec.Size.ToString ("D6") + ")" + " [" + sec.Name + "] " - let listSections (handler: BinHandler) = + let listSections (handler: BinHandle) = handler.FileInfo.GetSections () |> Seq.mapi (createSectionString handler) |> Seq.toArray @@ -89,9 +89,10 @@ type CmdList () = | "functions" :: _ | "funcs" :: _ -> listFunctions ess | "segments" :: _ - | "segs" :: _ -> listSegments ess.BinHandler + | "segs" :: _ -> listSegments ess.BinHandle | "sections" :: _ - | "secs" :: _ -> listSections ess.BinHandler + | "secs" :: _ -> listSections ess.BinHandle | _ -> [| "[*] Unknown list cmd is given." |] + |> Array.map OutputNormal // vim: set tw=80 sts=2 sw=2: diff --git a/src/Utilities/BinExplorer/Print.fs b/src/RearEnd/BinExplorer/Print.fs similarity index 89% rename from src/Utilities/BinExplorer/Print.fs rename to src/RearEnd/BinExplorer/Print.fs index aa4525b7..a2170f05 100644 --- a/src/Utilities/BinExplorer/Print.fs +++ b/src/RearEnd/BinExplorer/Print.fs @@ -22,13 +22,14 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer open System open System.Text.RegularExpressions open B2R2 -open B2R2.FrontEnd -open B2R2.BinEssence +open B2R2.FrontEnd.BinInterface +open B2R2.MiddleEnd.BinEssence +open B2R2.RearEnd type PrintFormat = | Hexadecimal @@ -108,21 +109,21 @@ type CmdPrint () = with _ -> Error "[*] Invalid address given." let hexPrint sz (i: uint64) = - i.ToString ("X" + (sz * 2).ToString ()) + i.ToString ("x" + (sz * 2).ToString ()) let print handler sz fmt addr = match fmt with | Hexadecimal -> - BinHandler.ReadUInt (handler, addr, sz) |> hexPrint sz + BinHandle.ReadUInt (handler, addr=addr, size=sz) |> hexPrint sz | UnsignedDecimal -> - BinHandler.ReadUInt(handler, addr, sz).ToString () + BinHandle.ReadUInt(handler, addr=addr, size=sz).ToString () | Decimal -> - BinHandler.ReadInt(handler, addr, sz).ToString () + BinHandle.ReadInt(handler, addr=addr, size=sz).ToString () | _ -> failwith "This is impossible" let getAddressPrefix handler (addr: uint64) = let hexWidth = WordSize.toByteWidth handler.ISA.WordSize * 2 - addr.ToString ("X" + hexWidth.ToString ()) + ": " + addr.ToString ("x" + hexWidth.ToString ()) + ": " let rec iter handler sz fmt addr endAddr acc = if addr >= endAddr then List.rev acc |> List.toArray @@ -136,7 +137,8 @@ type CmdPrint () = let rec printStrings handler addr cnt acc = if cnt <= 0 then List.rev acc |> List.toArray else - let s = try BinHandler.ReadASCII (handler, addr) |> Some with _ -> None + let s = + try BinHandle.ReadASCII (handler, addr=addr) |> Some with _ -> None match s with | None -> printStrings handler addr 0 acc | Some s -> @@ -146,10 +148,10 @@ type CmdPrint () = let validateRequest (binEssence: BinEssence) = function | Ok (_, count, ASCII, addr) -> - let handler = binEssence.BinHandler + let handler = binEssence.BinHandle printStrings handler addr count [] | Ok (sz, count, fmt, addr) -> - let handler = binEssence.BinHandler + let handler = binEssence.BinHandle let sz = PrintSize.ToInt sz let endAddr = addr + uint64 (sz * count) if addr > endAddr then [| "[*] Invalid address range given."|] @@ -186,5 +188,6 @@ type CmdPrint () = |> Result.bind (parseAddr addr) |> validateRequest binEssence | _ -> [| __.CmdHelp |] + |> Array.map OutputNormal // vim: set tw=80 sts=2 sw=2: diff --git a/src/Utilities/BinExplorer/Main.fs b/src/RearEnd/BinExplorer/Program.fs similarity index 82% rename from src/Utilities/BinExplorer/Main.fs rename to src/RearEnd/BinExplorer/Program.fs index ebb97bd2..05f33209 100644 --- a/src/Utilities/BinExplorer/Main.fs +++ b/src/RearEnd/BinExplorer/Program.fs @@ -22,16 +22,16 @@ SOFTWARE. *) -module B2R2.Utilities.BinExplorer.Main +module B2R2.RearEnd.BinExplorer.Program open B2R2 -open B2R2.FrontEnd -open B2R2.BinGraph -open B2R2.BinEssence -open B2R2.Lens -open B2R2.MiddleEnd -open B2R2.Visualization -open B2R2.Utilities +open B2R2.FrontEnd.BinInterface +open B2R2.MiddleEnd.ControlFlowGraph +open B2R2.MiddleEnd.BinEssence +open B2R2.MiddleEnd.ControlFlowAnalysis +open B2R2.RearEnd +open B2R2.RearEnd.Visualization +open B2R2.RearEnd.BinExplorer.CmdUtils type BinExplorerOpts (isa) = inherit CmdOpts() @@ -50,7 +50,7 @@ type BinExplorerOpts (isa) = member val JsonDumpDir = "" with get, set /// Specify ISA. This is only meaningful for universal (fat) binaries because - /// BinHandler will automatically detect file format by default. When a fat + /// BinHandle will automatically detect file format by default. When a fat /// binary is given, we need to choose which architecture to explorer with /// this option. member val ISA = isa with get, set @@ -65,16 +65,14 @@ type BinExplorerOpts (isa) = member val EnableBranchRecovery = true with get, set /// Enable branch recovery analysis. - member val EnableGapComp = true with get, set + member val EnableGapComp = false with get, set /// List of analyses to perform. member __.GetAnalyses () = - [ yield LibcAnalysis () :> IAnalysis - yield EVMCodeCopyAnalysis () :> IAnalysis - if __.EnableBranchRecovery then - yield BranchRecovery (__.EnableNoReturn) :> IAnalysis - if __.EnableGapComp then - yield SpeculativeGapCompletion (__.EnableNoReturn) :> IAnalysis ] + let preanalyses = [ yield LibcAnalysis () :> IPluggableAnalysis ] + let iteranalyses = [] + let postanalyses = [] + preanalyses, iteranalyses, postanalyses static member private ToThis (opts: CmdOpts) = match opts with @@ -180,8 +178,8 @@ let spec = ] let buildGraph (opts: BinExplorerOpts) handle = - BinEssence.init handle - |> Analyzer.run (opts.GetAnalyses ()) + let preanalyses, iteranalyses, postanalyses = opts.GetAnalyses () + BinEssence.init handle preanalyses iteranalyses postanalyses let startGUI (opts: BinExplorerOpts) arbiter = HTTPServer.startServer arbiter opts.IP opts.Port opts.Verbose @@ -192,16 +190,17 @@ let startGUI (opts: BinExplorerOpts) arbiter = let dumpJsonFiles jsonDir ess = try System.IO.Directory.Delete(jsonDir, true) with _ -> () System.IO.Directory.CreateDirectory(jsonDir) |> ignore - ess.CalleeMap.InternalCallees - |> Seq.iter (fun { CalleeID = id; Addr = addr } -> + ess.CodeManager.FunctionMaintainer.RegularFunctions + |> Seq.iter (fun func -> + let id = func.FunctionID + let entry = func.Entry let disasmJsonPath = Printf.sprintf "%s/%s.disasmCFG" jsonDir id - let cfg, root = ess.GetFunctionCFG (Option.get addr) - let lens = DisasmLens.Init ess - let disasmcfg, _ = lens.Filter (cfg, [root], ess) + let cfg, root = BinEssence.getFunctionCFG ess entry |> Result.get + let disasmcfg, _ = DisasmLens.filter ess.CodeManager cfg root CFGExport.toJson disasmcfg disasmJsonPath) let initBinHdl isa (name: string) = - BinHandler.Init (isa, ArchOperationMode.NoMode, true, 0UL, name) + BinHandle.Init (isa, ArchOperationMode.NoMode, true, None, name) let interactiveMain files (opts: BinExplorerOpts) = if List.length files = 0 then @@ -227,10 +226,6 @@ let showBatchUsage () = eprintfn "" eprintfn " visualize " eprintfn "" - eprintfn "* dumpswitch: dump switch recovery information to output directory." - eprintfn "" - eprintfn " dumpswitch " - eprintfn "" exit 1 let visualizeGraph inputFile outputFile = @@ -255,42 +250,27 @@ let batchRun opts paths fstParam restParams fn = let runCommand cmdMap opts file cmd args = let ess = initBinHdl ISA.DefaultISA file |> buildGraph opts Cmd.handle cmdMap ess cmd args - |> Array.iter System.Console.WriteLine + |> Array.iter out.Print -let dumpSwitch _cmdMap opts file outdir _args = - let ess = initBinHdl ISA.DefaultISA file |> buildGraph opts - let file = file.Replace (System.IO.Path.DirectorySeparatorChar, '_') - let file = file.Replace (':', '_') - let outpath = System.IO.Path.Combine (outdir, file) - use writer = System.IO.File.CreateText (outpath) - ess.IndirectBranchMap - |> Map.iter (fun fromAddr { TargetAddresses = targets } -> - targets - |> Set.iter (fun target -> - writer.WriteLine (fromAddr.ToString ("X") + "," + target.ToString ("X")) - ) - ) +let [] private toolName = "binexplore" let batchMain opts paths args = match args with | "visualize" :: infile :: outfile :: _ -> visualizeGraph infile outfile - | "dumpswitch" :: outdir :: _ -> - try System.IO.Directory.Delete (outdir, true) with _ -> () - System.IO.Directory.CreateDirectory (outdir) |> ignore - batchRun opts paths outdir [] dumpSwitch | cmd :: args -> batchRun opts paths cmd args runCommand | _ -> showBatchUsage () let parseAndRunBatchMode opts (beforeOpts, afterOpts) = CmdOpts.ParseAndRun (fun rest opts -> batchMain opts rest (Array.tail afterOpts |> Array.toList) - ) "" spec opts beforeOpts + ) toolName "" spec opts beforeOpts [] let main args = let opts = BinExplorerOpts (ISA.DefaultISA) match Array.tryFindIndex (fun a -> a = "--batch") args with | Some idx -> Array.splitAt idx args |> parseAndRunBatchMode opts - | None -> CmdOpts.ParseAndRun interactiveMain "" spec opts args + | None -> + CmdOpts.ParseAndRun interactiveMain toolName "" spec opts args // vim: set tw=80 sts=2 sw=2: diff --git a/src/Utilities/BinExplorer/Protocol.fs b/src/RearEnd/BinExplorer/Protocol.fs similarity index 95% rename from src/Utilities/BinExplorer/Protocol.fs rename to src/RearEnd/BinExplorer/Protocol.fs index 719ea9e5..23a6f3dd 100644 --- a/src/Utilities/BinExplorer/Protocol.fs +++ b/src/RearEnd/BinExplorer/Protocol.fs @@ -22,20 +22,20 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer -open B2R2 +open B2R2.MiddleEnd.BinEssence open System.IO type SendMsg = | GetBinEssence | LogString of string - | UpdateBinEssence of BinEssence.BinEssence + | UpdateBinEssence of BinEssence | Terminate type ReplyMsg = | Ack - | ReplyBinEssence of BinEssence.BinEssence + | ReplyBinEssence of BinEssence | ReplyExitStatus of bool (* Either success (true) or failure (false) *) type Msg = diff --git a/src/Utilities/BinExplorer/ROP.fs b/src/RearEnd/BinExplorer/ROP.fs similarity index 93% rename from src/Utilities/BinExplorer/ROP.fs rename to src/RearEnd/BinExplorer/ROP.fs index b19a03c9..553009b4 100644 --- a/src/Utilities/BinExplorer/ROP.fs +++ b/src/RearEnd/BinExplorer/ROP.fs @@ -22,10 +22,11 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer open B2R2 -open B2R2.ROP +open B2R2.RearEnd +open B2R2.RearEnd.ROP type CmdGadgetSearch () = inherit Cmd () @@ -42,8 +43,9 @@ type CmdGadgetSearch () = override __.SubCommands = [] override __.CallBack _ ess _args = - let hdl = ess.BinHandler + let hdl = ess.BinHandle [| Galileo.findGadgets hdl |> GadgetMap.toString hdl |] + |> Array.map OutputNormal type CmdROP () = inherit Cmd () @@ -69,13 +71,15 @@ type CmdROP () = override __.SubCommands = [] override __.CallBack _ ess args = - let hdl = ess.BinHandler + let hdl = ess.BinHandle match hdl.ISA.Arch with | Architecture.IntelX86 -> let rop = ROPHandle.init hdl 0UL __.HandleSubCmd hdl rop args + |> Array.map OutputNormal | arch -> [| "[*] We currently do not support " + (ISA.ArchToString arch) |] + |> Array.map OutputNormal member private __.HandleSubCmd hdl rop args = match args with diff --git a/src/Utilities/BinExplorer/Search.fs b/src/RearEnd/BinExplorer/Search.fs similarity index 90% rename from src/Utilities/BinExplorer/Search.fs rename to src/RearEnd/BinExplorer/Search.fs index a72b727d..03714465 100644 --- a/src/Utilities/BinExplorer/Search.fs +++ b/src/RearEnd/BinExplorer/Search.fs @@ -22,23 +22,23 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer open System open B2R2 -open B2R2.BinFile -open B2R2.FrontEnd +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinInterface type CmdSearch () = inherit Cmd () let search hdl pattern = hdl.FileInfo.GetSegments (Permission.Readable) - |> Seq.map (fun s -> BinHandler.ReadBytes (hdl, s.Address, int s.Size) + |> Seq.map (fun s -> BinHandle.ReadBytes (hdl, s.Address, int s.Size) |> ByteArray.findIdxs 0UL pattern |> List.map (fun idx -> idx + s.Address)) |> Seq.concat - |> Seq.map (fun idx -> "Found @ " + idx.ToString("X")) + |> Seq.map (fun idx -> "Found @ " + String.u64ToHexNoPrefix idx) |> Seq.toList override __.CmdName = "search" @@ -74,6 +74,7 @@ type CmdSearch () = match args with | [] | _ :: [] -> [| __.CmdHelp |] - | t :: pattern :: _ -> t.ToLower () |> __.CmdHandle ess.BinHandler pattern + | t :: pattern :: _ -> t.ToLower () |> __.CmdHandle ess.BinHandle pattern + |> Array.map OutputNormal // vim: set tw=80 sts=2 sw=2: diff --git a/src/Utilities/BinExplorer/Show.fs b/src/RearEnd/BinExplorer/Show.fs similarity index 65% rename from src/Utilities/BinExplorer/Show.fs rename to src/RearEnd/BinExplorer/Show.fs index 5232ba62..e1d43c82 100644 --- a/src/Utilities/BinExplorer/Show.fs +++ b/src/RearEnd/BinExplorer/Show.fs @@ -22,13 +22,13 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer open System open System.Text open B2R2 -open B2R2.BinEssence -open B2R2.MiddleEnd +open B2R2.MiddleEnd.ControlFlowAnalysis +open B2R2.MiddleEnd.BinEssence type CmdShow () = inherit Cmd () @@ -49,33 +49,38 @@ type CmdShow () = override __.SubCommands = [] member private __.CallerToString (sb: StringBuilder) (addr: Addr) = - sb.Append (" - referenced by " + addr.ToString("X") + "\n") - - member private __.CalleeToSimpleString prefix (sb: StringBuilder) callee = - let noret = if callee.IsNoReturn then " [no return]" else "" - match callee.Addr with - | None -> sb.Append (prefix + callee.CalleeName + noret + "\n") - | Some addr -> - sb.Append (prefix + callee.CalleeName - + noret + " @ " + addr.ToString("X") + "\n") - - member private __.CalleeToString (sb: StringBuilder) callee = - __.CalleeToSimpleString "" sb callee - |> (fun sb -> callee.Callers |> Set.fold __.CallerToString sb) + sb.Append (" - referenced by " + String.u64ToHexNoPrefix addr + "\n") + + member private __.CalleeToSimpleString ess prefix (sb: StringBuilder) (callee: Function) = + let noret = + match callee.NoReturnProperty with + | NoRet -> " [no return]" + | ConditionalNoRet _ -> " [conditional no return]" + | NotNoRetConfirmed | NotNoRet -> "" + | UnknownNoRet -> "" + if callee.FunctionKind <> FunctionKind.Regular then + sb.Append (prefix + callee.FunctionName + noret + "\n") + else + sb.Append (prefix + callee.FunctionName + + noret + " @ " + String.u64ToHexNoPrefix callee.Entry + "\n") + + member private __.CalleeToString ess (sb: StringBuilder) callee = + __.CalleeToSimpleString ess "" sb callee + |> (fun sb -> callee.Callers |> Seq.fold __.CallerToString sb) member __.ShowCaller ess = function | (expr: string) :: _ -> let addr = CmdUtils.convHexString expr |> Option.defaultValue 0UL - match Map.tryFind addr ess.CalleeMap.CallerMap with + match ess.CodeManager.FunctionMaintainer.TryFind addr with | None -> [| "[*] Not found." |] - | Some callees -> + | Some func -> let sb = StringBuilder () let sb = sb.Append (expr + " calls:\n") let sb = - callees - |> Set.fold (fun sb (addr: Addr) -> - match ess.CalleeMap.Find addr with - | Some callee -> __.CalleeToSimpleString " - " sb callee + func.Callers + |> Seq.fold (fun sb (addr: Addr) -> + match ess.CodeManager.FunctionMaintainer.TryFind addr with + | Some callee -> __.CalleeToSimpleString ess " - " sb callee | None -> sb) sb [| sb.ToString () |] | _ -> [| __.CmdHelp |] @@ -84,9 +89,10 @@ type CmdShow () = | (expr: string) :: _ -> let addr = CmdUtils.convHexString expr |> Option.defaultValue 0UL let sb = StringBuilder () - if Char.IsDigit expr.[0] then ess.CalleeMap.Find (addr) - else ess.CalleeMap.Find (expr) - |> Option.map (fun callee -> (__.CalleeToString sb callee).ToString ()) + if Char.IsDigit expr.[0] then + ess.CodeManager.FunctionMaintainer.TryFind (addr) + else ess.CodeManager.FunctionMaintainer.TryFind (expr) + |> Option.map (fun callee -> (__.CalleeToString ess sb callee).ToString ()) |> Option.defaultValue "[*] Not found." |> Array.singleton | _ -> [| __.CmdHelp |] @@ -101,5 +107,6 @@ type CmdShow () = match args with | [] -> [| __.CmdHelp |] | c :: opts -> c.ToLower () |> __.CmdHandle ess opts + |> Array.map OutputNormal // vim: set tw=80 sts=2 sw=2: diff --git a/src/Utilities/BinExplorer/SimpleArithConverter.fs b/src/RearEnd/BinExplorer/SimpleArithConverter.fs similarity index 98% rename from src/Utilities/BinExplorer/SimpleArithConverter.fs rename to src/RearEnd/BinExplorer/SimpleArithConverter.fs index 1f4a73ad..aad4ff15 100644 --- a/src/Utilities/BinExplorer/SimpleArithConverter.fs +++ b/src/RearEnd/BinExplorer/SimpleArithConverter.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module B2R2.Utilities.BinExplorer.SimpleArithConverter +module B2R2.RearEnd.BinExplorer.SimpleArithConverter open System open System.Numerics diff --git a/src/Utilities/BinExplorer/SimpleArithHelper.fs b/src/RearEnd/BinExplorer/SimpleArithHelper.fs similarity index 99% rename from src/Utilities/BinExplorer/SimpleArithHelper.fs rename to src/RearEnd/BinExplorer/SimpleArithHelper.fs index 26835e46..5789c121 100644 --- a/src/Utilities/BinExplorer/SimpleArithHelper.fs +++ b/src/RearEnd/BinExplorer/SimpleArithHelper.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module B2R2.Utilities.BinExplorer.SimpleArithHelper +module B2R2.RearEnd.BinExplorer.SimpleArithHelper open System open System.Numerics diff --git a/src/Utilities/BinExplorer/SimpleArithOperator.fs b/src/RearEnd/BinExplorer/SimpleArithOperator.fs similarity index 99% rename from src/Utilities/BinExplorer/SimpleArithOperator.fs rename to src/RearEnd/BinExplorer/SimpleArithOperator.fs index 6816602d..4d54828a 100644 --- a/src/Utilities/BinExplorer/SimpleArithOperator.fs +++ b/src/RearEnd/BinExplorer/SimpleArithOperator.fs @@ -22,13 +22,13 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer open System.Numerics open SimpleArithHelper open SimpleArithReference open FParsec -open B2R2.Utilities.BinExplorer +open B2R2.RearEnd.BinExplorer module SimpleArithOperate = let selectUnsignedOperand operand1 operand2 = diff --git a/src/Utilities/BinExplorer/SimpleArithParser.fs b/src/RearEnd/BinExplorer/SimpleArithParser.fs similarity index 99% rename from src/Utilities/BinExplorer/SimpleArithParser.fs rename to src/RearEnd/BinExplorer/SimpleArithParser.fs index 19e21fd6..dd175db2 100644 --- a/src/Utilities/BinExplorer/SimpleArithParser.fs +++ b/src/RearEnd/BinExplorer/SimpleArithParser.fs @@ -22,9 +22,9 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer -open B2R2.Utilities.BinExplorer +open B2R2.RearEnd.BinExplorer open FParsec open SimpleArithHelper open SimpleArithOperate diff --git a/src/Utilities/BinExplorer/SimpleArithReference.fs b/src/RearEnd/BinExplorer/SimpleArithReference.fs similarity index 97% rename from src/Utilities/BinExplorer/SimpleArithReference.fs rename to src/RearEnd/BinExplorer/SimpleArithReference.fs index 5d706876..44be7b10 100644 --- a/src/Utilities/BinExplorer/SimpleArithReference.fs +++ b/src/RearEnd/BinExplorer/SimpleArithReference.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module B2R2.Utilities.BinExplorer.SimpleArithReference +module B2R2.RearEnd.BinExplorer.SimpleArithReference let (|Between|_|) (lo, hi) x = if lo <= x && x <= hi then Some () else None diff --git a/src/Utilities/BinExplorer/SimpleArithTypes.fs b/src/RearEnd/BinExplorer/SimpleArithTypes.fs similarity index 99% rename from src/Utilities/BinExplorer/SimpleArithTypes.fs rename to src/RearEnd/BinExplorer/SimpleArithTypes.fs index ff119a26..c4208b6d 100644 --- a/src/Utilities/BinExplorer/SimpleArithTypes.fs +++ b/src/RearEnd/BinExplorer/SimpleArithTypes.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.Utilities.BinExplorer +namespace B2R2.RearEnd.BinExplorer open System.Numerics open SimpleArithReference open System diff --git a/src/Utilities/BinExplorer/WebUI/b2r2.png b/src/RearEnd/BinExplorer/WebUI/b2r2.png similarity index 100% rename from src/Utilities/BinExplorer/WebUI/b2r2.png rename to src/RearEnd/BinExplorer/WebUI/b2r2.png diff --git a/src/Utilities/BinExplorer/WebUI/css/b2r2.base.css b/src/RearEnd/BinExplorer/WebUI/css/b2r2.base.css similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/b2r2.base.css rename to src/RearEnd/BinExplorer/WebUI/css/b2r2.base.css diff --git a/src/Utilities/BinExplorer/WebUI/css/b2r2.css b/src/RearEnd/BinExplorer/WebUI/css/b2r2.css similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/b2r2.css rename to src/RearEnd/BinExplorer/WebUI/css/b2r2.css diff --git a/src/Utilities/BinExplorer/WebUI/css/b2r2.footer.css b/src/RearEnd/BinExplorer/WebUI/css/b2r2.footer.css similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/b2r2.footer.css rename to src/RearEnd/BinExplorer/WebUI/css/b2r2.footer.css diff --git a/src/Utilities/BinExplorer/WebUI/css/b2r2.graph.css b/src/RearEnd/BinExplorer/WebUI/css/b2r2.graph.css similarity index 97% rename from src/Utilities/BinExplorer/WebUI/css/b2r2.graph.css rename to src/RearEnd/BinExplorer/WebUI/css/b2r2.graph.css index 484afb53..d9ae2547 100644 --- a/src/Utilities/BinExplorer/WebUI/css/b2r2.graph.css +++ b/src/RearEnd/BinExplorer/WebUI/css/b2r2.graph.css @@ -132,6 +132,10 @@ stroke: var(--graph-edge-fallthrough-stroke); } +.c-graph__exceptionfallthroughedge { + stroke: var(--graph-edge-fallthrough-stroke); +} + /* Arrow */ .c-arrow-interjmpedge { fill: var(--graph-edge-interjmp-stroke); @@ -185,6 +189,10 @@ fill: var(--graph-edge-fallthrough-stroke); } +.c-arrow-exceptionfallthroughedge { + fill: var(--graph-edge-fallthrough-stroke); +} + .c-minimap { margin-right: 10px; margin-bottom: 10px; diff --git a/src/Utilities/BinExplorer/WebUI/css/b2r2.header.css b/src/RearEnd/BinExplorer/WebUI/css/b2r2.header.css similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/b2r2.header.css rename to src/RearEnd/BinExplorer/WebUI/css/b2r2.header.css diff --git a/src/Utilities/BinExplorer/WebUI/css/b2r2.main.css b/src/RearEnd/BinExplorer/WebUI/css/b2r2.main.css similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/b2r2.main.css rename to src/RearEnd/BinExplorer/WebUI/css/b2r2.main.css diff --git a/src/Utilities/BinExplorer/WebUI/css/b2r2.modal.css b/src/RearEnd/BinExplorer/WebUI/css/b2r2.modal.css similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/b2r2.modal.css rename to src/RearEnd/BinExplorer/WebUI/css/b2r2.modal.css diff --git a/src/Utilities/BinExplorer/WebUI/css/b2r2.rotating.css b/src/RearEnd/BinExplorer/WebUI/css/b2r2.rotating.css similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/b2r2.rotating.css rename to src/RearEnd/BinExplorer/WebUI/css/b2r2.rotating.css diff --git a/src/Utilities/BinExplorer/WebUI/css/b2r2.toast.css b/src/RearEnd/BinExplorer/WebUI/css/b2r2.toast.css similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/b2r2.toast.css rename to src/RearEnd/BinExplorer/WebUI/css/b2r2.toast.css diff --git a/src/Utilities/BinExplorer/WebUI/css/bootstrap.min.css b/src/RearEnd/BinExplorer/WebUI/css/bootstrap.min.css similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/bootstrap.min.css rename to src/RearEnd/BinExplorer/WebUI/css/bootstrap.min.css diff --git a/src/Utilities/BinExplorer/WebUI/css/fontawesome.min.css b/src/RearEnd/BinExplorer/WebUI/css/fontawesome.min.css similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/fontawesome.min.css rename to src/RearEnd/BinExplorer/WebUI/css/fontawesome.min.css diff --git a/src/Utilities/BinExplorer/WebUI/css/images/ui-icons_444444_256x240.png b/src/RearEnd/BinExplorer/WebUI/css/images/ui-icons_444444_256x240.png similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/images/ui-icons_444444_256x240.png rename to src/RearEnd/BinExplorer/WebUI/css/images/ui-icons_444444_256x240.png diff --git a/src/Utilities/BinExplorer/WebUI/css/images/ui-icons_555555_256x240.png b/src/RearEnd/BinExplorer/WebUI/css/images/ui-icons_555555_256x240.png similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/images/ui-icons_555555_256x240.png rename to src/RearEnd/BinExplorer/WebUI/css/images/ui-icons_555555_256x240.png diff --git a/src/Utilities/BinExplorer/WebUI/css/images/ui-icons_777620_256x240.png b/src/RearEnd/BinExplorer/WebUI/css/images/ui-icons_777620_256x240.png similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/images/ui-icons_777620_256x240.png rename to src/RearEnd/BinExplorer/WebUI/css/images/ui-icons_777620_256x240.png diff --git a/src/Utilities/BinExplorer/WebUI/css/images/ui-icons_777777_256x240.png b/src/RearEnd/BinExplorer/WebUI/css/images/ui-icons_777777_256x240.png similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/images/ui-icons_777777_256x240.png rename to src/RearEnd/BinExplorer/WebUI/css/images/ui-icons_777777_256x240.png diff --git a/src/Utilities/BinExplorer/WebUI/css/images/ui-icons_cc0000_256x240.png b/src/RearEnd/BinExplorer/WebUI/css/images/ui-icons_cc0000_256x240.png similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/images/ui-icons_cc0000_256x240.png rename to src/RearEnd/BinExplorer/WebUI/css/images/ui-icons_cc0000_256x240.png diff --git a/src/Utilities/BinExplorer/WebUI/css/images/ui-icons_ffffff_256x240.png b/src/RearEnd/BinExplorer/WebUI/css/images/ui-icons_ffffff_256x240.png similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/images/ui-icons_ffffff_256x240.png rename to src/RearEnd/BinExplorer/WebUI/css/images/ui-icons_ffffff_256x240.png diff --git a/src/Utilities/BinExplorer/WebUI/css/jquery-ui.min.css b/src/RearEnd/BinExplorer/WebUI/css/jquery-ui.min.css similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/jquery-ui.min.css rename to src/RearEnd/BinExplorer/WebUI/css/jquery-ui.min.css diff --git a/src/Utilities/BinExplorer/WebUI/css/jquery.contextMenu.min.css b/src/RearEnd/BinExplorer/WebUI/css/jquery.contextMenu.min.css similarity index 100% rename from src/Utilities/BinExplorer/WebUI/css/jquery.contextMenu.min.css rename to src/RearEnd/BinExplorer/WebUI/css/jquery.contextMenu.min.css diff --git a/src/Utilities/BinExplorer/WebUI/favicon.ico b/src/RearEnd/BinExplorer/WebUI/favicon.ico similarity index 100% rename from src/Utilities/BinExplorer/WebUI/favicon.ico rename to src/RearEnd/BinExplorer/WebUI/favicon.ico diff --git a/src/Utilities/BinExplorer/WebUI/fonts/Inconsolata-Bold.ttf b/src/RearEnd/BinExplorer/WebUI/fonts/Inconsolata-Bold.ttf similarity index 100% rename from src/Utilities/BinExplorer/WebUI/fonts/Inconsolata-Bold.ttf rename to src/RearEnd/BinExplorer/WebUI/fonts/Inconsolata-Bold.ttf diff --git a/src/Utilities/BinExplorer/WebUI/fonts/Inconsolata-Regular.ttf b/src/RearEnd/BinExplorer/WebUI/fonts/Inconsolata-Regular.ttf similarity index 100% rename from src/Utilities/BinExplorer/WebUI/fonts/Inconsolata-Regular.ttf rename to src/RearEnd/BinExplorer/WebUI/fonts/Inconsolata-Regular.ttf diff --git a/src/Utilities/BinExplorer/WebUI/fonts/context-menu-icons.woff2 b/src/RearEnd/BinExplorer/WebUI/fonts/context-menu-icons.woff2 similarity index 100% rename from src/Utilities/BinExplorer/WebUI/fonts/context-menu-icons.woff2 rename to src/RearEnd/BinExplorer/WebUI/fonts/context-menu-icons.woff2 diff --git a/src/Utilities/BinExplorer/WebUI/fonts/fa-brands-400.woff2 b/src/RearEnd/BinExplorer/WebUI/fonts/fa-brands-400.woff2 similarity index 100% rename from src/Utilities/BinExplorer/WebUI/fonts/fa-brands-400.woff2 rename to src/RearEnd/BinExplorer/WebUI/fonts/fa-brands-400.woff2 diff --git a/src/Utilities/BinExplorer/WebUI/fonts/fa-regular-400.woff2 b/src/RearEnd/BinExplorer/WebUI/fonts/fa-regular-400.woff2 similarity index 100% rename from src/Utilities/BinExplorer/WebUI/fonts/fa-regular-400.woff2 rename to src/RearEnd/BinExplorer/WebUI/fonts/fa-regular-400.woff2 diff --git a/src/Utilities/BinExplorer/WebUI/fonts/fa-solid-900.woff2 b/src/RearEnd/BinExplorer/WebUI/fonts/fa-solid-900.woff2 similarity index 100% rename from src/Utilities/BinExplorer/WebUI/fonts/fa-solid-900.woff2 rename to src/RearEnd/BinExplorer/WebUI/fonts/fa-solid-900.woff2 diff --git a/src/Utilities/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.eot b/src/RearEnd/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.eot similarity index 100% rename from src/Utilities/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.eot rename to src/RearEnd/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.eot diff --git a/src/Utilities/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.svg b/src/RearEnd/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.svg similarity index 100% rename from src/Utilities/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.svg rename to src/RearEnd/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.svg diff --git a/src/Utilities/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.ttf b/src/RearEnd/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.ttf similarity index 100% rename from src/Utilities/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.ttf rename to src/RearEnd/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.ttf diff --git a/src/Utilities/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.woff b/src/RearEnd/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.woff similarity index 100% rename from src/Utilities/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.woff rename to src/RearEnd/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.woff diff --git a/src/Utilities/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.woff2 b/src/RearEnd/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.woff2 similarity index 100% rename from src/Utilities/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.woff2 rename to src/RearEnd/BinExplorer/WebUI/fonts/glyphicons-halflings-regular.woff2 diff --git a/src/Utilities/BinExplorer/WebUI/index.html b/src/RearEnd/BinExplorer/WebUI/index.html similarity index 100% rename from src/Utilities/BinExplorer/WebUI/index.html rename to src/RearEnd/BinExplorer/WebUI/index.html diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.consts.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.consts.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.consts.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.consts.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.flowgraph.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.flowgraph.js similarity index 98% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.flowgraph.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.flowgraph.js index 2a7b38f3..24387a4b 100644 --- a/src/Utilities/BinExplorer/WebUI/js/b2r2.flowgraph.js +++ b/src/RearEnd/BinExplorer/WebUI/js/b2r2.flowgraph.js @@ -55,10 +55,10 @@ class FlowGraph extends Graph { .curve(d3.curveMonotoneY); } - queryDataflow(roots, addr, term) { + queryDataflow(roots, addr, tag, term) { const myself = this; const root = roots[0]; - const args = [root, addr, term]; + const args = [root, addr, tag, term]; query({ "q": "DataFlow", "args": args }, function (_status, json) { let nodes = myself.linemap[addr].Tokens[term]; for (let i = 0; i < json.length; i++) { @@ -94,7 +94,7 @@ class FlowGraph extends Graph { span.on("click", function () { myself.deactivateHighlights(); d3.event.stopPropagation(); - myself.queryDataflow(roots, addr, term); + myself.queryDataflow(roots, addr, tag, term); }); } } diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.graph.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.graph.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.graph.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.graph.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.header.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.header.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.header.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.header.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.hexgraph.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.hexgraph.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.hexgraph.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.hexgraph.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.keyhandler.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.keyhandler.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.keyhandler.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.keyhandler.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.minimap.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.minimap.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.minimap.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.minimap.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.navbar.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.navbar.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.navbar.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.navbar.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.search.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.search.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.search.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.search.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.side.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.side.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.side.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.side.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.svgdefs.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.svgdefs.js similarity index 97% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.svgdefs.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.svgdefs.js index 6eb42cb5..8402f15a 100644 --- a/src/Utilities/BinExplorer/WebUI/js/b2r2.svgdefs.js +++ b/src/RearEnd/BinExplorer/WebUI/js/b2r2.svgdefs.js @@ -38,6 +38,7 @@ class SVGDefs { SVGDefs.setMarkerArrow(defs, "IntraCJmpFalseEdge"); SVGDefs.setMarkerArrow(defs, "FallThroughEdge"); SVGDefs.setMarkerArrow(defs, "CallFallThroughEdge"); + SVGDefs.setMarkerArrow(defs, "ExceptionFallThroughEdge"); SVGDefs.setMarkerArrow(defs, "RecursiveCallEdge"); SVGDefs.setMarkerArrow(defs, "CallEdge"); SVGDefs.setMarkerArrow(defs, "RetEdge"); diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.termgraph.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.termgraph.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.termgraph.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.termgraph.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.toast.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.toast.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.toast.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.toast.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.utils.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.utils.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.utils.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.utils.js diff --git a/src/Utilities/BinExplorer/WebUI/js/b2r2.window.js b/src/RearEnd/BinExplorer/WebUI/js/b2r2.window.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/b2r2.window.js rename to src/RearEnd/BinExplorer/WebUI/js/b2r2.window.js diff --git a/src/Utilities/BinExplorer/WebUI/js/bootstrap.min.js b/src/RearEnd/BinExplorer/WebUI/js/bootstrap.min.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/bootstrap.min.js rename to src/RearEnd/BinExplorer/WebUI/js/bootstrap.min.js diff --git a/src/Utilities/BinExplorer/WebUI/js/d3.min.js b/src/RearEnd/BinExplorer/WebUI/js/d3.min.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/d3.min.js rename to src/RearEnd/BinExplorer/WebUI/js/d3.min.js diff --git a/src/Utilities/BinExplorer/WebUI/js/jquery-ui.min.js b/src/RearEnd/BinExplorer/WebUI/js/jquery-ui.min.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/jquery-ui.min.js rename to src/RearEnd/BinExplorer/WebUI/js/jquery-ui.min.js diff --git a/src/Utilities/BinExplorer/WebUI/js/jquery.contextMenu.min.js b/src/RearEnd/BinExplorer/WebUI/js/jquery.contextMenu.min.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/jquery.contextMenu.min.js rename to src/RearEnd/BinExplorer/WebUI/js/jquery.contextMenu.min.js diff --git a/src/Utilities/BinExplorer/WebUI/js/jquery.mark.min.js b/src/RearEnd/BinExplorer/WebUI/js/jquery.mark.min.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/jquery.mark.min.js rename to src/RearEnd/BinExplorer/WebUI/js/jquery.mark.min.js diff --git a/src/Utilities/BinExplorer/WebUI/js/jquery.min.js b/src/RearEnd/BinExplorer/WebUI/js/jquery.min.js similarity index 100% rename from src/Utilities/BinExplorer/WebUI/js/jquery.min.js rename to src/RearEnd/BinExplorer/WebUI/js/jquery.min.js diff --git a/src/Utilities/Core/B2R2.Utilities.Core.fsproj b/src/RearEnd/Core/B2R2.RearEnd.Core.fsproj similarity index 64% rename from src/Utilities/Core/B2R2.Utilities.Core.fsproj rename to src/RearEnd/Core/B2R2.RearEnd.Core.fsproj index 612d5302..183a2d7e 100644 --- a/src/Utilities/Core/B2R2.Utilities.Core.fsproj +++ b/src/RearEnd/Core/B2R2.RearEnd.Core.fsproj @@ -1,13 +1,13 @@ - + - netstandard2.1 + net5.0 false - false - + + diff --git a/src/RearEnd/Core/CmdOpts.fs b/src/RearEnd/Core/CmdOpts.fs new file mode 100644 index 00000000..a55bf72e --- /dev/null +++ b/src/RearEnd/Core/CmdOpts.fs @@ -0,0 +1,123 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd + +open B2R2 +open B2R2.FsOptParse +open System + +module CS = ColoredSegment + +/// A common set of command-line options used in analyzing binaries. +type CmdOpts () = + /// Verbosity + member val Verbose = false with get, set + + /// Just a wrapper function that instantiate an OptParse.Option object. + static member New<'a> (descr, ?callback, ?required, ?extra, ?help, + ?short, ?long, ?dummy, ?descrColor) = + Option<'a> (descr, + ?callback=callback, + ?required=required, + ?extra=extra, ?help=help, + ?short=short, ?long=long, + ?dummy=dummy, ?descrColor=descrColor) + + /// "-v" or "--verbose" option turns on the verbose mode. + static member OptVerbose () = + let cb (opts: #CmdOpts) _ = + opts.Verbose <- true; opts + CmdOpts.New (descr = "Verbose mode", + callback = cb, short = "-v", long = "--verbose") + + /// "-h" or "--help" option. + static member OptHelp () = + CmdOpts.New (descr = "Show this usage", + help = true, short = "-h", long = "--help") + + /// Write B2R2 logo to console. We can selectively append a new line at the + /// end. + static member WriteB2R2 newLine = + [ CS.dcyan "B"; CS.dyellow "2"; CS.dcyan "R"; CS.dyellow "2" ] + |> Printer.printToConsole + if newLine then Printer.printToConsoleLine () else () + + static member private WriteIntro () = + CmdOpts.WriteB2R2 false + Printer.printToConsoleLine (", the Next-Generation Reversing Platform") + Printer.printToConsoleLine (Attribution.copyright + Environment.NewLine) + + static member private CreateUsageGetter tool usageTail = + fun () -> + CmdOpts.WriteIntro () + let tail = if String.IsNullOrEmpty usageTail then "" else " " + usageTail + String.Format ("[Usage]{0}{0}dotnet b2r2 {1} %o{2}", + Environment.NewLine, tool, tail) + + static member private TermFunction () = exit 1 + + static member private parseCmdOpts spec defaultOpts argv tool usageTail = + let prog = Environment.GetCommandLineArgs().[0] + let usageGetter = CmdOpts.CreateUsageGetter tool usageTail + try + optParse spec usageGetter prog argv defaultOpts + with + | SpecErr msg -> + eprintfn "Invalid spec: %s" msg + exit 1 + | RuntimeErr msg -> + eprintfn "Invalid command line args given: %s" msg + usagePrint spec prog usageGetter CmdOpts.TermFunction + | e -> + eprintfn "Fatal error: %s" e.Message + usagePrint spec prog usageGetter CmdOpts.TermFunction + + static member PrintUsage tool usageTail spec = + let prog = Environment.GetCommandLineArgs().[0] + let usageGetter = CmdOpts.CreateUsageGetter tool usageTail + usagePrint spec prog usageGetter CmdOpts.TermFunction + + /// Parse command line arguments, and run the mainFn + static member ParseAndRun mainFn tool usageTail spec (opts: #CmdOpts) args = + let rest, opts = CmdOpts.parseCmdOpts spec opts args tool usageTail + if opts.Verbose then CmdOpts.WriteIntro () else () + try mainFn rest opts; 0 + with e -> eprintfn "Error: %s" e.Message + eprintfn "%s" (if opts.Verbose then e.StackTrace else ""); 1 + + /// Check if the rest args contain an option string. If so, exit the program. + /// Otherwise, do nothing. + static member SanitizeRestArgs args = + let rec sanitize = function + | (arg: string) :: rest -> + if arg.StartsWith ('-') then + Printer.printErrorToConsole + <| sprintf "Invalid argument (%s) is used" arg + exit 1 + else sanitize rest + | [] -> () + sanitize args + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/RearEnd/Core/HexDumper.fs b/src/RearEnd/Core/HexDumper.fs new file mode 100644 index 00000000..2b8910f1 --- /dev/null +++ b/src/RearEnd/Core/HexDumper.fs @@ -0,0 +1,75 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd + +open B2R2 + +module CS = ColoredSegment + +module HexDumper = + let internal padSpace chuckSize length = + let m = length % chuckSize + if m = 0 then Array.empty else Array.create (chuckSize - m) " " + + let internal addSpace idx s = + match idx with + | 0 -> s + | 8 | 16 | 24 -> " " + s + | _ -> " " + s + + let internal colorHexDumper addrStr chuckSize (bytes: byte []) = + let padding = + padSpace chuckSize bytes.Length + |> Array.map (fun pad -> ColoredSegment (NoColor, pad)) + let coloredHex = + Array.append (bytes |> Array.map CS.byteToHex) padding + |> Array.mapi (fun idx (color, hex) -> color, addSpace idx hex) + let coloredAscii = bytes |> Array.map CS.byteToAscii + Array.append [| ColoredSegment (NoColor, " | ") |] coloredAscii + |> Array.append coloredHex + |> Array.append [| ColoredSegment (NoColor, addrStr + ": ") |] + |> List.ofArray + |> ColoredString.compile + |> OutputColored + + let internal regularHexDumper addrStr chuckSize (bytes: byte []) = + let padding = padSpace chuckSize (bytes.Length) + let hex = + Array.append (bytes |> Array.map (fun b -> b.ToString ("X2"))) padding + |> Array.mapi (fun idx s -> addSpace idx s) + |> Array.fold (fun arr s -> arr + s) "" + let ascii = + bytes |> Array.fold (fun arr b -> arr + CS.getRepresentation b) "" + addrStr + ": " + hex + " | " + ascii + |> OutputNormal + + let internal dumpLine chuckSize wordSize isColored addr linenum bytes = + let addrStr = Addr.toString wordSize (addr + uint64 (linenum * chuckSize)) + let dumper = if isColored then colorHexDumper else regularHexDumper + dumper addrStr chuckSize bytes + + let dump chuckSize wordSize isColored addr bytes = + Array.chunkBySize chuckSize bytes + |> Array.mapi (dumpLine chuckSize wordSize isColored addr) diff --git a/src/RearEnd/FileViewer/B2R2.RearEnd.FileViewer.fsproj b/src/RearEnd/FileViewer/B2R2.RearEnd.FileViewer.fsproj new file mode 100644 index 00000000..05fc5700 --- /dev/null +++ b/src/RearEnd/FileViewer/B2R2.RearEnd.FileViewer.fsproj @@ -0,0 +1,24 @@ + + + + Exe + net5.0 + false + + + + + + + + + + + + + + + + + + diff --git a/src/RearEnd/FileViewer/Cmd.fs b/src/RearEnd/FileViewer/Cmd.fs new file mode 100644 index 00000000..aea11e17 --- /dev/null +++ b/src/RearEnd/FileViewer/Cmd.fs @@ -0,0 +1,272 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.FileViewer + +open B2R2 +open B2R2.RearEnd +open System +open System.Collections.Generic + +type FileViewerOpts () = + inherit CmdOpts () + + let items = HashSet () + + /// Display items. + member val DisplayItems = items with get + + /// Specific ISA. This is only meaningful for universal (fat) binaries because + /// BinHandle will automatically detect file format by default. When a fat + /// binary is given, we need to choose which architecture to explorer with + /// this option. + member val ISA = ISA.DefaultISA with get, set + + /// Base address to use. By default, it is zero (0). + member val BaseAddress: Addr option = None with get, set + + static member private ToThis (opts: CmdOpts) = + match opts with + | :? FileViewerOpts as opts -> opts + | _ -> failwith "Invalid Opts." + + static member private AddOpt (opts: #CmdOpts) item = + (FileViewerOpts.ToThis opts).DisplayItems.Add item |> ignore + opts + + /// "-h" or "--help" option. + static member OptHelp () = + CmdOpts.New (descr = "Show this usage", help = true, long = "--help") + + /// "-b" or "--base-addr" option for specifying a base address. + static member OptBaseAddr () = + let cb opts (arg: string []) = + (FileViewerOpts.ToThis opts).BaseAddress <- + Some (Convert.ToUInt64 (arg.[0], 16)) + opts + CmdOpts.New (descr = "Specify the base
in hex (default=0)", + extra = 1, callback = cb, short = "-b", long = "--base-addr") + + /// "-a" or "--all" option for displaying all the file information. + static member OptAll () = + let cb opts _ = FileViewerOpts.AddOpt opts DisplayAll + CmdOpts.New (descr = "Display all the file information", + callback = cb, short = "-a", long = "--all") + + /// "-h" or "--file-header" option for displaying the file header. + static member OptFileHeader () = + let cb opts _ = + FileViewerOpts.AddOpt opts DisplayFileHeader + CmdOpts.New (descr = "Display the file header", + callback = cb, short = "-h", long = "--file-header") + + /// "--section-headers" option for displaying the section headers. + static member OptSectionHeaders () = + let cb opts _ = + FileViewerOpts.AddOpt opts DisplaySectionHeaders + CmdOpts.New (descr = "Display the section headers", + callback = cb, short = "-S", long = "--section-headers") + + /// "--section-details" option for displaying the target section details. + static member OptSectionDetails () = + let cb opts (arg: string []) = + FileViewerOpts.AddOpt opts (DisplaySectionDetails arg.[0]) + CmdOpts.New (descr = "Display the section details", extra = 1, + callback = cb, short = "-d", long = "--section-details") + + /// "-s" or "--symbols" option for displaying the symbols. + static member OptSymbols () = + let cb opts _ = + FileViewerOpts.AddOpt opts DisplaySymbols + CmdOpts.New (descr = "Display the symbols", + callback = cb, short = "-s", long = "--symbols") + + /// "--relocs" option for displaying the relocation section. + static member OptRelocs () = + let cb opts _ = + FileViewerOpts.AddOpt opts DisplayRelocations + CmdOpts.New (descr = "Display the relocation section", + callback = cb, short = "-r", long = "--relocations") + + /// "-f" or "--functions" option for displaying the functions. + static member OptFunctions () = + let cb opts _ = + FileViewerOpts.AddOpt opts DisplayFunctions + CmdOpts.New (descr = "Display the function symbols", + callback = cb, short = "-f", long = "--functions") + + /// "--program-headers" option for displaying the program headers. + static member OptProgramHeaders () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayELFSpecific ELFDisplayProgramHeader) + CmdOpts.New (descr = "Display the program headers", + callback = cb, long = "--program-headers") + + /// "--plt" option for displaying the PLT. + static member OptPLT () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayELFSpecific ELFDisplayPLT) + CmdOpts.New (descr = "Display the PLT-GOT information", + callback = cb, long = "--plt") + + /// "--ehframe" option for displaying the eh_frame section information. + static member OptEHFrame () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayELFSpecific ELFDisplayEHFrame) + CmdOpts.New (descr = "Display the eh_frame information", + callback = cb, long = "--ehframe") + + /// "--lsda" option for displaying the .gcc_except_table section information, + /// i.e., LSDAs. + static member OptLSDA () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayELFSpecific ELFDisplayLSDA) + CmdOpts.New (descr = "Display the LSDA information", + callback = cb, long = "--lsda") + + /// "--notes" option for displaying the notes section information. + static member OptNotes () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayELFSpecific ELFDisplayNotes) + CmdOpts.New (descr = "Display the notes information", + callback = cb, long = "--notes") + + /// "--imports" option for displaying the import table. + static member OptImports () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayPESpecific PEDisplayImports) + CmdOpts.New (descr = "Display the import table", + callback = cb, long = "--imports") + + /// "--exports" option for displaying the export table. + static member OptExports () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayPESpecific PEDisplayExports) + CmdOpts.New (descr = "Display the export table", + callback = cb, long = "--exports") + + /// "--optional-header" option for displaying the optional header. + static member OptOptionalHeader () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayPESpecific PEDisplayOptionalHeader) + CmdOpts.New (descr = "Display the optional header", + callback = cb, long = "--optional-header") + + /// "--clr-header" option for displaying the CLR header. + static member OptCLRHeader () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayPESpecific PEDisplayCLRHeader) + CmdOpts.New (descr = "Display the CLR header", + callback = cb, long = "--clr-header") + + /// "--dependencies" option for displaying the dependencies. + static member OptDependencies () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayPESpecific PEDisplayDependencies) + CmdOpts.New (descr = "Display the dependencies", + callback = cb, long = "--dependencies") + + /// "--archive-header" option for displaying the archive header. + static member OptArchiveHeader () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayMachSpecific MachDisplayArchiveHeader) + CmdOpts.New (descr = "Display the archive header", + callback = cb, long = "--archive-header") + + /// "--universal-header" option for displaying the universal header. + static member OptUniversalHeader () = + let cb opts _ = + FileViewerOpts.AddOpt opts + (DisplayMachSpecific MachDisplayUniversalHeader) + CmdOpts.New (descr = "Display the universal header", + callback = cb, long = "--universal-header") + + /// "--load-commands" option for displaying the load commands. + static member OptLoadCommands () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayMachSpecific MachDisplayLoadCommands) + CmdOpts.New (descr = "Display the load commands", + callback = cb, long = "--load-commands") + + /// "--shared-libs" option for displaying the shared libraries. + static member OptSharedLibs () = + let cb opts _ = + FileViewerOpts.AddOpt opts (DisplayMachSpecific MachDisplaySharedLibs) + CmdOpts.New (descr = "Display the shared libraries", + callback = cb, long = "--shared-libs") + + /// "-i" or "--isa" option for specifying ISA. + static member OptISA () = + let cb opts (arg: string []) = + (FileViewerOpts.ToThis opts).ISA <- ISA.OfString arg.[0]; opts + CmdOpts.New (descr = "Specify (e.g., x86) for fat binaries", + extra = 1, callback = cb, short = "-i", long= "--isa") + +[] +module Cmd = + let spec: FileViewerOpts FsOptParse.Option list = + [ CmdOpts.New (descr = "[General options]", dummy = true) + CmdOpts.New (descr = "", dummy = true) + + FileViewerOpts.OptHelp () + CmdOpts.OptVerbose () + FileViewerOpts.OptBaseAddr () + FileViewerOpts.OptAll () + FileViewerOpts.OptFileHeader () + FileViewerOpts.OptSectionHeaders () + FileViewerOpts.OptSectionDetails () + FileViewerOpts.OptSymbols () + FileViewerOpts.OptRelocs () + FileViewerOpts.OptFunctions () + + CmdOpts.New (descr = "", dummy = true) + CmdOpts.New (descr = "[ELF options]", dummy = true) + CmdOpts.New (descr = "", dummy = true) + + FileViewerOpts.OptProgramHeaders () + FileViewerOpts.OptPLT () + FileViewerOpts.OptEHFrame () + FileViewerOpts.OptLSDA () + FileViewerOpts.OptNotes () + + CmdOpts.New (descr = "", dummy = true) + CmdOpts.New (descr = "[PE options]", dummy = true) + CmdOpts.New (descr = "", dummy = true) + + FileViewerOpts.OptImports () + FileViewerOpts.OptExports () + FileViewerOpts.OptOptionalHeader () + FileViewerOpts.OptCLRHeader () + FileViewerOpts.OptDependencies () + + CmdOpts.New (descr = "", dummy = true) + CmdOpts.New (descr = "[Mach-O options]", dummy = true) + CmdOpts.New (descr = "", dummy = true) + + FileViewerOpts.OptArchiveHeader () + FileViewerOpts.OptUniversalHeader () + FileViewerOpts.OptLoadCommands () + FileViewerOpts.OptSharedLibs () + + FileViewerOpts.OptISA () ] diff --git a/src/BinEssence/RecoveredInfo.fs b/src/RearEnd/FileViewer/DisplayItem.fs similarity index 51% rename from src/BinEssence/RecoveredInfo.fs rename to src/RearEnd/FileViewer/DisplayItem.fs index 07ccb3dd..39cc5096 100644 --- a/src/BinEssence/RecoveredInfo.fs +++ b/src/RearEnd/FileViewer/DisplayItem.fs @@ -22,39 +22,50 @@ SOFTWARE. *) -namespace B2R2.BinEssence - -open B2R2 - -type IndirectBranchInfo = { - /// The host function (owner) of the indirect jump. - HostFunctionAddr: Addr - /// Possible target addresses. - TargetAddresses: Set - /// Information about the corresponding jump table (if exists). - JumpTableInfo: JumpTableInfo option -} - -/// Jump table (for switch-case) information. -and JumpTableInfo = { - /// Base address of the jump table. - JTBaseAddr: Addr - /// The start and the end address of the jump table (AddrRange). - JTRange: AddrRange - /// Size of each entry of the table. - JTEntrySize: RegType -} -with - static member Init jtBase jtRange jtEntrySize = - { JTBaseAddr = jtBase ; JTRange = jtRange ; JTEntrySize = jtEntrySize } - -/// No-return function info. -type NoReturnInfo = { - /// No-return function addresses. - NoReturnFuncs: Set - /// Program points of no-return call sites. - NoReturnCallSites: Set -} -with - static member Init noRetFuncs noRetCallSites = - { NoReturnFuncs = noRetFuncs ; NoReturnCallSites = noRetCallSites } +namespace B2R2.RearEnd.FileViewer + +/// Display items for ELF. +type ELFDisplayItem = + | ELFDisplayProgramHeader + | ELFDisplayPLT + | ELFDisplayEHFrame + | ELFDisplayLSDA + | ELFDisplayNotes + +/// Display items for PE. +type PEDisplayItem = + | PEDisplayImports + | PEDisplayExports + | PEDisplayOptionalHeader + | PEDisplayCLRHeader + | PEDisplayDependencies + +/// Display items for Mach-O. +type MachDisplayItem = + | MachDisplayArchiveHeader + | MachDisplayUniversalHeader + | MachDisplayLoadCommands + | MachDisplaySharedLibs + +/// Display items for FileViewer. +type DisplayItem = + /// Special item that represents all items. + | DisplayAll + /// Basic file header information. + | DisplayFileHeader + /// Section headers + | DisplaySectionHeaders + /// Section details + | DisplaySectionDetails of string + /// Symbols. + | DisplaySymbols + /// Relocations + | DisplayRelocations + /// Functions. + | DisplayFunctions + /// ELF-specific item. + | DisplayELFSpecific of ELFDisplayItem + /// PE-specific item. + | DisplayPESpecific of PEDisplayItem + /// Mach-specific item. + | DisplayMachSpecific of MachDisplayItem diff --git a/src/RearEnd/FileViewer/ELFViewer.fs b/src/RearEnd/FileViewer/ELFViewer.fs new file mode 100644 index 00000000..268fdfa2 --- /dev/null +++ b/src/RearEnd/FileViewer/ELFViewer.fs @@ -0,0 +1,323 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.RearEnd.FileViewer.ELFViewer + +open B2R2 +open B2R2.FrontEnd.BinInterface +open B2R2.FrontEnd.BinFile +open B2R2.RearEnd.FileViewer.Helper + +let badAccess _ _ = + raise InvalidFileTypeException + +let computeMagicBytes (fi: ELFFileInfo) = + fi.ELF.BinReader.PeekBytes (16, 0) |> ColoredSegment.colorBytes + +let computeEntryPoint (hdr: ELF.ELFHeader) = + [ ColoredSegment.green <| String.u64ToHex hdr.EntryPoint ] + +let dumpFileHeader (_: FileViewerOpts) (fi: ELFFileInfo) = + let hdr = fi.ELF.ELFHdr + out.PrintTwoColsWithColorOnSnd "Magic:" (computeMagicBytes fi) + out.PrintTwoCols "Class:" ("ELF" + WordSize.toString hdr.Class) + out.PrintTwoCols "Data:" (Endian.toString hdr.Endian + " endian") + out.PrintTwoCols "Version:" (hdr.Version.ToString ()) + out.PrintTwoCols "ABI:" (hdr.OSABI.ToString ()) + out.PrintTwoCols "ABI version:" (hdr.OSABIVersion.ToString ()) + out.PrintTwoCols "Type:" (hdr.ELFFileType.ToString ()) + out.PrintTwoCols "Machine:" (hdr.MachineType.ToString ()) + out.PrintTwoColsWithColorOnSnd "Entry point:" (computeEntryPoint hdr) + out.PrintTwoCols "PHdr table offset:" (String.u64ToHex hdr.PHdrTblOffset) + out.PrintTwoCols "SHdr table offset:" (String.u64ToHex hdr.SHdrTblOffset) + out.PrintTwoCols "Flags:" (String.u64ToHex (uint64 hdr.ELFFlags)) + out.PrintTwoCols "Header size:" (toNBytes (uint64 hdr.HeaderSize)) + out.PrintTwoCols "PHdr Entry Size:" (toNBytes (uint64 hdr.PHdrEntrySize)) + out.PrintTwoCols "PHdr Entry Num:" (hdr.PHdrNum.ToString ()) + out.PrintTwoCols "SHdr Entry Size:" (toNBytes (uint64 (hdr.SHdrEntrySize))) + out.PrintTwoCols "SHdr Entry Num:" (hdr.SHdrNum.ToString ()) + out.PrintTwoCols "SHdr string index:" (hdr.SHdrStrIdx.ToString ()) + +let dumpSectionHeaders (opts: FileViewerOpts) (fi: ELFFileInfo) = + let addrColumn = columnWidthOfAddr fi |> LeftAligned + if opts.Verbose then + let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 24; + LeftAligned 14; LeftAligned 12; LeftAligned 8; LeftAligned 10; + LeftAligned 4; LeftAligned 4; LeftAligned 6; LeftAligned 20 ] + out.PrintRow (true, cfg, [ "Num"; "Start"; "End"; "Name" + "Type"; "Offset"; "Size"; "EntrySize" + "Link"; "Info"; "Align"; "Flags" ]) + out.PrintLine " ---" + fi.ELF.SecInfo.SecByNum + |> Array.iteri (fun idx s -> + out.PrintRow (true, cfg, + [ String.wrapSqrdBracket (idx.ToString ()) + (Addr.toString fi.WordSize s.SecAddr) + (Addr.toString fi.WordSize (s.SecAddr + s.SecSize - uint64 1)) + normalizeEmpty s.SecName + s.SecType.ToString () + String.u64ToHex s.SecOffset + String.u64ToHex s.SecSize + String.u64ToHex s.SecEntrySize + s.SecLink.ToString () + s.SecInfo.ToString () + String.u64ToHex s.SecAlignment + s.SecFlags.ToString () ])) + else + let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 24 ] + out.PrintRow (true, cfg, [ "Num"; "Start"; "End"; "Name" ]) + out.PrintLine " ---" + fi.GetSections () + |> Seq.iteri (fun idx s -> + out.PrintRow (true, cfg, + [ String.wrapSqrdBracket (idx.ToString ()) + (Addr.toString fi.WordSize s.Address) + (Addr.toString fi.WordSize (s.Address + s.Size - uint64 1)) + normalizeEmpty s.Name ])) + +let dumpSectionDetails (secname: string) (fi: ELFFileInfo) = + match fi.ELF.SecInfo.SecByName.TryFind secname with + | Some section -> + out.PrintTwoCols "Section number:" (section.SecNum.ToString ()) + out.PrintTwoCols "Section name:" section.SecName + out.PrintTwoCols "Type:" (section.SecType.ToString ()) + out.PrintTwoCols "Address:" (String.u64ToHex section.SecAddr) + out.PrintTwoCols "Offset:" (String.u64ToHex section.SecOffset) + out.PrintTwoCols "Size:" (String.u64ToHex section.SecSize) + out.PrintTwoCols "Entry Size:" (String.u64ToHex section.SecEntrySize) + out.PrintTwoCols "Flag:" (section.SecFlags.ToString ()) + out.PrintTwoCols "Link:" (section.SecLink.ToString ()) + out.PrintTwoCols "Info:" (section.SecInfo.ToString ()) + out.PrintTwoCols "Alignment:" (String.u64ToHex section.SecAlignment) + | None -> out.PrintLine "Not found." + +let printSymbolInfoVerbose (fi: ELFFileInfo) s (elfSymbol: ELF.ELFSymbol) cfg = + let sectionIndex = + match elfSymbol.SecHeaderIndex with + | ELF.SectionHeaderIdx.SecIdx idx -> idx.ToString () + | _ as idx -> idx.ToString () + out.PrintRow (true, cfg, + [ targetString s + Addr.toString fi.WordSize s.Address + normalizeEmpty s.Name + (toLibString >> normalizeEmpty) s.LibraryName + String.u64ToHex elfSymbol.Size + elfSymbol.SymType.ToString () + elfSymbol.Bind.ToString () + elfSymbol.Vis.ToString () + String.wrapSqrdBracket sectionIndex ]) + +let printSymbolInfoNone (fi: ELFFileInfo) s cfg = + out.PrintRow (true, cfg, + [ targetString s + Addr.toString fi.WordSize s.Address + normalizeEmpty s.Name + (toLibString >> normalizeEmpty) s.LibraryName + "(n/a)"; "(n/a)"; "(n/a)"; "(n/a)"; "(n/a)" ]) + +let printSymbolInfo isVerbose (fi: ELFFileInfo) (symbols: seq) = + let addrColumn = columnWidthOfAddr fi |> LeftAligned + if isVerbose then + let cfg = [ LeftAligned 4; addrColumn; LeftAligned 55; LeftAligned 15 + LeftAligned 8; LeftAligned 12; LeftAligned 12; LeftAligned 12 + LeftAligned 8 ] + out.PrintRow (true, cfg, [ "Kind"; "Address"; "Name"; "LibraryName" + "Size"; "Type"; "Bind"; "Visibility" + "SectionIndex" ]) + out.PrintLine " ---" + symbols + |> Seq.sortBy (fun s -> s.Name) + |> Seq.sortBy (fun s -> s.Address) + |> Seq.sortBy (fun s -> s.Target) + |> Seq.iter (fun s -> + match fi.ELF.SymInfo.AddrToSymbTable.TryFind s.Address with + | Some elfSymbol -> printSymbolInfoVerbose fi s elfSymbol cfg + | None -> + match fi.ELF.RelocInfo.RelocByName.TryFind s.Name with + | Some reloc -> + match reloc.RelSymbol with + | Some elfSymbol -> printSymbolInfoVerbose fi s elfSymbol cfg + | None -> printSymbolInfoNone fi s cfg + | None -> printSymbolInfoNone fi s cfg) + else + let cfg = [ LeftAligned 15; addrColumn; LeftAligned 75; LeftAligned 15 ] + out.PrintRow (true, cfg, [ "Kind"; "Address"; "Name"; "LibraryName" ]) + out.PrintLine " ---" + symbols + |> Seq.sortBy (fun s -> s.Name) + |> Seq.sortBy (fun s -> s.Address) + |> Seq.sortBy (fun s -> s.Target) + |> Seq.iter (fun s -> + out.PrintRow (true, cfg, + [ targetString s + Addr.toString fi.WordSize s.Address + normalizeEmpty s.Name + (toLibString >> normalizeEmpty) s.LibraryName ])) + +let dumpSymbols (opts: FileViewerOpts) (fi: ELFFileInfo) = + fi.GetSymbols () + |> printSymbolInfo opts.Verbose fi + +let dumpRelocs (opts: FileViewerOpts) (fi: ELFFileInfo) = + fi.GetRelocationSymbols () + |> printSymbolInfo opts.Verbose fi + +let dumpFunctions (opts: FileViewerOpts) (fi: ELFFileInfo) = + fi.GetFunctionSymbols () + |> printSymbolInfo opts.Verbose fi + +let dumpSegments (opts: FileViewerOpts) (fi: ELFFileInfo) = + let addrColumn = columnWidthOfAddr fi |> LeftAligned + if opts.Verbose then + let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 10 + LeftAligned 12; LeftAligned 8; addrColumn; addrColumn + LeftAligned 8; LeftAligned 8; LeftAligned 8 ] + out.PrintRow (true, cfg, [ "Num"; "Start"; "End"; "Permission" + "Type"; "Offset"; "VirtAddr"; "PhysAddr" + "FileSize"; "MemSize"; "Alignment" ]) + out.PrintLine " ---" + fi.ELF.ProgHeaders + |> List.iteri (fun idx ph -> + out.PrintRow (true, cfg, + [ String.wrapSqrdBracket (idx.ToString ()) + (Addr.toString fi.WordSize ph.PHAddr) + (Addr.toString fi.WordSize (ph.PHAddr + ph.PHMemSize - uint64 1)) + (FileInfo.PermissionToString ph.PHFlags) + ph.PHType.ToString () + String.u64ToHex ph.PHOffset + String.u64ToHex ph.PHAddr + String.u64ToHex ph.PHPhyAddr + String.u64ToHex ph.PHFileSize + String.u64ToHex ph.PHMemSize + String.u64ToHex ph.PHAlignment ])) + else + let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 10 ] + out.PrintRow (true, cfg, [ "Num"; "Start"; "End"; "Permission" ]) + out.PrintLine " ---" + fi.GetSegments () + |> Seq.iteri (fun idx s -> + out.PrintRow (true, cfg, + [ String.wrapSqrdBracket (idx.ToString ()) + (Addr.toString fi.WordSize s.Address) + (Addr.toString fi.WordSize (s.Address + s.Size - uint64 1)) + (FileInfo.PermissionToString s.Permission) ])) + +let dumpLinkageTable (opts: FileViewerOpts) (fi: ELFFileInfo) = + let addrColumn = columnWidthOfAddr fi |> LeftAligned + if opts.Verbose then + let cfg = [ addrColumn; addrColumn; LeftAligned 40; LeftAligned 15 + LeftAligned 8; LeftAligned 6; LeftAligned 4 ] + out.PrintRow (true, cfg, + [ "PLT Addr"; "GOT Addr"; "FunctionName"; "LibraryName" + "Addend"; "SecIdx"; "Type" ]) + out.PrintLine " ---" + fi.GetLinkageTableEntries () + |> Seq.iter (fun e -> + match fi.ELF.RelocInfo.RelocByAddr.TryFind e.TableAddress with + | Some reloc -> + out.PrintRow (true, cfg, + [ (Addr.toString fi.WordSize e.TrampolineAddress) + (Addr.toString fi.WordSize e.TableAddress) + normalizeEmpty e.FuncName + (toLibString >> normalizeEmpty) e.LibraryName + reloc.RelAddend.ToString () + reloc.RelSecNumber.ToString () + reloc.RelType.ToString () ]) + | None -> + out.PrintRow (true, cfg, + [ (Addr.toString fi.WordSize e.TrampolineAddress) + (Addr.toString fi.WordSize e.TableAddress) + normalizeEmpty e.FuncName + (toLibString >> normalizeEmpty) e.LibraryName + "(n/a)"; "(n/a)"; "(n/a)" ])) + else + let cfg = [ addrColumn; addrColumn; LeftAligned 20; LeftAligned 15 ] + out.PrintRow (true, cfg, + [ "PLT"; "GOT"; "FunctionName"; "LibraryName" ]) + out.PrintLine " ---" + fi.GetLinkageTableEntries () + |> Seq.iter (fun e -> + out.PrintRow (true, cfg, + [ (Addr.toString fi.WordSize e.TrampolineAddress) + (Addr.toString fi.WordSize e.TableAddress) + normalizeEmpty e.FuncName + (toLibString >> normalizeEmpty) e.LibraryName ])) + +let cfaToString (hdl: BinHandle) cfa = + ELF.CanonicalFrameAddress.toString hdl.RegisterBay cfa + +let ruleToString (hdl: BinHandle) (rule: ELF.Rule) = + rule + |> Map.fold (fun s k v -> + match k with + | ELF.ReturnAddress -> s + "(ra:" + ELF.Action.toString v + ")" + | ELF.NormalReg rid -> + let reg = hdl.RegisterBay.RegIDToString rid + s + "(" + reg + ":" + ELF.Action.toString v + ")") "" + +let dumpEHFrame hdl (fi: ELFFileInfo) = + let addrColumn = columnWidthOfAddr fi |> LeftAligned + let cfg = [ addrColumn; LeftAligned 10; LeftAligned 50 ] + fi.ELF.ExceptionFrame + |> List.iter (fun cfi -> + out.PrintLine ("- CIE: \"{0}\" cf={1} df={2}", + cfi.CIERecord.AugmentationString, + cfi.CIERecord.CodeAlignmentFactor.ToString ("+0;-#"), + cfi.CIERecord.DataAlignmentFactor.ToString ("+0;-#")) + out.PrintLine () + cfi.FDERecord + |> Array.iter (fun fde -> + out.PrintLine (" FDE pc={0}..{1}", + String.u64ToHex fde.PCBegin, + String.u64ToHex fde.PCEnd) + if fde.UnwindingInfo.IsEmpty then () + else + out.PrintLine " ---" + out.PrintRow (true, cfg, [ "Location"; "CFA"; "Rules" ]) + fde.UnwindingInfo + |> List.iter (fun i -> + out.PrintRow (true, cfg, + [ String.u64ToHex i.Location + cfaToString hdl i.CanonicalFrameAddress + ruleToString hdl i.Rule ])) + out.PrintLine () + ) + ) + +let dumpLSDA _hdl (fi: ELFFileInfo) = + let addrColumn = columnWidthOfAddr fi |> LeftAligned + let cfg = [ addrColumn; LeftAligned 15; LeftAligned 15; addrColumn ] + out.PrintRow (true, cfg, [ "Address"; "LP App"; "LP Val"; "TT End" ]) + fi.ELF.LSDAs + |> List.iter (fun lsda -> + let ttbase = lsda.Header.TTBase |> Option.defaultValue 0UL + out.PrintRow (true, cfg, + [ Addr.toString fi.WordSize lsda.LSDAAddr + lsda.Header.LPAppEncoding.ToString () + lsda.Header.LPValueEncoding.ToString () + ttbase |> Addr.toString fi.WordSize ]) + ) + +let dumpNotes _hdl (fi: ELFFileInfo) = + Utils.futureFeature () diff --git a/src/FrontEnd/ARM32/ARM32Parser.fsi b/src/RearEnd/FileViewer/Helper.fs similarity index 67% rename from src/FrontEnd/ARM32/ARM32Parser.fsi rename to src/RearEnd/FileViewer/Helper.fs index eb98c83d..0ad2febc 100644 --- a/src/FrontEnd/ARM32/ARM32Parser.fsi +++ b/src/RearEnd/FileViewer/Helper.fs @@ -22,20 +22,28 @@ SOFTWARE. *) -/// ARMv7 instruction parser. -module B2R2.FrontEnd.ARM32.Parser +module B2R2.RearEnd.FileViewer.Helper open B2R2 -open B2R2.FrontEnd - -/// Read in bytes and return a parsed instruction for ARMv7. This function -/// returns ARM32Instruction, which is a specialized type for 32-bit ARM. If you -/// want to handle instructions in a platform-agnostic manner, you'd better use -/// the ARM32Parser class. -val parse: BinReader - -> ParsingContext - -> Architecture - -> Addr - -> int - -> ARM32Instruction +open B2R2.FrontEnd.BinFile +/// The console printer. +let internal out = ConsolePrinter () :> Printer + +let normalizeEmpty s = + if System.String.IsNullOrEmpty s then "(n/a)" else s + +let toNBytes (v: uint64) = + v.ToString () + " bytes" + +let columnWidthOfAddr (fi: FileInfo) = + WordSize.toByteWidth fi.WordSize * 2 + +let targetString s = + match s.Target with + | TargetKind.StaticSymbol -> "(s)" + | TargetKind.DynamicSymbol -> "(d)" + | _ -> Utils.impossible () + +let toLibString s = + if System.String.IsNullOrEmpty s then s else "@" + s diff --git a/src/RearEnd/FileViewer/MachViewer.fs b/src/RearEnd/FileViewer/MachViewer.fs new file mode 100644 index 00000000..155d371d --- /dev/null +++ b/src/RearEnd/FileViewer/MachViewer.fs @@ -0,0 +1,386 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.RearEnd.FileViewer.MachViewer + +open System +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.RearEnd.FileViewer.Helper + +let badAccess _ _ = + raise InvalidFileTypeException + +let translateFlags flags = + let enumFlags = + Enum.GetValues (typeof) :?> Mach.MachFlag [] + |> Array.toList + let rec loop acc flags = function + | [] -> List.rev acc + | enumFlag :: tail -> + if uint64 enumFlag &&& flags = uint64 enumFlag then + loop ((" - " + enumFlag.ToString ()) :: acc) flags tail + else + loop acc flags tail + loop [] flags enumFlags + +let dumpFileHeader _ (fi: MachFileInfo) = + let hdr = fi.Mach.MachHdr + out.PrintTwoCols + "Magic:" + (String.u64ToHex (uint64 hdr.Magic) + + String.wrapParen (hdr.Magic.ToString ())) + out.PrintTwoCols + "Cpu type:" + (hdr.CPUType.ToString ()) + out.PrintTwoCols + "Cpu subtype:" + (String.u32ToHex (uint32 hdr.CPUSubType)) + out.PrintTwoCols + "File type:" + (hdr.FileType.ToString ()) + out.PrintTwoCols + "Number of commands:" + (hdr.NumCmds.ToString ()) + out.PrintTwoCols + "Size of commands:" + (hdr.SizeOfCmds.ToString ()) + out.PrintTwoCols + "Flags:" + (String.u64ToHex (uint64 hdr.Flags)) + translateFlags (uint64 hdr.Flags) + |> List.iter (fun str -> out.PrintTwoCols "" str) + +let translateAttribs attribs = + let enumAttribs = + System.Enum.GetValues (typeof) + :?> Mach.SectionAttribute [] + |> Array.toList + let rec loop acc attribs = function + | [] -> List.rev acc + | enumAttrib :: tail -> + if uint64 enumAttrib &&& attribs = uint64 enumAttrib then + loop ((" - " + enumAttrib.ToString ()) :: acc) attribs tail + else + loop acc attribs tail + loop [] attribs enumAttribs + +let dumpSectionHeaders (opts: FileViewerOpts) (fi: MachFileInfo) = + let addrColumn = columnWidthOfAddr fi |> LeftAligned + if opts.Verbose then + let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 16 + LeftAligned 8; LeftAligned 8; LeftAligned 8; LeftAligned 8 + LeftAligned 10; LeftAligned 6; LeftAligned 22 + LeftAligned 4; LeftAligned 4; LeftAligned 8 ] + out.PrintRow (true, cfg, [ "Num"; "Start"; "End"; "Name" + "SegName"; "Size"; "Offset"; "Align" + "SecRelOff"; "#Reloc"; "Type" + "Res1"; "Res2"; "Attrib" ]) + out.PrintLine " ---" + fi.Mach.Sections.SecByNum + |> Array.iteri (fun idx s -> + out.PrintRow (true, cfg, + [ String.wrapSqrdBracket (idx.ToString ()) + (Addr.toString fi.WordSize s.SecAddr) + (Addr.toString fi.WordSize (s.SecAddr + s.SecSize - uint64 1)) + normalizeEmpty s.SecName + normalizeEmpty s.SegName + String.u64ToHex s.SecSize + String.u64ToHex (uint64 s.SecOffset) + String.u64ToHex (uint64 s.SecAlignment) + s.SecRelOff.ToString () + s.SecNumOfReloc.ToString () + s.SecType.ToString () + s.SecReserved1.ToString () + s.SecReserved2.ToString () + String.u32ToHex (uint32 s.SecAttrib) ]) + translateAttribs (uint64 s.SecAttrib) + |> List.iter (fun str -> + out.PrintRow (true, cfg, [ ""; ""; ""; ""; ""; ""; ""; ""; "" + ""; ""; ""; ""; str ])) + ) + else + let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 24 ] + out.PrintRow (true, cfg, [ "Num"; "Start"; "End"; "Name" ]) + out.PrintLine " ---" + fi.GetSections () + |> Seq.iteri (fun idx s -> + out.PrintRow (true, cfg, + [ String.wrapSqrdBracket (idx.ToString ()) + (Addr.toString fi.WordSize s.Address) + (Addr.toString fi.WordSize (s.Address + s.Size - uint64 1)) + normalizeEmpty s.Name ])) + +let dumpSectionDetails (secname: string) (fi: MachFileInfo) = + match fi.Mach.Sections.SecByName.TryFind secname with + | Some section -> + out.PrintTwoCols + "SecName:" + section.SecName + out.PrintTwoCols + "SegName:" + section.SegName + out.PrintTwoCols + "SecAddr:" + (String.u64ToHex section.SecAddr) + out.PrintTwoCols + "SecSize:" + (String.u64ToHex section.SecSize) + out.PrintTwoCols + "SecOffset:" + (String.u64ToHex (uint64 section.SecOffset)) + out.PrintTwoCols + "SecAlignment:" + (String.u64ToHex (uint64 section.SecAlignment)) + out.PrintTwoCols + "SecRelOff:" + (String.u64ToHex (uint64 section.SecRelOff)) + out.PrintTwoCols + "SecNumOfReloc:" + (section.SecNumOfReloc.ToString ()) + out.PrintTwoCols + "SecType:" + (section.SecType.ToString ()) + out.PrintTwoCols + "SecAttrib:" + (String.u32ToHex (uint32 section.SecAttrib)) + translateAttribs (uint64 section.SecAttrib) + |> List.iter (fun str -> out.PrintTwoCols "" str ) + out.PrintTwoCols + "SecReserved1:" + (section.SecReserved1.ToString ()) + out.PrintTwoCols + "SecReserved2:" + (section.SecReserved2.ToString ()) + | None -> out.PrintLine "Not found." + +let toVersionString (v: uint32) = + let major = (v &&& uint32 0xFFFF0000) >>> 16 + let minor1 = (v &&& uint32 0x0000FF00) >>> 8 + let minor2 = v &&& uint32 0x000000FF + major.ToString () + "." + minor1.ToString () + "." + minor2.ToString () + +let printSymbolInfoVerbose fi s (machSymbol: Mach.MachSymbol) cfg = + let externLibVerinfo = + match machSymbol.VerInfo with + | Some info -> + info.DyLibName + + String.wrapParen + "compatibility version " + toVersionString info.DyLibCmpVer + ", " + + "current version" + toVersionString info.DyLibCurVer + | None -> "(n/a)" + out.PrintRow (true, cfg, + [ targetString s + Addr.toString (fi: MachFileInfo).WordSize s.Address + normalizeEmpty s.Name + (toLibString >> normalizeEmpty) s.LibraryName + machSymbol.SymType.ToString () + machSymbol.SymDesc.ToString () + machSymbol.IsExternal.ToString () + externLibVerinfo + String.wrapSqrdBracket (machSymbol.SecNum.ToString ()); ""; ""; "" ]) + +let printSymbolInfoNone fi s cfg = + out.PrintRow (true, cfg, + [ targetString s + Addr.toString (fi: MachFileInfo).WordSize s.Address + normalizeEmpty s.Name + (toLibString >> normalizeEmpty) s.LibraryName + "(n/a)"; "(n/a)"; "(n/a)"; "(n/a)"; "(n/a)" ]) + +let printSymbolInfo isVerbose (fi: MachFileInfo) (symbols: seq) = + let addrColumn = columnWidthOfAddr fi |> LeftAligned + if isVerbose then + let cfg = [ LeftAligned 10; addrColumn; LeftAligned 40; LeftAligned 35 + LeftAligned 8; LeftAligned 8; LeftAligned 8; LeftAligned 8 + LeftAligned 8 ] + out.PrintRow (true, cfg, [ "Kind"; "Address"; "Name"; "LibraryName" + "Type"; "Description"; "External"; "Version" + "SectionIndex" ]) + out.PrintLine " ---" + symbols + |> Seq.sortBy (fun s -> s.Name) + |> Seq.sortBy (fun s -> s.Address) + |> Seq.sortBy (fun s -> s.Target) + |> Seq.iter (fun s -> + match fi.Mach.SymInfo.SymbolMap.TryFind s.Address with + | Some machSymbol -> printSymbolInfoVerbose fi s machSymbol cfg + | None -> printSymbolInfoNone fi s cfg) + else + let cfg = [ LeftAligned 10; addrColumn; LeftAligned 55; LeftAligned 15 ] + out.PrintRow (true, cfg, [ "Kind"; "Address"; "Name"; "LibraryName" ]) + out.PrintLine " ---" + symbols + |> Seq.sortBy (fun s -> s.Name) + |> Seq.sortBy (fun s -> s.Address) + |> Seq.sortBy (fun s -> s.Target) + |> Seq.iter (fun s -> + out.PrintRow (true, cfg, + [ targetString s + Addr.toString fi.WordSize s.Address + normalizeEmpty s.Name + (toLibString >> normalizeEmpty) s.LibraryName ])) + +let dumpSymbols (opts: FileViewerOpts) (fi: MachFileInfo) = + fi.GetSymbols () + |> printSymbolInfo opts.Verbose fi + +let dumpRelocs (opts: FileViewerOpts) (fi: MachFileInfo) = + fi.GetRelocationSymbols () + |> printSymbolInfo opts.Verbose fi + +let dumpFunctions (opts: FileViewerOpts) (fi: MachFileInfo) = + fi.GetFunctionSymbols () + |> printSymbolInfo opts.Verbose fi + +let dumpArchiveHeader (opts: FileViewerOpts) (fi: MachFileInfo) = + Utils.futureFeature () + +let dumpUniversalHeader (opts: FileViewerOpts) (fi: MachFileInfo) = + Utils.futureFeature () + +let printSegCmd (segCmd: Mach.SegCmd) idx = + out.PrintSubsectionTitle ("Load command " + idx.ToString ()) + out.PrintTwoCols "Cmd:" (segCmd.Cmd.ToString ()) + out.PrintTwoCols "CmdSize:" (segCmd.CmdSize.ToString ()) + out.PrintTwoCols "SegCmdName:" segCmd.SegCmdName + out.PrintTwoCols "VMAddr:" (String.u64ToHex segCmd.VMAddr) + out.PrintTwoCols "VMSize:" (String.u64ToHex segCmd.VMSize) + out.PrintTwoCols "FileOff:" (segCmd.FileOff.ToString ()) + out.PrintTwoCols "FileSize:" (segCmd.FileSize.ToString ()) + out.PrintTwoCols "MaxProt:" (String.u64ToHex (uint64 segCmd.MaxProt)) + out.PrintTwoCols "InitProt:" (String.u64ToHex (uint64 segCmd.InitProt)) + out.PrintTwoCols "NumSecs:" (segCmd.NumSecs.ToString ()) + out.PrintTwoCols "SegFlag:" (String.u64ToHex (uint64 segCmd.SegFlag)) + +let printSymTabCmd (symTabCmd: Mach.SymTabCmd) idx = + out.PrintSubsectionTitle ("Load command " + idx.ToString ()) + out.PrintTwoCols "Cmd:" (symTabCmd.Cmd.ToString ()) + out.PrintTwoCols "CmdSize:" (symTabCmd.CmdSize.ToString ()) + out.PrintTwoCols "SymOff:" (String.u64ToHex (uint64 symTabCmd.SymOff)) + out.PrintTwoCols "NumOfSym:" (symTabCmd.NumOfSym.ToString ()) + out.PrintTwoCols "StrOff:" (String.u64ToHex (uint64 symTabCmd.StrOff)) + out.PrintTwoCols "StrSize:" (toNBytes (uint64 symTabCmd.StrSize)) + +let printDySymTabCmd (dySymTabCmd: Mach.DySymTabCmd) idx = + out.PrintSubsectionTitle ("Load command " + idx.ToString ()) + out.PrintTwoCols "Cmd:" (dySymTabCmd.Cmd.ToString ()) + out.PrintTwoCols "CmdSize:" (dySymTabCmd.CmdSize.ToString ()) + out.PrintTwoCols "IdxLocalSym:" (dySymTabCmd.IdxLocalSym.ToString ()) + out.PrintTwoCols "NumLocalSym:" (dySymTabCmd.NumLocalSym.ToString ()) + out.PrintTwoCols "IdxExtSym:" (dySymTabCmd.IdxExtSym.ToString ()) + out.PrintTwoCols "NumExtSym:" (dySymTabCmd.NumExtSym.ToString ()) + out.PrintTwoCols "IdxUndefSym:" (dySymTabCmd.IdxUndefSym.ToString ()) + out.PrintTwoCols "NumUndefSym:" (dySymTabCmd.NumUndefSym.ToString ()) + out.PrintTwoCols "TOCOffset:" (dySymTabCmd.TOCOffset.ToString ()) + out.PrintTwoCols "NumTOCContents:" (dySymTabCmd.NumTOCContents.ToString ()) + out.PrintTwoCols "ModTabOff:" (dySymTabCmd.ModTabOff.ToString ()) + out.PrintTwoCols "NumModTab:" (dySymTabCmd.NumModTab.ToString ()) + out.PrintTwoCols "ExtRefSymOff:" (dySymTabCmd.ExtRefSymOff.ToString ()) + out.PrintTwoCols "NumExtRefSym:" (dySymTabCmd.NumExtRefSym.ToString ()) + out.PrintTwoCols "IndirectSymOff:" (dySymTabCmd.IndirectSymOff.ToString ()) + out.PrintTwoCols "NumIndirectSym:" (dySymTabCmd.NumIndirectSym.ToString ()) + out.PrintTwoCols "ExtRelOff:" (dySymTabCmd.ExtRelOff.ToString ()) + out.PrintTwoCols "NumExtRel:" (dySymTabCmd.NumExtRel.ToString ()) + out.PrintTwoCols "LocalRelOff:" (dySymTabCmd.LocalRelOff.ToString ()) + out.PrintTwoCols "NumLocalRel:" (dySymTabCmd.NumLocalRel.ToString ()) + +let toTimeStampString (v: uint32) = + ((DateTime.UnixEpoch.AddSeconds (float v)).ToLocalTime ()).ToString () + + TimeZoneInfo.Local.ToString () + +let printDyLibCmd (dyLibCmd: Mach.DyLibCmd) idx = + out.PrintSubsectionTitle ("Load command " + idx.ToString ()) + out.PrintTwoCols "Cmd:" (dyLibCmd.Cmd.ToString ()) + out.PrintTwoCols "CmdSize:" (dyLibCmd.CmdSize.ToString ()) + out.PrintTwoCols "DyLibName:" dyLibCmd.DyLibName + out.PrintTwoCols "DyLibTimeStamp:" (toTimeStampString dyLibCmd.DyLibTimeStamp) + out.PrintTwoCols "DyLibCurVer:" (toVersionString dyLibCmd.DyLibCurVer) + out.PrintTwoCols "DyLibCmpVer:" (toVersionString dyLibCmd.DyLibCmpVer) + +let printDyLdInfoCmd (dyLdInfoCmd: Mach.DyLdInfoCmd) idx = + out.PrintSubsectionTitle ("Load command " + idx.ToString ()) + out.PrintTwoCols "Cmd:" (dyLdInfoCmd.Cmd.ToString ()) + out.PrintTwoCols "CmdSize:" (dyLdInfoCmd.CmdSize.ToString ()) + out.PrintTwoCols "RebaseOff:" (dyLdInfoCmd.RebaseOff.ToString ()) + out.PrintTwoCols "RebaseSize:" (dyLdInfoCmd.RebaseSize.ToString ()) + out.PrintTwoCols "BindOff:" (dyLdInfoCmd.BindOff.ToString ()) + out.PrintTwoCols "BindSize:" (dyLdInfoCmd.BindSize.ToString ()) + out.PrintTwoCols "WeakBindOff:" (dyLdInfoCmd.WeakBindOff.ToString ()) + out.PrintTwoCols "WeakBindSize:" (dyLdInfoCmd.WeakBindSize.ToString ()) + out.PrintTwoCols "LazyBindOff:" (dyLdInfoCmd.LazyBindOff.ToString ()) + out.PrintTwoCols "LazyBindSize:" (dyLdInfoCmd.LazyBindSize.ToString ()) + out.PrintTwoCols "ExportOff:" (dyLdInfoCmd.ExportOff.ToString ()) + out.PrintTwoCols "ExportSize:" (dyLdInfoCmd.ExportSize.ToString ()) + +let printFuncStartsCmd (funcStartsCmd: Mach.FuncStartsCmd) idx = + out.PrintSubsectionTitle ("Load command " + idx.ToString ()) + out.PrintTwoCols "DataOffset:" (funcStartsCmd.DataOffset.ToString ()) + out.PrintTwoCols "DataSize:" (funcStartsCmd.DataSize.ToString ()) + +let printMainCmd (mainCmd: Mach.MainCmd) idx = + out.PrintSubsectionTitle ("Load command " + idx.ToString ()) + out.PrintTwoCols "Cmd:" (mainCmd.Cmd.ToString ()) + out.PrintTwoCols "CmdSize:" (mainCmd.CmdSize.ToString ()) + out.PrintTwoCols "EntryOff:" (mainCmd.EntryOff.ToString ()) + out.PrintTwoCols "StackSize:" (mainCmd.StackSize.ToString ()) + +let printUnhandledCmd (unhandledCmd: Mach.UnhandledCommand) idx = + out.PrintSubsectionTitle ("Load command " + idx.ToString ()) + out.PrintTwoCols "Cmd:" (unhandledCmd.Cmd.ToString ()) + out.PrintTwoCols "CmdSize:" (unhandledCmd.CmdSize.ToString ()) + +let dumpLoadCommands _ (fi: MachFileInfo) = + fi.Mach.Cmds + |> List.iteri (fun idx cmd -> + match cmd with + | Mach.Segment segCmd -> + printSegCmd segCmd idx + fi.Mach.Sections.SecByNum + |> Array.iter (fun s -> + if s.SegName = segCmd.SegCmdName then + out.PrintLine () + out.PrintSubsubsectionTitle (String.wrapSqrdBracket "Section") + dumpSectionDetails s.SecName fi) + | Mach.SymTab symTabCmd -> printSymTabCmd symTabCmd idx + | Mach.DySymTab dySymTabCmd -> printDySymTabCmd dySymTabCmd idx + | Mach.DyLib dyLibCmd -> printDyLibCmd dyLibCmd idx + | Mach.DyLdInfo dyLdInfoCmd ->printDyLdInfoCmd dyLdInfoCmd idx + | Mach.FuncStarts funcStartsCmd -> printFuncStartsCmd funcStartsCmd idx + | Mach.Main mainCmd -> printMainCmd mainCmd idx + | Mach.Unhandled unhandledCmd -> printUnhandledCmd unhandledCmd idx + out.PrintLine ()) + +let dumpSharedLibs _ (fi: MachFileInfo) = + let cfg = [ LeftAligned 35; LeftAligned 15; LeftAligned 15 ] + out.PrintRow (true, cfg, [ "LibraryName"; "CurVersion"; "CompatVersion" ]) + fi.Mach.Cmds + |> List.iter (fun cmd -> + match cmd with + | Mach.DyLib dyLibCmd -> + out.PrintRow (true, cfg, + [ dyLibCmd.DyLibName + toVersionString dyLibCmd.DyLibCurVer + toVersionString dyLibCmd.DyLibCmpVer ]) + | _ -> ()) diff --git a/src/RearEnd/FileViewer/PEViewer.fs b/src/RearEnd/FileViewer/PEViewer.fs new file mode 100644 index 00000000..4cec162f --- /dev/null +++ b/src/RearEnd/FileViewer/PEViewer.fs @@ -0,0 +1,509 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.RearEnd.FileViewer.PEViewer + +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.RearEnd.FileViewer.Helper +open System.Reflection.PortableExecutable + +let badAccess _ _ = + raise InvalidFileTypeException + +let translateChracteristics chars = + let enumChars = + System.Enum.GetValues (typeof) + :?> Characteristics [] + |> Array.toList + let rec loop acc chars = function + | [] -> List.rev acc + | enumChar :: tail -> + if uint64 enumChar &&& chars = uint64 enumChar then + loop ((" - " + enumChar.ToString ()) :: acc) chars tail + else + loop acc chars tail + loop [] chars enumChars + +let dumpFileHeader _ (fi: PEFileInfo) = + let hdr = fi.PE.PEHeaders.CoffHeader + out.PrintTwoCols + "Machine:" + (String.u64ToHex (uint64 hdr.Machine) + + String.wrapParen (hdr.Machine.ToString ())) + out.PrintTwoCols + "Number of sections:" + (hdr.NumberOfSections.ToString ()) + out.PrintTwoCols + "Time date stamp:" + (hdr.TimeDateStamp.ToString ()) + out.PrintTwoCols + "Pointer to symbol table:" + (String.u64ToHex (uint64 hdr.PointerToSymbolTable)) + out.PrintTwoCols + "Size of optional header:" + (String.u64ToHex (uint64 hdr.SizeOfOptionalHeader)) + out.PrintTwoCols + "Characteristics:" + (String.u64ToHex (uint64 hdr.Characteristics)) + translateChracteristics (uint64 hdr.Characteristics) + |> List.iter (fun str -> out.PrintTwoCols "" str) + +let translateSectionChracteristics chars = + let enumChars = + System.Enum.GetValues (typeof) + :?> SectionCharacteristics [] + |> Array.toList + if chars = uint64 0 then + [ " - TypeReg" ] + else + let rec loop acc chars = function + | [] -> List.rev acc + | enumChar :: t -> + if uint64 enumChar &&& chars = uint64 enumChar + && not (uint64 enumChar = uint64 0) then + loop ((" - " + enumChar.ToString ()) :: acc) chars t + else + loop acc chars t + loop [] chars enumChars + +let dumpSectionHeaders (opts: FileViewerOpts) (fi: PEFileInfo) = + let addrColumn = columnWidthOfAddr fi |> LeftAligned + if opts.Verbose then + let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 24 + LeftAligned 8; LeftAligned 8; LeftAligned 8; LeftAligned 8 + LeftAligned 8; LeftAligned 8; LeftAligned 8; LeftAligned 8 + LeftAligned 8 ] + out.PrintRow (true, cfg, + [ "Num"; "Start"; "End"; "Name" + "VirtSize"; "VirtAddr"; "RawSize"; "RawPtr" + "RelocPtr"; "LineNPtr"; "RelocNum"; "LineNNum" + "Characteristics" ]) + out.PrintLine " ---" + fi.PE.SectionHeaders + |> Array.iteri (fun idx s -> + let startAddr = fi.PE.BaseAddr + uint64 s.VirtualAddress + let size = + uint64 (if s.VirtualSize = 0 then s.SizeOfRawData else s.VirtualSize) + let characteristics = uint64 s.SectionCharacteristics + out.PrintRow (true, cfg, + [ String.wrapSqrdBracket (idx.ToString ()) + (Addr.toString fi.WordSize startAddr) + (Addr.toString fi.WordSize (startAddr + size - uint64 1)) + normalizeEmpty s.Name + String.u64ToHex (uint64 s.VirtualSize) + String.u64ToHex (uint64 s.VirtualAddress) + String.u64ToHex (uint64 s.SizeOfRawData) + String.u64ToHex (uint64 s.PointerToRawData) + String.u64ToHex (uint64 s.PointerToRelocations) + String.u64ToHex (uint64 s.PointerToLineNumbers) + s.NumberOfRelocations.ToString () + s.NumberOfLineNumbers.ToString () + String.u64ToHex characteristics ]) + translateSectionChracteristics characteristics + |> List.iter (fun str -> + out.PrintRow (true, cfg, [ ""; ""; ""; ""; ""; ""; "" + ""; ""; ""; ""; ""; str ]))) + else + let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 24 ] + out.PrintRow (true, cfg, [ "Num"; "Start"; "End"; "Name" ]) + out.PrintLine " ---" + fi.GetSections () + |> Seq.iteri (fun idx s -> + out.PrintRow (true, cfg, + [ String.wrapSqrdBracket (idx.ToString ()) + (Addr.toString fi.WordSize s.Address) + (Addr.toString fi.WordSize (s.Address + s.Size - uint64 1)) + normalizeEmpty s.Name ])) + +let dumpSectionDetails (secname: string) (fi: PEFileInfo) = + let idx = + Array.tryFindIndex (fun (s: SectionHeader) -> + s.Name = secname) fi.PE.SectionHeaders + match idx with + | Some idx -> + let section = fi.PE.SectionHeaders.[idx] + let characteristics = uint64 section.SectionCharacteristics + out.PrintTwoCols + "Section number:" + (String.wrapSqrdBracket (idx.ToString ())) + out.PrintTwoCols + "Section name:" + section.Name + out.PrintTwoCols + "Virtual size:" + (String.u64ToHex (uint64 section.VirtualSize)) + out.PrintTwoCols + "Virtual address:" + (String.u64ToHex (uint64 section.VirtualAddress)) + out.PrintTwoCols + "Size of raw data:" + (String.u64ToHex (uint64 section.SizeOfRawData)) + out.PrintTwoCols + "Pointer to raw data:" + (String.u64ToHex (uint64 section.PointerToRawData)) + out.PrintTwoCols + "Pointer to relocations:" + (String.u64ToHex (uint64 section.PointerToRelocations)) + out.PrintTwoCols + "Pointer to line numbers:" + (String.u64ToHex (uint64 section.PointerToLineNumbers)) + out.PrintTwoCols + "Number of relocations:" + (section.NumberOfRelocations.ToString ()) + out.PrintTwoCols + "Number of line numbers:" + (section.NumberOfLineNumbers.ToString ()) + out.PrintTwoCols + "Characteristics:" + (String.u64ToHex characteristics) + translateSectionChracteristics characteristics + |> List.iter (fun str -> out.PrintTwoCols "" str) + | None -> out.PrintTwoCols "" "Not found." + +let printSymbolInfo (fi: PEFileInfo) (symbols: seq) = + let addrColumn = columnWidthOfAddr fi |> LeftAligned + let cfg = [ LeftAligned 5; addrColumn; LeftAligned 50; LeftAligned 15 ] + out.PrintRow (true, cfg, [ "Kind"; "Address"; "Name"; "LibraryName" ]) + out.PrintLine " ---" + symbols + |> Seq.sortBy (fun s -> s.Name) + |> Seq.sortBy (fun s -> s.Address) + |> Seq.sortBy (fun s -> s.Target) + |> Seq.iter (fun s -> + out.PrintRow (true, cfg, + [ targetString s + Addr.toString fi.WordSize s.Address + normalizeEmpty s.Name + (toLibString >> normalizeEmpty) s.LibraryName ])) + +let dumpSymbols _ (fi: PEFileInfo) = + fi.GetSymbols () + |> printSymbolInfo fi + +let dumpRelocs _ (fi: PEFileInfo) = + fi.GetRelocationSymbols () + |> printSymbolInfo fi + +let dumpFunctions _ (fi: PEFileInfo) = + fi.GetFunctionSymbols () + |> printSymbolInfo fi + +let inline addrFromRVA baseAddr rva = + uint64 rva + baseAddr + +let dumpImports _ (fi: PEFileInfo) = + let cfg = [ LeftAligned 50; LeftAligned 50; LeftAligned 20 ] + out.PrintRow (true, cfg, + [ "FunctionName"; "LibraryName"; "TableAddress" ]) + out.PrintLine " ---" + fi.PE.ImportMap + |> Map.iter (fun addr info -> + match info with + | PE.ImportInfo.ImportByOrdinal (ordinal, dllname) -> + out.PrintRow (true, cfg, + [ "#" + ordinal.ToString () + dllname + String.u64ToHex (addrFromRVA fi.PE.BaseAddr addr) ]) + | PE.ImportInfo.ImportByName (_, fname, dllname) -> + out.PrintRow (true, cfg, + [ fname + dllname + String.u64ToHex (addrFromRVA fi.PE.BaseAddr addr) ])) + +let dumpExports _ (fi: PEFileInfo) = + let cfg = [ LeftAligned 45; LeftAligned 20 ] + out.PrintRow (true, cfg, [ "FunctionName"; "TableAddress" ]) + out.PrintLine " ---" + fi.PE.ExportMap + |> Map.iter (fun addr names -> + let rva = int (addr - fi.PE.BaseAddr) + match fi.PE.FindSectionIdxFromRVA rva with + | -1 -> () + | idx -> + names + |> List.iter (fun name -> + out.PrintRow (true, cfg, [ name; String.u64ToHex addr ]))) + out.PrintLine "" + out.PrintRow (true, cfg, [ "FunctionName"; "ForwardName" ]) + out.PrintLine " ---" + fi.PE.ForwardMap + |> Map.iter (fun name (bin, func) -> + out.PrintRow (true, cfg, [ name; bin + "!" + func ])) + +let translateDllChracteristcs chars = + let enumChars = + System.Enum.GetValues (typeof) + :?> DllCharacteristics [] + |> Array.toList + let rec loop acc chars = function + | [] -> List.rev acc + | enumChar :: tail as all -> + if uint64 enumChar &&& chars = uint64 enumChar then + loop ((" - " + enumChar.ToString ()) :: acc) chars tail + elif uint64 0x0080 &&& chars = uint64 0x0080 then + loop (" - ForceIntegrity" :: acc) (chars ^^^ uint64 0x0080) all + elif uint64 0x4000 &&& chars = uint64 0x4000 then + loop (" - ControlFlowGuard" :: acc) (chars ^^^ uint64 0x4000) all + else + loop acc chars tail + loop [] chars enumChars + +let dumpOptionalHeader _ (fi: PEFileInfo) = + let hdr = fi.PE.PEHeaders.PEHeader + let imageBase = hdr.ImageBase + let sizeOfImage = uint64 hdr.SizeOfImage + let entryPoint = String.u64ToHex (imageBase + uint64 hdr.AddressOfEntryPoint) + let startImage = String.u64ToHex imageBase + let endImage = String.u64ToHex (imageBase + sizeOfImage - uint64 1) + let exportDir = hdr.ExportTableDirectory + let importDir = hdr.ImportTableDirectory + let resourceDir = hdr.ResourceTableDirectory + let exceptionDir = hdr.ExceptionTableDirectory + let certificateDir = hdr.CertificateTableDirectory + let baseRelocDir = hdr.BaseRelocationTableDirectory + let debugDir = hdr.DebugTableDirectory + let architectureDir = hdr.CopyrightTableDirectory + let globalPtrDir = hdr.GlobalPointerTableDirectory + let threadLoStorDir = hdr.ThreadLocalStorageTableDirectory + let loadConfigDir = hdr.ThreadLocalStorageTableDirectory + let boundImpDir = hdr.BoundImportTableDirectory + let importAddrDir = hdr.ImportAddressTableDirectory + let delayImpDir = hdr.DelayImportTableDirectory + let comDescDir = hdr.CorHeaderTableDirectory + out.PrintTwoCols + "Magic:" + (String.u64ToHex (uint64 hdr.Magic) + + String.wrapParen (hdr.Magic.ToString ())) + out.PrintTwoCols + "Linker version:" + (hdr.MajorLinkerVersion.ToString () + + "." + hdr.MinorLinkerVersion.ToString ()) + out.PrintTwoCols + "Size of code:" + (String.u64ToHex (uint64 hdr.SizeOfCode)) + out.PrintTwoCols + "Size of initialized data:" + (String.u64ToHex (uint64 hdr.SizeOfInitializedData)) + out.PrintTwoCols + "Size of uninitialized data:" + (String.u64ToHex (uint64 hdr.SizeOfUninitializedData)) + out.PrintTwoCols + "Entry point:" + entryPoint + out.PrintTwoCols + "Base of code:" + (String.u64ToHex (uint64 hdr.BaseOfCode)) + out.PrintTwoCols + "Image base:" + (String.u64ToHex imageBase + + String.wrapParen (startImage + " to " + endImage)) + out.PrintTwoCols + "Section alignment:" + (String.u64ToHex (uint64 hdr.SectionAlignment)) + out.PrintTwoCols + "File Alignment:" + (String.u64ToHex (uint64 hdr.FileAlignment)) + out.PrintTwoCols + "Operating system version:" + (hdr.MajorOperatingSystemVersion.ToString () + + "." + hdr.MinorOperatingSystemVersion.ToString ()) + out.PrintTwoCols + "Image version:" + (hdr.MajorImageVersion.ToString () + + "." + hdr.MinorImageVersion.ToString ()) + out.PrintTwoCols + "Subsystem version:" + (hdr.MajorSubsystemVersion.ToString () + + "." + hdr.MinorSubsystemVersion.ToString ()) + out.PrintTwoCols + "Size of image:" + (String.u64ToHex sizeOfImage) + out.PrintTwoCols + "Size of headers:" + (String.u64ToHex (uint64 hdr.SizeOfHeaders)) + out.PrintTwoCols + "Checksum:" + (String.u64ToHex (uint64 hdr.CheckSum)) + out.PrintTwoCols + "Subsystem:" + (String.u64ToHex (uint64 hdr.Subsystem) + + String.wrapParen (hdr.Subsystem.ToString ())) + out.PrintTwoCols + "DLL characteristics:" + (String.u64ToHex (uint64 hdr.DllCharacteristics)) + translateDllChracteristcs (uint64 hdr.DllCharacteristics) + |> List.iter (fun str -> out.PrintTwoCols "" str) + out.PrintTwoCols + "Size of stack reserve:" + (String.u64ToHex (uint64 hdr.SizeOfStackReserve)) + out.PrintTwoCols + "Size of stack commit:" + (String.u64ToHex (uint64 hdr.SizeOfStackCommit)) + out.PrintTwoCols + "Size of heap reserve:" + (String.u64ToHex (uint64 hdr.SizeOfHeapReserve)) + out.PrintTwoCols + "Size of heap commit:" + (String.u64ToHex (uint64 hdr.SizeOfHeapCommit)) + out.PrintTwoCols + "Loader flags (reserved):" + "0x0" + out.PrintTwoCols + "Number of directories:" + (hdr.NumberOfRvaAndSizes.ToString ()) + out.PrintTwoCols + "RVA[size] of Export Table Directory:" + (String.u64ToHex (uint64 exportDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 exportDir.Size))) + out.PrintTwoCols + "RVA[size] of Import Table Directory:" + (String.u64ToHex (uint64 importDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 importDir.Size))) + out.PrintTwoCols + "RVA[size] of Resource Table Directory:" + (String.u64ToHex (uint64 resourceDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 resourceDir.Size))) + out.PrintTwoCols + "RVA[size] of Exception Table Directory:" + (String.u64ToHex (uint64 exceptionDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 exceptionDir.Size))) + out.PrintTwoCols + "RVA[size] of Certificate Table Directory:" + (String.u64ToHex (uint64 certificateDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 certificateDir.Size))) + out.PrintTwoCols + "RVA[size] of Base Relocation Table Directory:" + (String.u64ToHex (uint64 baseRelocDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 baseRelocDir.Size))) + out.PrintTwoCols + "RVA[size] of Debug Table Directory:" + (String.u64ToHex (uint64 debugDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 debugDir.Size))) + out.PrintTwoCols + "RVA[size] of Architecture Table Directory:" + (String.u64ToHex (uint64 architectureDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 architectureDir.Size))) + out.PrintTwoCols + "RVA[size] of Global Pointer Table Directory:" + (String.u64ToHex (uint64 globalPtrDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 globalPtrDir.Size))) + out.PrintTwoCols + "RVA[size] of Thread Storage Table Directory:" + (String.u64ToHex (uint64 threadLoStorDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 threadLoStorDir.Size))) + out.PrintTwoCols + "RVA[size] of Load Configuration Table Directory:" + (String.u64ToHex (uint64 loadConfigDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 loadConfigDir.Size))) + out.PrintTwoCols + "RVA[size] of Bound Import Table Directory:" + (String.u64ToHex (uint64 boundImpDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 boundImpDir.Size))) + out.PrintTwoCols + "RVA[size] of Import Address Table Directory:" + (String.u64ToHex (uint64 importAddrDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 importAddrDir.Size))) + out.PrintTwoCols + "RVA[size] of Delay Import Table Directory:" + (String.u64ToHex (uint64 delayImpDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 delayImpDir.Size))) + out.PrintTwoCols + "RVA[size] of COM Descriptor Table Directory:" + (String.u64ToHex (uint64 comDescDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 comDescDir.Size))) + out.PrintTwoCols + "RVA[size] of Reserved Directory:" + "0x0[0x0]" + +let translateCorFlags flags = + let enumFlags = + System.Enum.GetValues (typeof) + :?> CorFlags [] + |> Array.toList + let rec loop acc flags = function + | [] -> List.rev acc + | enumFlag :: tail -> + if uint64 enumFlag &&& flags = uint64 enumFlag then + loop ((" - " + enumFlag.ToString ()) :: acc) flags tail + else + loop acc flags tail + loop [] flags enumFlags + +let dumpCLRHeader _ (fi: PEFileInfo) = + let hdr = fi.PE.PEHeaders.CorHeader + if isNull hdr then + out.PrintTwoCols "" "Not found." + else + let metaDataDir = hdr.MetadataDirectory + let resourcesDir = hdr.ResourcesDirectory + let strongNameSigDir = hdr.StrongNameSignatureDirectory + let codeMgrTblDir = hdr.CodeManagerTableDirectory + let vTableFixups = hdr.VtableFixupsDirectory + let exportAddrTblJmps = hdr.ExportAddressTableJumpsDirectory + let managedNativeHdr = hdr.ManagedNativeHeaderDirectory + out.PrintTwoCols + "Runtime version:" + (hdr.MajorRuntimeVersion.ToString () + + "." + hdr.MinorRuntimeVersion.ToString ()) + out.PrintTwoCols + "RVA[size] of Meta Data Directory:" + (String.u64ToHex (uint64 metaDataDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 metaDataDir.Size))) + out.PrintTwoCols + "Flags:" + (String.u64ToHex (uint64 hdr.Flags)) + translateCorFlags (uint64 hdr.Flags) + |> List.iter (fun str -> out.PrintTwoCols "" str) + out.PrintTwoCols + "RVA[size] of Resources Directory:" + (String.u64ToHex (uint64 resourcesDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 resourcesDir.Size))) + out.PrintTwoCols + "RVA[size] of Strong Name Signature Directory:" + (String.u64ToHex (uint64 strongNameSigDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 strongNameSigDir.Size))) + out.PrintTwoCols + "RVA[size] of Code Manager Table Directory:" + (String.u64ToHex (uint64 codeMgrTblDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 codeMgrTblDir.Size))) + out.PrintTwoCols + "RVA[size] of VTable Fixups Directory:" + (String.u64ToHex (uint64 vTableFixups.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 vTableFixups.Size))) + out.PrintTwoCols + "RVA[size] of Export Address Table Jumps Directory:" + (String.u64ToHex (uint64 exportAddrTblJmps.RelativeVirtualAddress) + + String.wrapSqrdBracket + (String.u64ToHex (uint64 exportAddrTblJmps.Size))) + out.PrintTwoCols + "RVA[size] of Managed Native Header Directory:" + (String.u64ToHex (uint64 managedNativeHdr.RelativeVirtualAddress) + + String.wrapSqrdBracket (String.u64ToHex (uint64 managedNativeHdr.Size))) + +let dumpDependencies _ (fi: PEFileInfo) = + fi.GetLinkageTableEntries () + |> Seq.map (fun e -> e.LibraryName) + |> Set.ofSeq + |> Set.iter (fun s -> out.PrintTwoCols "" s) diff --git a/src/RearEnd/FileViewer/Program.fs b/src/RearEnd/FileViewer/Program.fs new file mode 100644 index 00000000..61e17f5f --- /dev/null +++ b/src/RearEnd/FileViewer/Program.fs @@ -0,0 +1,232 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.RearEnd.FileViewer.Program + +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinInterface +open B2R2.RearEnd +open B2R2.RearEnd.FileViewer.Helper + +let dumpBasic (fi: FileInfo) = + let entry = FileInfo.EntryPointToString fi.EntryPoint |> ColoredSegment.green + out.PrintSectionTitle "Basic Information" + out.PrintTwoCols "File format:" (FileFormat.toString fi.FileFormat) + out.PrintTwoCols "Architecture:" (ISA.ArchToString fi.ISA.Arch) + out.PrintTwoCols "Endianness:" (Endian.toString fi.ISA.Endian) + out.PrintTwoCols "Word size:" (WordSize.toString fi.WordSize + " bit") + out.PrintTwoCols "File type:" (FileInfo.FileTypeToString fi.FileType) + out.PrintTwoColsWithColorOnSnd "Entry point:" [ entry ] + out.PrintLine () + +let dumpSecurity (fi: FileInfo) = + out.PrintSectionTitle "Security Information" + out.PrintTwoCols "Stripped binary:" (fi.IsStripped.ToString ()) + out.PrintTwoCols "DEP (NX) enabled:" (fi.IsNXEnabled.ToString ()) + out.PrintTwoCols "Relocatable (PIE):" (fi.IsRelocatable.ToString ()) + out.PrintLine () + +let dumpSpecific opts (fi: FileInfo) title elf pe mach = + out.PrintSectionTitle title + match fi with + | :? ELFFileInfo as fi -> elf opts fi + | :? PEFileInfo as fi -> pe opts fi + | :? MachFileInfo as fi -> mach opts fi + | _ -> Utils.futureFeature () + out.PrintLine () + +let dumpFileHeader (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "File Header Information" + ELFViewer.dumpFileHeader + PEViewer.dumpFileHeader + MachViewer.dumpFileHeader + +let dumpSectionHeaders (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Section Header Information" + ELFViewer.dumpSectionHeaders + PEViewer.dumpSectionHeaders + MachViewer.dumpSectionHeaders + +let dumpSectionDetails (secname: string) (fi: FileInfo) = + dumpSpecific secname fi "Section Details" + ELFViewer.dumpSectionDetails + PEViewer.dumpSectionDetails + MachViewer.dumpSectionDetails + +let dumpSymbols (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Symbol Information" + ELFViewer.dumpSymbols + PEViewer.dumpSymbols + MachViewer.dumpSymbols + +let dumpRelocs (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Relocation Information" + ELFViewer.dumpRelocs + PEViewer.dumpRelocs + MachViewer.dumpRelocs + +let dumpFunctions (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Function Information" + ELFViewer.dumpFunctions + PEViewer.dumpFunctions + MachViewer.dumpFunctions + +let dumpSegments (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Segment Information" + ELFViewer.dumpSegments PEViewer.badAccess MachViewer.badAccess + +let dumpLinkageTable (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Linkage Table Information" + ELFViewer.dumpLinkageTable PEViewer.badAccess MachViewer.badAccess + +let dumpEHFrame hdl (fi: FileInfo) = + dumpSpecific hdl fi ".eh_frame Information" + ELFViewer.dumpEHFrame PEViewer.badAccess MachViewer.badAccess + +let dumpLSDA hdl (fi: FileInfo) = + dumpSpecific hdl fi ".gcc_except_table Information" + ELFViewer.dumpLSDA PEViewer.badAccess MachViewer.badAccess + +let dumpNotes hdl (fi: FileInfo) = + dumpSpecific hdl fi ".notes Information" + ELFViewer.dumpNotes PEViewer.badAccess MachViewer.badAccess + +let dumpImports (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Import table Information" + ELFViewer.badAccess PEViewer.dumpImports MachViewer.badAccess + +let dumpExports (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Export table Information" + ELFViewer.badAccess PEViewer.dumpExports MachViewer.badAccess + +let dumpOptionalHeader (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Optional Header Information" + ELFViewer.badAccess PEViewer.dumpOptionalHeader MachViewer.badAccess + +let dumpCLRHeader (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "CLR Header Information" + ELFViewer.badAccess PEViewer.dumpCLRHeader MachViewer.badAccess + +let dumpDependencies (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Dependencies Information" + ELFViewer.badAccess PEViewer.dumpDependencies MachViewer.badAccess + +let dumpArchiveHeader (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Archive Header Information" + ELFViewer.badAccess PEViewer.badAccess MachViewer.dumpArchiveHeader + +let dumpUniversalHeader (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Universal Header Information" + ELFViewer.badAccess PEViewer.badAccess MachViewer.dumpUniversalHeader + +let dumpLoadCommands (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Load Commands Information" + ELFViewer.badAccess PEViewer.badAccess MachViewer.dumpLoadCommands + +let dumpSharedLibs (opts: FileViewerOpts) (fi: FileInfo) = + dumpSpecific opts fi "Shared Libs Information" + ELFViewer.badAccess PEViewer.badAccess MachViewer.dumpSharedLibs + +let printFileName filepath = + [ Green, "["; Yellow, filepath; Green, "]" ] |> out.PrintLine + out.PrintLine () + +let printBasic fi = + dumpBasic fi + dumpSecurity fi + +let printAll opts hdl (fi: FileInfo) = + dumpBasic fi + dumpSecurity fi + dumpFileHeader opts fi + dumpSectionHeaders opts fi + dumpSymbols opts fi + dumpRelocs opts fi + dumpFunctions opts fi + match fi with + | :? ELFFileInfo as fi -> + dumpSegments opts fi + dumpLinkageTable opts fi + dumpEHFrame hdl fi + dumpLSDA hdl fi + | :? PEFileInfo as fi -> + dumpImports opts fi + dumpExports opts fi + dumpOptionalHeader opts fi + dumpCLRHeader opts fi + dumpDependencies opts fi + | :? MachFileInfo as fi -> + dumpLoadCommands opts fi + dumpSharedLibs opts fi + | _ -> Utils.futureFeature () + +let printSelectively hdl opts fi = function + | DisplayAll -> Utils.impossible () + | DisplayFileHeader -> dumpFileHeader opts fi + | DisplaySectionHeaders -> dumpSectionHeaders opts fi + | DisplaySectionDetails s -> dumpSectionDetails s fi + | DisplaySymbols -> dumpSymbols opts fi + | DisplayRelocations -> dumpRelocs opts fi + | DisplayFunctions -> dumpFunctions opts fi + | DisplayELFSpecific ELFDisplayProgramHeader -> dumpSegments opts fi + | DisplayELFSpecific ELFDisplayPLT -> dumpLinkageTable opts fi + | DisplayELFSpecific ELFDisplayEHFrame -> dumpEHFrame hdl fi + | DisplayELFSpecific ELFDisplayLSDA -> dumpLSDA hdl fi + | DisplayELFSpecific ELFDisplayNotes -> dumpNotes hdl fi + | DisplayPESpecific PEDisplayImports -> dumpImports opts fi + | DisplayPESpecific PEDisplayExports -> dumpExports opts fi + | DisplayPESpecific PEDisplayOptionalHeader -> dumpOptionalHeader opts fi + | DisplayPESpecific PEDisplayCLRHeader -> dumpCLRHeader opts fi + | DisplayPESpecific PEDisplayDependencies -> dumpDependencies opts fi + | DisplayMachSpecific MachDisplayArchiveHeader -> dumpArchiveHeader opts fi + | DisplayMachSpecific MachDisplayUniversalHeader -> dumpUniversalHeader opts fi + | DisplayMachSpecific MachDisplayLoadCommands -> dumpLoadCommands opts fi + | DisplayMachSpecific MachDisplaySharedLibs -> dumpSharedLibs opts fi + +let dumpFile (opts: FileViewerOpts) (filepath: string) = + let hdl = BinHandle.Init (opts.ISA, opts.BaseAddress, filepath) + let fi = hdl.FileInfo + printFileName fi.FilePath + if opts.DisplayItems.Count = 0 then printBasic fi + elif opts.DisplayItems.Contains DisplayAll then printAll opts hdl fi + else opts.DisplayItems |> Seq.iter (printSelectively hdl opts fi) + +let [] private toolName = "fileview" +let [] private usageTail = "" + +let dump files opts = + CmdOpts.SanitizeRestArgs files + match files with + | [] -> + Printer.printErrorToConsole "File(s) must be given." + CmdOpts.PrintUsage toolName usageTail Cmd.spec + | files -> + try files |> List.iter (dumpFile opts) + finally out.Flush () + +[] +let main args = + let opts = FileViewerOpts () + CmdOpts.ParseAndRun dump toolName usageTail Cmd.spec opts args diff --git a/src/RearEnd/Launcher/B2R2.RearEnd.Launcher.fsproj b/src/RearEnd/Launcher/B2R2.RearEnd.Launcher.fsproj new file mode 100644 index 00000000..e58692a1 --- /dev/null +++ b/src/RearEnd/Launcher/B2R2.RearEnd.Launcher.fsproj @@ -0,0 +1,31 @@ + + + + Exe + net5.0 + true + b2r2 + ../../../build + LICENSE.md + b2r2-240x240.png + README.md + B2R2 rear-end launcher. + + + + + + + + + + + + + + + + + + + diff --git a/src/RearEnd/Launcher/Program.fs b/src/RearEnd/Launcher/Program.fs new file mode 100644 index 00000000..526ca51b --- /dev/null +++ b/src/RearEnd/Launcher/Program.fs @@ -0,0 +1,115 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.RearEnd.Launcher + +open System.Reflection +open B2R2 +open B2R2.RearEnd + +let showUsage () = + Printer.printToConsole """ + '''''''''' + .;' ';. + ;' o o '; 888888b. 8888888b. + .. ,, ,, .. 888 "88b 888 "88b +;''cl l:MMO 888 .88P .oPYo. 888 888 .oPYo. +l c.dooooooooooooooood.:MMM 8888888K. `8 888 d88P `8 +: cdMMMMMMMMMMMMMMMMMMd:MMk 888 "Y88b oP' 8888888P" oP' + .. .WMMMMMWWMMMMMMWMMW. :/ 888 888 .oP' 888 T88b .oP' + 'XMMMMl.MMMMMX.xX' 888 d88P 8' 888 T88b 8' + cKMMMMMMMMMMKc 8888888P" 8ooooo 888 T88b 8ooooo + `dcoddocd' + +B2R2 is the next-generation binary reversing framework that runs +purely on .NET, that is it runs on any platform that .NET supports. +This is the B2R2 launcher, which is a .NET tool that can invoke +various tools provided by our framework. To know more about B2R2, +please visit our official website: https://b2r2.org/. + +Usage: b2r2 [app name] + +[Available Applications] + +- file (a.k.a. peek, fileview) + + This is a file format reader that is similar to readelf or otool. + You can read various file format information using this app. To + learn more about the tool, type the following command: + + $ b2r2 file --help + +- dump (a.k.a. disasm, bindump) + + This is a linear-sweep disassembler similar to objdump, although + this app is more powerful and versatile. To learn more about the + tool, type the following command: + + $ b2r2 dump --help + +- explore (a.k.a. binexplorer, analyze) + + This is a recursive-descent disassembler that provides a web-based + GUI as well as its own CLI terminal. To learn more about the tool, + type the following command: + + $ b2r2 explore --help + +- repl + + This is a REPL (Read Evaluate Print Loop) for our binary IR as well + as binary assembly languages. To learn more about the tool type the + following command: + + $ b2r2 repl --help + +- asm (a.k.a. assembler) + + This is a simple cross-platform assembler. To learn more about the + tool, type the following command: + + $ b2r2 asm --help +""" + +let printMyVersion () = + let asm = Assembly.GetEntryAssembly () + let attr = asm.GetCustomAttribute () + attr.InformationalVersion.ToString () + |> Printer.printToConsole + +let handleCommands (cmd: string) (rest: string []) = + match cmd.ToLower () with + | "help" | "--help" | "-h" -> showUsage (); 0 + | "fileviewer" | "file" | "fileview" | "peek" -> FileViewer.Program.main rest + | "bindump" | "disasm" | "dump" | "disas" | "dis" -> BinDump.Program.main rest + | "binexplorer" | "explore" | "binexplore" | "analyze" -> + BinExplorer.Program.main rest + | "repl" -> Repl.Program.main rest + | "assembler" | "asm" -> Assembler.Program.main rest + | _ -> Utils.futureFeature () + +[] +let main argv = + if argv.Length = 0 then showUsage (); 1 + else handleCommands argv.[0] argv.[1..] diff --git a/src/RearEnd/Launcher/README.md b/src/RearEnd/Launcher/README.md new file mode 100644 index 00000000..b2f921a6 --- /dev/null +++ b/src/RearEnd/Launcher/README.md @@ -0,0 +1,12 @@ +# B2R2.RearEnd.Launcher + +### B2R2? + +B2R2 is a binary analysis and reversing framework written purely in F#. Since it +does not rely on any native (unmanaged) code, it is readily usable in any +platform or OS that .NET runs on. + +### B2R2.RearEnd.Launcher Package? + +`B2R2.RearEnd.Launcher` is the B2R2's command-line launcher that can start +various different tools provided by our framework. This is a .NET CLI tool. diff --git a/src/RearEnd/ROP/B2R2.RearEnd.ROP.fsproj b/src/RearEnd/ROP/B2R2.RearEnd.ROP.fsproj new file mode 100644 index 00000000..6ce4aaec --- /dev/null +++ b/src/RearEnd/ROP/B2R2.RearEnd.ROP.fsproj @@ -0,0 +1,23 @@ + + + + net5.0 + false + + + + + + + + + + + + + + + + + + diff --git a/src/ROP/Chain.fs b/src/RearEnd/ROP/Chain.fs similarity index 96% rename from src/ROP/Chain.fs rename to src/RearEnd/ROP/Chain.fs index 34f9f361..257a87ca 100644 --- a/src/ROP/Chain.fs +++ b/src/RearEnd/ROP/Chain.fs @@ -22,16 +22,16 @@ SOFTWARE. *) -namespace B2R2.ROP +namespace B2R2.RearEnd.ROP open System.Collections open B2R2 -open B2R2.BinFile -open B2R2.FrontEnd +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinInterface type ROPHandle = { BinBase : Addr - BinHdl : BinHandler + BinHdl : BinHandle Gadgets : GadgetArr Summaries : Concurrent.ConcurrentDictionary } @@ -57,8 +57,13 @@ module ROPHandle = } let private getSummary (hdl: ROPHandle) (gadget: Gadget) = - hdl.Summaries.GetOrAdd (gadget.Offset, - (fun _ -> Summary.summary hdl.BinHdl gadget)) + try + hdl.Summaries.GetOrAdd (gadget.Offset, + (fun _ -> Summary.summary hdl.BinHdl gadget)) + |> Ok + with + | B2R2.BinIR.InvalidExprException as e -> Error <| sprintf "%A" e + | e -> raise e let private getSetterMap hdl = let folder acc info = @@ -176,7 +181,7 @@ module ROPHandle = let private findBytes hdl bytes = let chooser (seg: Segment) = let min = seg.Address - BinHandler.ReadBytes (hdl.BinHdl, min, int seg.Size) + BinHandle.ReadBytes (hdl.BinHdl, min, int seg.Size) |> ByteArray.tryFindIdx min bytes (getFileInfo hdl).GetSegments Permission.Readable |> Seq.tryPick chooser diff --git a/src/ROP/Gadget.fs b/src/RearEnd/ROP/Gadget.fs similarity index 95% rename from src/ROP/Gadget.fs rename to src/RearEnd/ROP/Gadget.fs index 615f9b15..971c8a7f 100644 --- a/src/ROP/Gadget.fs +++ b/src/RearEnd/ROP/Gadget.fs @@ -22,10 +22,11 @@ SOFTWARE. *) -namespace B2R2.ROP +namespace B2R2.RearEnd.ROP open System -open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinInterface /// Tail is a instruction sequence that needs to be placed at the end of each /// ROP gadget. @@ -56,7 +57,7 @@ module Gadget = let sb = sb.Append (sprintf "[*] Offset = %x\n" gadget.Offset) gadget.Instrs |> List.fold (fun (sb: Text.StringBuilder) i -> - let disasm = BinHandler.DisasmInstr hdl true false i + let disasm = BinHandle.DisasmInstr hdl true false i sb.Append(disasm).Append(Environment.NewLine)) sb |> fun sb -> sb.ToString () diff --git a/src/ROP/Galileo.fs b/src/RearEnd/ROP/Galileo.fs similarity index 91% rename from src/ROP/Galileo.fs rename to src/RearEnd/ROP/Galileo.fs index dbc93fe4..ea4914b1 100644 --- a/src/ROP/Galileo.fs +++ b/src/RearEnd/ROP/Galileo.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module B2R2.ROP.Galileo +module B2R2.RearEnd.ROP.Galileo open B2R2 -open B2R2.BinFile -open B2R2.FrontEnd +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinInterface open B2R2.BinIR.LowUIR let filter = function @@ -77,10 +77,10 @@ let inline updateGadgets curAddr nextAddr ins gadgets = let rec buildBackward hdl minAddr curAddr lastAddr map = if curAddr < minAddr || (curAddr + 1UL) = 0UL then map else - match BinHandler.TryParseInstr hdl hdl.DefaultParsingContext curAddr with - | Some ins -> + match BinHandle.TryParseInstr (hdl, curAddr) with + | Ok ins -> let nextAddr = curAddr + (uint64 ins.Length) - if ins.IsExit () then + if ins.IsBBLEnd () then if nextAddr < lastAddr then map else buildBackward hdl minAddr (curAddr - 1UL) lastAddr map else @@ -89,13 +89,13 @@ let rec buildBackward hdl minAddr curAddr lastAddr map = let minAddr' = curAddr - instrMaxLen hdl buildBackward hdl minAddr' (curAddr - 1UL) curAddr map | None -> buildBackward hdl minAddr (curAddr - 1UL) lastAddr map - | None -> buildBackward hdl minAddr (curAddr - 1UL) lastAddr map + | Error _ -> buildBackward hdl minAddr (curAddr - 1UL) lastAddr map let parseTail hdl addr bytes = let lastAddr = (Array.length bytes |> uint64) + addr let rec parseLoop acc addr = if lastAddr > addr then - let ins = BinHandler.ParseInstr hdl hdl.DefaultParsingContext addr + let ins = BinHandle.ParseInstr (hdl, addr) parseLoop (ins :: acc) (addr + uint64 ins.Length) else List.rev acc parseLoop [] addr @@ -106,7 +106,7 @@ let private buildGadgetMap hdl (tail: Tail) map (seg: Segment) = let sGadget = parseTail hdl idx tail.Pattern |> Gadget.create idx Map.add idx sGadget map |> buildBackward hdl (min 0UL (minAddr - instrMaxLen hdl)) (idx - 1UL) idx - BinHandler.ReadBytes (hdl, seg.Address, int (seg.Size)) + BinHandle.ReadBytes (hdl, seg.Address, int (seg.Size)) |> ByteArray.findIdxs minAddr tail.Pattern |> List.fold build map diff --git a/src/ROP/ROPPayload.fs b/src/RearEnd/ROP/ROPPayload.fs similarity index 99% rename from src/ROP/ROPPayload.fs rename to src/RearEnd/ROP/ROPPayload.fs index ff78e578..2f7af27a 100644 --- a/src/ROP/ROPPayload.fs +++ b/src/RearEnd/ROP/ROPPayload.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.ROP +namespace B2R2.RearEnd.ROP open System.Text diff --git a/src/ROP/ROPValue.fs b/src/RearEnd/ROP/ROPValue.fs similarity index 95% rename from src/ROP/ROPValue.fs rename to src/RearEnd/ROP/ROPValue.fs index 47721339..6ded27c4 100644 --- a/src/ROP/ROPValue.fs +++ b/src/RearEnd/ROP/ROPValue.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -namespace B2R2.ROP +namespace B2R2.RearEnd.ROP open System open B2R2 -open B2R2.FrontEnd +open B2R2.FrontEnd.BinInterface type ROPExpr = | Var of string @@ -73,7 +73,7 @@ module ROPValue = let dummy32 = ofUInt32 0xdeadbeefu let strFolder hdl acc ins = - let acc = acc + " " + BinHandler.DisasmInstr hdl true false ins + let acc = acc + " " + BinHandle.DisasmInstr hdl true false ins acc + Environment.NewLine let toString hdl binBase = function diff --git a/src/RearEnd/ROP/Simplify.fs b/src/RearEnd/ROP/Simplify.fs new file mode 100644 index 00000000..5380ee63 --- /dev/null +++ b/src/RearEnd/ROP/Simplify.fs @@ -0,0 +1,234 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.RearEnd.ROP.Simplify + +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR + +let inline negNum x = BitVector.neg x |> AST.num + +let inline zeroNum ty = BitVector.zero ty |> AST.num + +let inline maxNum ty = + match ty with + | 8 -> BitVector.maxUInt8 |> AST.num + | 16 -> BitVector.maxUInt16 |> AST.num + | 32 -> BitVector.maxUInt32 |> AST.num + | 64 -> BitVector.maxUInt64 |> AST.num + | _ -> failwith "maxNum fail" + +let inline isZero e = + match e.E with + | Num n -> (BitVector.getValue n).IsZero + | _ -> false + +let inline isOne e = + match e.E with + | Num n -> (BitVector.getValue n).IsOne + | _ -> false + +let isFlippable x = (BitVector.isNegative x) && not (BitVector.isSignedMin x) + +let inline isMax ty e = + match e.E with + | Num n -> (BitVector.one ty |> BitVector.add n |> BitVector.getValue).IsZero + | _ -> false + +let inline binADD e1 e2 = AST.binop BinOpType.ADD e1 e2 + +let inline binSUB e1 e2 = AST.binop BinOpType.SUB e1 e2 + +let inline subNum n1 n2 = BitVector.sub n1 n2 |> AST.num + +let inline addNum n1 n2 = BitVector.add n1 n2 |> AST.num + +let rec simplify expr = + match expr.E with + | UnOp (op, e1, _) -> AST.unop op <| simplify e1 + | BinOp (op, ty, e1, e2, _) -> simplifyBinOp op ty e1 e2 + | RelOp (op, e1, e2, _) -> AST.relop op (simplify e1) (simplify e2) + | Load (endian, ty, e1, _) -> AST.load endian ty <| simplify e1 + | Ite (e1, e2, e3, _) -> AST.ite (simplify e1) (simplify e2) (simplify e3) + | Cast (kind, ty, e1, _) -> simplifyCast kind ty e1 + | _ -> expr (* Var, TempVar, Num, Name, PCVar *) + +and simplifyBinOp op ty e1 e2 = + match op, e1.E, e2.E with + | BinOpType.XOR, _, _ when e1 = e2 -> zeroNum ty + | BinOpType.XOR, _, _ when isZero e1 -> simplify e2 + | BinOpType.XOR, _, _ when isZero e2 -> simplify e1 + | BinOpType.AND, _, _ when e1 = e2 -> simplify e1 + | BinOpType.AND, _, _ when isMax ty e1 -> simplify e2 + | BinOpType.AND, _, _ when isMax ty e2 -> simplify e1 + | BinOpType.AND, _, _ when isZero e1 || isZero e2 -> zeroNum ty + | BinOpType.OR, _, _ when e1 = e2 -> simplify e1 + | BinOpType.OR, _, _ when isZero e1 -> simplify e2 + | BinOpType.OR, _, _ when isZero e2 -> simplify e1 + | BinOpType.OR, _, _ when isMax ty e1 || isMax ty e2 -> maxNum ty + | op, _, _ when isZero e1 && (op = BinOpType.ADD || op = BinOpType.SUB) -> + simplify e2 + | op, _, _ when isZero e2 && (op = BinOpType.ADD || op = BinOpType.SUB) -> + simplify e1 + | BinOpType.ADD, Num (n1), _ when isFlippable n1 -> + simplify (binSUB e2 (negNum n1)) + | BinOpType.ADD, _, Num (n1) when isFlippable n1 -> + simplify (binSUB e2 (negNum n1)) + | BinOpType.SUB, _, Num (n2) when isFlippable n2 -> + simplify (binADD e1 (negNum n2)) + | BinOpType.SUB, Num (n1), _ when isFlippable n1 -> + simplify (binSUB e2 (negNum n1)) + (* ADD + ADD *) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) -> + simplify (binADD (binADD e2 e4) (addNum n1 n3)) + (* SUB + SUB *) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4, _) -> + simplify (binSUB (addNum n1 n3) (binADD e2 e4)) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.SUB, _, e3, { E = Num (n4) }, _) -> + simplify (binADD (subNum n1 n4) (binSUB e3 e2)) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, e2, { E = Num (n1) }, _), + BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4, _) -> + simplify (binADD (subNum n3 n1) (binSUB e2 e4)) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, e2, { E = Num (n1) }, _), + BinOp (BinOpType.SUB, _, e4, { E = Num (n3) }, _) -> + simplify (binSUB (binADD e2 e4) (addNum n1 n3)) + (* Num + Num *) + | BinOpType.ADD, Num (n1), Num (n2) -> addNum n1 n2 + (* ADD + Num, Num + ADD *) + | BinOpType.ADD, Num (n1), BinOp (BinOpType.ADD, _, { E = Num (n2) }, e3, _) + | BinOpType.ADD, Num (n1), BinOp (BinOpType.ADD, _, e3, { E = Num (n2) }, _) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n2) }, e3, _), Num (n1) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, e3, { E = Num (n2) }, _), Num (n1) + -> + simplify (binADD e3 (addNum n1 n2)) + (* Num + SUB, SUB + Num *) + | BinOpType.ADD, Num (n1), BinOp (BinOpType.SUB, _, { E = Num (n2) }, e3, _) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n2) }, e3, _), Num (n1) + -> + simplify (binSUB (addNum n1 n2) e3) + | BinOpType.ADD, Num (n1), BinOp (BinOpType.SUB, _, e2, { E = Num (n3) }, _) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, e2, { E = Num (n3) }, _), Num (n1) + -> + simplify (binADD e2 (subNum n1 n3)) + (* SUB + ADD, ADD + SUB *) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _), + BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _), + BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _) -> + simplify (binADD (addNum n1 n3) (binSUB e4 e2)) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _), + BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _), + BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) -> + simplify (binADD (subNum n3 n2) (binADD e1 e4)) + (* ADD - ADD *) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) -> + simplify (binADD (binSUB e2 e4) (subNum n1 n3)) + (* SUB - SUB *) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4, _) -> + simplify (binSUB (subNum n1 n3) (binSUB e2 e4)) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.SUB, _, e3, { E = Num (n4) }, _) -> + simplify (binSUB (addNum n1 n4) (binADD e2 e3)) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, e2, { E = Num (n1) }, _), + BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4, _) -> + simplify (binSUB (binADD e2 e4) (addNum n1 n3)) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, e2, { E = Num (n1) }, _), + BinOp (BinOpType.SUB, _, e4, { E = Num (n3) }, _) -> + simplify (binSUB (binSUB e2 e4) (subNum n1 n3)) + (* Num - Num *) + | BinOpType.SUB, Num (n1), Num (n2) -> subNum n1 n2 + (* ADD - Num, Num - ADD *) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), Num (n3) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), Num (n3) + -> simplify (binADD (subNum n1 n3) e2) + | BinOpType.SUB, Num (n1), BinOp (BinOpType.ADD, _, { E = Num (n2) }, e3, _) + | BinOpType.SUB, Num (n1), BinOp (BinOpType.ADD, _, e3, { E = Num (n2) }, _) + -> simplify (binSUB (subNum n1 n2) e3) + (* SUB - Num, Num - SUB *) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), Num (n3) + -> simplify (binSUB (subNum n1 n3) e2) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _), Num (n3) + -> simplify (binSUB e1 (addNum n2 n3)) + | BinOpType.SUB, Num (n1), BinOp (BinOpType.SUB, _, { E = Num (n2) }, e3, _) + -> simplify (binADD e3 (subNum n1 n2)) + | BinOpType.SUB, Num (n1), BinOp (BinOpType.SUB, _, e2, { E = Num (n3) }, _) + -> simplify (binSUB (addNum n1 n3) e2) + (* ADD - SUB, SUB - ADD *) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4, _) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), + BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4, _) -> + simplify (binADD (subNum n1 n3) (binSUB e2 e4)) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.SUB, _, e3, { E = Num (n4) }, _) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), + BinOp (BinOpType.SUB, _, e3, { E = Num (n4) }, _) -> + simplify (binADD (addNum n1 n4) (binSUB e2 e3)) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) -> + simplify (binSUB (binSUB e1 e4) (addNum n2 n3)) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) -> + simplify (binSUB (subNum n1 n3) (binADD e2 e4)) + | BinOpType.SUB, _, _ when e1 = e2 -> zeroNum ty + | BinOpType.MUL, _, _ when isOne e1 -> simplify e2 + | BinOpType.MUL, _, _ when isOne e2 -> simplify e1 + | BinOpType.MUL, _, _ when isZero e1 || isZero e2 -> zeroNum ty + | _, _, _ -> AST.binop op (simplify e1) (simplify e2) + +and simplifyCast kind ty e1 = + match kind, e1.E with + | CastKind.ZeroExt, Num n -> BitVector.zext n ty |> AST.num + | _, _ -> AST.cast kind ty <| simplify e1 diff --git a/src/ROP/State.fs b/src/RearEnd/ROP/State.fs similarity index 67% rename from src/ROP/State.fs rename to src/RearEnd/ROP/State.fs index e0010413..001ee3d9 100644 --- a/src/ROP/State.fs +++ b/src/RearEnd/ROP/State.fs @@ -22,20 +22,23 @@ SOFTWARE. *) -namespace B2R2.ROP +namespace B2R2.RearEnd.ROP open System open B2R2 open B2R2.BinIR open B2R2.BinIR.LowUIR -open B2R2.ROP.Simplify +open B2R2.RearEnd.ROP.Simplify type Reg = string type Value (expr) = let expr = simplify expr override __.GetHashCode () = expr.GetHashCode () - override this.Equals other = this.GetHashCode () = other.GetHashCode () + override this.Equals x = + match x with + | :? Value as x -> expr.Equals <| x.GetExpr () + | _ -> false interface IComparable with override this.CompareTo other = this.GetHashCode () - other.GetHashCode () @@ -45,13 +48,17 @@ type Value (expr) = module Value = let toLinear (value: Value) = - match value.GetExpr () with + match value.GetExpr().E with | Var (32, _, reg, _) -> Some (reg, 0u) - | BinOp (BinOpType.ADD, _, Var (32, _, reg, _), Num n, _, _) - | BinOp (BinOpType.ADD, _, Num n, Var (32, _, reg, _), _, _) -> + | BinOp (BinOpType.ADD, _, + { E = Var (32, _, reg, _) }, { E = Num n }, _) + | BinOp (BinOpType.ADD, _, + { E = Num n }, { E = Var (32, _, reg, _) }, _) -> Some (reg, BitVector.toUInt32 n) - | BinOp (BinOpType.SUB, _, Var (32, _, reg, _), Num n, _, _) - | BinOp (BinOpType.SUB, _, Num n, Var (32, _, reg, _), _, _) -> + | BinOp (BinOpType.SUB, _, + { E = Var (32, _, reg, _) }, { E = Num n }, _) + | BinOp (BinOpType.SUB, _, + { E = Num n }, { E = Var (32, _, reg, _) }, _) -> Some (reg, BitVector.neg n |> BitVector.toUInt32) | _ -> None @@ -77,39 +84,39 @@ module State = SideEff = false } - let private getReg state reg = - let _, _, name, _ = reg + let private getReg state name expr = match Map.tryFind name state.Regs with | Some v -> v - | None -> Var reg |> Value + | None -> Value expr let private getTempReg state name = match Map.tryFind name state.TempRegs with | Some v -> v | None -> failwithf "get T_%d fail" name - let rec evalExpr state = function - | Var (t, id, n, rs) -> getReg state (t, id, n, rs) - | TempVar (t, name) -> getTempReg state name - | UnOp (op, expr, _, _) -> AST.unop op (getEvalExpr state expr) |> Value - | BinOp (op, ty, lExpr, rExpr, _, _) -> + let rec evalExpr state e = + match e.E with + | Var (_, _, name, _) -> getReg state name e + | TempVar (_, name) -> getTempReg state name + | UnOp (op, expr, _) -> AST.unop op (getEvalExpr state expr) |> Value + | BinOp (op, ty, lExpr, rExpr, _) -> AST.binop op (getEvalExpr state lExpr) (getEvalExpr state rExpr) |> Value - | RelOp (op, lExpr, rExpr, _, _) -> + | RelOp (op, lExpr, rExpr, _) -> AST.relop op (getEvalExpr state lExpr) (getEvalExpr state rExpr) |> Value - | Load (endian, ty, expr, _, _) -> evalLoad state endian ty expr - | Ite (cExpr, tExpr, fExpr, _, _) -> + | Load (endian, ty, expr, _) -> evalLoad state endian ty expr + | Ite (cExpr, tExpr, fExpr, _) -> AST.ite (getEvalExpr state cExpr) (getEvalExpr state tExpr) (getEvalExpr state fExpr) |> Value - | Cast (kind, ty, expr, _, _) -> + | Cast (kind, ty, expr, _) -> AST.cast kind ty <| getEvalExpr state expr |> Value - | expr -> Value expr // Num, Name, PCVar + | _ -> Value e // Num, Name, PCVar and evalLoad state endian ty expr = let addr = evalExpr state expr match Map.tryFind addr state.Mems with | Some v -> let expr = v.GetExpr () - let vType = AST.typeOf expr + let vType = TypeCheck.typeOf expr if vType = ty then v elif vType > ty then AST.extract (v.GetExpr ()) ty 0 |> Value else AST.load endian ty (addr.GetExpr ()) |> Value @@ -132,10 +139,20 @@ module State = let value = evalExpr state value { state with Mems = updateMems addr value state.Mems } + let private evalCJmp state condE trueE falseE = + let trueE = getEvalExpr state trueE + let falseE = getEvalExpr state falseE + match getEvalExpr state condE with + | e when e = AST.b1 -> trueE + | e when e = AST.b0 -> falseE + | e -> AST.ite e trueE falseE + // FIXME: Do not assume EIP + |> evalPutVar state "EIP" + let private evalSideEff (state: State) = function | SysCall | Interrupt 0x80 -> let nEAX = - Undefined (32, List.length state.SysCall |> sprintf "EAX%d") + AST.undef 32 (List.length state.SysCall |> sprintf "EAX%d") |> Value { state with SysCall = state :: state.SysCall SideEff = true @@ -143,12 +160,12 @@ module State = | _ -> { state with SideEff = true } let evalStmt state stmt = - match stmt with + match stmt.S with | ISMark _ | IEMark _ | LMark _ -> state - | Put (Var (_, _, reg, _), value) -> evalPutVar state reg value - | Put (TempVar (_, reg), value) -> evalPutTemp state reg value + | Put ({ E = Var (_, _, reg, _) }, value) -> evalPutVar state reg value + | Put ({ E = TempVar (_, reg) }, value) -> evalPutTemp state reg value | Store (endian, addr, value) -> evalStore state endian addr value - | InterJmp (PCVar (_, pc), value, _) -> evalPutVar state pc value - | Stmt.SideEffect eff -> evalSideEff state eff - | e -> failwithf "evalStmt fail %A" e - + | CJmp (condE, trueE, falseE) -> evalCJmp state condE trueE falseE + | InterJmp (value, _) -> evalPutVar state "EIP" value + | SideEffect eff -> evalSideEff state eff + | e -> failwithf "evalStmt fail %A" e \ No newline at end of file diff --git a/src/ROP/Summary.fs b/src/RearEnd/ROP/Summary.fs similarity index 74% rename from src/ROP/Summary.fs rename to src/RearEnd/ROP/Summary.fs index d75e90a8..0e43f823 100644 --- a/src/ROP/Summary.fs +++ b/src/RearEnd/ROP/Summary.fs @@ -22,13 +22,13 @@ SOFTWARE. *) -namespace B2R2.ROP +namespace B2R2.RearEnd.ROP open B2R2 open B2R2.BinIR open B2R2.BinIR.LowUIR -open B2R2.FrontEnd -open B2R2.FrontEnd.Intel +open B2R2.FrontEnd.BinInterface +open B2R2.FrontEnd.BinLifter.Intel type Summary = { InRegs : Set @@ -46,33 +46,37 @@ module Summary = // FIXME let private ESP = - Var (32, Register.toRegID Register.ESP, "ESP", RegisterSet.empty) + let regID = Register.toRegID Register.ESP + AST.var 32 regID "ESP" (IntelRegisterSet.singleton regID) let private REGS = [| "EIP"; "ESP"; "EBP"; "EAX"; "EBX"; "ECX"; "EDX"; "ESI"; "EDI" |] let private syscallOutRegs = - Map.ofList [("EAX", Undefined (32, "EAX0") |> Value)] - - let rec getInput = function - | Var (_, _, n, _) -> (Set.empty.Add (n), Set.empty) - | TempVar (_, n) -> failwithf "getInput fail: T_%d" n - | UnOp (_, expr, _, _) -> getInput expr - | BinOp (_, _, lExpr, rExpr, _, _) | RelOp (_, lExpr, rExpr, _, _) -> - mergeInput (getInput lExpr) (getInput rExpr) - | Load (_, _, expr, _, _) -> - mergeInput (getInput expr) (Set.empty, Set.empty.Add (Value expr)) - | Ite (cExpr, tExpr, fExpr, _, _) -> - mergeInput (getInput cExpr) (getInput tExpr) - |> mergeInput (getInput fExpr) - | Cast (_, _, expr, _, _) -> getInput expr - | expr -> emptyInput // Num, Name, PCVar + Map.ofList [("EAX", AST.undef 32 "EAX0" |> Value)] + + let getInput (state: State) e = + let rec getInput e = + match e.E with + | Var (_, _, n, _) -> (Set.empty.Add (n), Set.empty) + | TempVar (_, n) -> getInput <| (Map.find n state.TempRegs).GetExpr () + | UnOp (_, expr, _) -> getInput expr + | BinOp (_, _, lExpr, rExpr, _) | RelOp (_, lExpr, rExpr, _) -> + mergeInput (getInput lExpr) (getInput rExpr) + | Load (_, _, expr, _) -> + mergeInput (getInput expr) (Set.empty, Set.empty.Add (Value expr)) + | Ite (cExpr, tExpr, fExpr, _) -> + mergeInput (getInput cExpr) (getInput tExpr) + |> mergeInput (getInput fExpr) + | Cast (_, _, expr, _) | Extract (expr, _, _, _) -> getInput expr + | _ -> emptyInput // Num, Name, PCVar + getInput e let private getInputAll state = Set.empty |> Map.foldBack (fun _ v acc -> Set.add v acc) state.Regs |> Map.foldBack (fun k v acc -> Set.add k acc |> Set.add v) state.Mems - |> Set.fold (fun acc v -> v.GetExpr () |> getInput |> mergeInput acc) + |> Set.fold (fun acc v -> v.GetExpr () |> getInput state |> mergeInput acc) emptyInput let rec private getSummary (state: State) = @@ -88,18 +92,19 @@ module Summary = if n % 4 = 0 && n >=0 then Some (n / 4) else None - let private getEspOff = function - | var when var = ESP -> Some 0 - | BinOp (BinOpType.ADD, 32, var, Num (n), _, _) - | BinOp (BinOpType.ADD, 32, Num (n), var, _, _) when var = ESP -> + let private getEspOff e = + match e.E with + | _ when e = ESP -> Some 0 + | BinOp (BinOpType.ADD, 32, var, { E = Num (n) }, _) + | BinOp (BinOpType.ADD, 32, { E = Num (n) }, var, _) when var = ESP -> calcOffset (BitVector.toInt32 n) - | BinOp (BinOpType.SUB, 32, var, Num (n), _, _) when var = ESP -> - calcOffset (-(BitVector.toInt32 n)) + | BinOp (BinOpType.SUB, 32, var, { E = Num (n) }, _) when var = ESP -> + calcOffset (- (BitVector.toInt32 n)) | _ -> None let private getStackOff (v: Value) = - match v.GetExpr () with - | Load (_, 32, expr, _, _) -> getEspOff expr + match v.GetExpr().E with + | Load (_, 32, expr, _) -> getEspOff expr | _ -> None let private getRegStackOff reg regs = @@ -121,13 +126,18 @@ module Summary = let private isStackMems = Set.forall isStackMem - let private isLinearExpr = function + let private isLinearExpr e = + match e.E with | Var (32, _, reg, _) -> Some (reg, 0u) - | BinOp (BinOpType.ADD, _, Var (32, _, reg, _), Num n, _, _) - | BinOp (BinOpType.ADD, _, Num n, Var (32, _, reg, _), _, _) -> + | BinOp (BinOpType.ADD, _, + { E = Var (32, _, reg, _) }, { E = Num n }, _) + | BinOp (BinOpType.ADD, _, + { E = Num n }, { E = Var (32, _, reg, _) }, _) -> Some (reg, BitVector.toUInt32 n) - | BinOp (BinOpType.SUB, _, Var (32, _, reg, _), Num n, _, _) - | BinOp (BinOpType.SUB, _, Num n, Var (32, _, reg, _), _, _) -> + | BinOp (BinOpType.SUB, _, + { E = Var (32, _, reg, _) }, { E = Num n }, _) + | BinOp (BinOpType.SUB, _, + { E = Num n }, { E = Var (32, _, reg, _) }, _) -> Some (reg, BitVector.neg n |> BitVector.toUInt32) | _ -> None @@ -145,11 +155,15 @@ module Summary = | _, _ -> None else None - let isSysCall (sum: Summary) = + let isSysCall = function + | Error _ -> false + | Ok sum -> sum.SideEff && sum.InRegs = Set.empty && sum.InMems = Set.empty && sum.OutRegs = syscallOutRegs && sum.OutMems = Map.empty - let isEspAdder min (sum: Summary) = + let isEspAdder min = function + | Error _ -> (false, None) + | Ok sum -> if not sum.SideEff && sum.OutMems = Map.empty && isStackMems sum.InMems then match Map.tryFind "EIP" (getRegsStackOff sum) with | Some eip -> @@ -178,12 +192,14 @@ module Summary = let private getLinearLoad reg (sum: Summary) = match Map.tryFind reg sum.OutRegs with | Some value -> - match value.GetExpr () with - | Load (_, _, addr, _, _) -> isLinearExpr addr + match value.GetExpr().E with + | Load (_, _, addr, _) -> isLinearExpr addr | _ -> None | _ -> None - let isSetter (sum: Summary) = + let isSetter = function + | Error _ -> (false, None) + | Ok sum -> if not sum.SideEff && sum.OutMems = Map.empty && isStackMems sum.InMems then let regMap = getRegsStackOff sum let regSet = getRegs sum.OutRegs |> Set.remove "ESP" @@ -197,7 +213,9 @@ module Summary = else (true, None) else (false, None) - let isMemWriter regs (sum: Summary) = + let isMemWriter regs = function + | Error _ -> (false, None) + | Ok sum -> if not sum.SideEff && isStackMems sum.InMems then match Map.tryFind "EIP" (getRegsStackOff sum), getMemWriter regs sum with | Some eip, Some writer -> (true, Some (eip, writer)) @@ -205,7 +223,9 @@ module Summary = | None, _ -> (false, None) else (false, None) - let isStackPivotor regs (sum: Summary) = + let isStackPivotor regs = function + | Error _ -> (false, None) + | Ok sum -> if not sum.SideEff then match getLinear "ESP" sum, getLinearLoad "EIP" sum with | Some (r, o), Some eip when r <> "ESP" && eip = (r, o - 4u) -> @@ -216,17 +236,19 @@ module Summary = let private checkRegs (sum: Summary) regs = let checker (reg, v) = match Map.tryFind reg sum.OutRegs with - | Some x when x = (BitVector.ofUInt32 v 32 |> Num |> Value) -> true + | Some x when x = (BitVector.ofUInt32 v 32 |> AST.num |> Value) -> + true | _ -> false Array.forall checker regs let private addNum32 (ptr: Value) num = - Num (BitVector.ofInt32 num 32) + BitVector.ofInt32 num 32 + |> AST.num |> Simplify.simplifyBinOp BinOpType.ADD 32 (ptr.GetExpr ()) |> Value let private toBytes (value: Value) = - match value.GetExpr () with + match value.GetExpr().E with | Num n -> (BitVector.getValue n).ToByteArray () |> Some | _ -> None @@ -255,7 +277,9 @@ module Summary = && readMemStr sum ebx |> System.IO.Path.GetFullPath = "/bin/sh" | None -> false - let isShellCode (sum: Summary) = + let isShellCode = function + | Error _ -> false + | Ok sum -> match sum.SysCall with | [sum] when checkShellCode sum -> true | _ -> false @@ -274,7 +298,7 @@ module Summary = let summary hdl gadget = gadget.Instrs - |> List.map (BinHandler.LiftInstr hdl) + |> List.map (BinHandle.LiftInstr hdl) |> Array.concat |> Array.fold (State.evalStmt) State.initState |> getSummary diff --git a/src/RearEnd/Repl/B2R2.RearEnd.Repl.fsproj b/src/RearEnd/Repl/B2R2.RearEnd.Repl.fsproj new file mode 100644 index 00000000..29cd0bfa --- /dev/null +++ b/src/RearEnd/Repl/B2R2.RearEnd.Repl.fsproj @@ -0,0 +1,28 @@ + + + + Exe + net5.0 + false + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Utilities/Repl/Main.fs b/src/RearEnd/Repl/Program.fs similarity index 84% rename from src/Utilities/Repl/Main.fs rename to src/RearEnd/Repl/Program.fs index cf879af4..a2e45c92 100644 --- a/src/Utilities/Repl/Main.fs +++ b/src/RearEnd/Repl/Program.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module B2R2.Utilities.Repl.Main +module B2R2.RearEnd.Repl.Program open B2R2 -open B2R2.FrontEnd -open B2R2.Assembler +open B2R2.FrontEnd.BinInterface +open B2R2.Peripheral.Assembly let cmds = [ "show" @@ -40,8 +40,8 @@ let assemble (state: ReplState) (asm: AsmInterface) (input: string) = match state.CurrentParser with | LowUIRParser -> true | _ -> false - try asm.AssembleLowUIR isLowUIRParser (input.Trim ()) - with exc -> printfn "%s" exc.Message; [||] + try asm.LiftLowUIR isLowUIRParser (input.Trim ()) + with exc -> Error exc.Message let rec run showTemporary (state: ReplState) asm = let input = console.ReadLine () @@ -56,15 +56,17 @@ let rec run showTemporary (state: ReplState) asm = Display.printRegisters showTemporary state [] run showTemporary state asm | StmtInput input -> - let stmts = assemble state asm input - if Array.isEmpty stmts then run showTemporary state asm - else + match assemble state asm input with + | Error msg -> + printfn "%s" msg + run showTemporary state asm + | Ok stmts -> let regdelta = state.Update stmts Display.printRegisters showTemporary state regdelta run showTemporary state asm let runRepl _args (opts: ReplOpts) = - let binhandler = BinHandler.Init (opts.ISA) + let binhandler = BinHandle.Init (opts.ISA) let state = ReplState (opts.ISA, binhandler.RegisterBay, not opts.Verbose) let asm = AsmInterface (opts.ISA, 0UL) Display.printBlue "Welcome to B2R2 REPL\n" @@ -74,4 +76,4 @@ let runRepl _args (opts: ReplOpts) = [] let main args = let opts = ReplOpts () - ReplOpts.ParseAndRun runRepl "" ReplOpts.spec opts args + ReplOpts.ParseAndRun runRepl "repl" "" ReplOpts.spec opts args diff --git a/src/Utilities/Repl/ReplCommand.fs b/src/RearEnd/Repl/ReplCommand.fs similarity index 98% rename from src/Utilities/Repl/ReplCommand.fs rename to src/RearEnd/Repl/ReplCommand.fs index ed6cbe29..a79f7229 100644 --- a/src/Utilities/Repl/ReplCommand.fs +++ b/src/RearEnd/Repl/ReplCommand.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.Utilities.Repl +namespace B2R2.RearEnd.Repl /// Supported repl commands. Other commands may be added here. type ReplCommand = diff --git a/src/Utilities/Repl/ReplDisplay.fs b/src/RearEnd/Repl/ReplDisplay.fs similarity index 98% rename from src/Utilities/Repl/ReplDisplay.fs rename to src/RearEnd/Repl/ReplDisplay.fs index e6e4abbd..32b9171e 100644 --- a/src/Utilities/Repl/ReplDisplay.fs +++ b/src/RearEnd/Repl/ReplDisplay.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module B2R2.Utilities.Repl.Display +module B2R2.RearEnd.Repl.Display open System diff --git a/src/Utilities/Repl/ReplOpts.fs b/src/RearEnd/Repl/ReplOpts.fs similarity index 97% rename from src/Utilities/Repl/ReplOpts.fs rename to src/RearEnd/Repl/ReplOpts.fs index eb4bec87..def2297b 100644 --- a/src/Utilities/Repl/ReplOpts.fs +++ b/src/RearEnd/Repl/ReplOpts.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -namespace B2R2.Utilities.Repl +namespace B2R2.RearEnd.Repl open B2R2 -open B2R2.Utilities +open B2R2.RearEnd type ReplOpts () = inherit CmdOpts () diff --git a/src/Utilities/Repl/ReplState.fs b/src/RearEnd/Repl/ReplState.fs similarity index 78% rename from src/Utilities/Repl/ReplState.fs rename to src/RearEnd/Repl/ReplState.fs index fb08931f..8873cd4d 100644 --- a/src/Utilities/Repl/ReplState.fs +++ b/src/RearEnd/Repl/ReplState.fs @@ -22,37 +22,38 @@ SOFTWARE. *) -namespace B2R2.Utilities.Repl +namespace B2R2.RearEnd.Repl open B2R2 open B2R2.BinIR -open B2R2.FrontEnd -open B2R2.ConcEval +open B2R2.BinIR.LowUIR +open B2R2.FrontEnd.BinLifter +open B2R2.MiddleEnd.ConcEval type ParserState = | LowUIRParser | BinParser of Architecture type ReplState (isa: ISA, regbay: RegisterBay, doFiltering) = + let rstate = EvalState () let mutable parser = BinParser isa.Arch - let mutable rstate = + do regbay.GetAllRegExprs () |> List.map (fun r -> - (regbay.RegIDFromRegExpr r, BitVector.ofInt32 0 (LowUIR.AST.typeOf r))) - |> List.map (fun (x, y) -> (x, Def y)) - |> EvalState.PrepareContext (EvalState ()) 0 0UL + (regbay.RegIDFromRegExpr r, BitVector.ofInt32 0 (TypeCheck.typeOf r))) + |> List.map (fun (x, y) -> (x, y)) + |> rstate.PrepareContext 0 0UL let mutable prevReg = - (EvalState.GetCurrentContext rstate).Registers.ToSeq () |> Seq.toArray + (rstate.GetCurrentContext ()).Registers.ToSeq () |> Seq.toArray let mutable prevTmp = - (EvalState.GetCurrentContext rstate).Temporaries.ToSeq () |> Seq.toArray + (rstate.GetCurrentContext ()).Temporaries.ToSeq () |> Seq.toArray let generalRegs = regbay.GetGeneralRegExprs () |> List.map regbay.RegIDFromRegExpr |> Set.ofList - member private __.EvaluateStmts (stmts: LowUIR.Stmt []) = - stmts - |> Array.fold (fun rstate stmt -> Evaluator.evalStmt rstate stmt) rstate + member private __.EvaluateStmts (stmts: Stmt []) = + stmts |> Array.iter (fun stmt -> Evaluator.evalStmt rstate stmt) member private __.ComputeDelta prev curr = Array.fold2 (fun acc t1 t2 -> @@ -61,9 +62,9 @@ type ReplState (isa: ISA, regbay: RegisterBay, doFiltering) = /// Update the state and return deltas. member __.Update stmts = - try rstate <- __.EvaluateStmts stmts + try __.EvaluateStmts stmts with exc -> printfn "%s" exc.Message - let currContext = EvalState.GetCurrentContext rstate + let currContext = rstate.GetCurrentContext () let currReg = currContext.Registers.ToSeq () |> Seq.toArray let currTmp = currContext.Temporaries.ToSeq () |> Seq.toArray let regdelta = __.ComputeDelta prevReg currReg @@ -71,11 +72,6 @@ type ReplState (isa: ISA, regbay: RegisterBay, doFiltering) = prevTmp <- currTmp regdelta - member private __.EvalValueToString v = - match v with - | Def bv -> bv.ToString () - | Undef -> "undef" - member private __.Filter regPairs = if doFiltering then regPairs @@ -89,12 +85,12 @@ type ReplState (isa: ISA, regbay: RegisterBay, doFiltering) = |> __.Filter |> List.map (fun (r, v) -> let regStr = regbay.RegIDToString r - let regVal = __.EvalValueToString v + let regVal = v.ToString () regStr + ": " + regVal, Set.contains r set) /// Gets a temporary register name and EvalValue string representation. member private __.TempRegString (n: int) v = - "T_" + string (n) + ": " + (__.EvalValueToString v) + "T_" + string (n) + ": " + v.ToString () member __.GetAllTempValString delta = let set = Set.ofList delta diff --git a/src/Visualization/B2R2.Visualization.fsproj b/src/RearEnd/Visualization/B2R2.RearEnd.Visualization.fsproj similarity index 68% rename from src/Visualization/B2R2.Visualization.fsproj rename to src/RearEnd/Visualization/B2R2.RearEnd.Visualization.fsproj index 8e689c48..41442ba2 100644 --- a/src/Visualization/B2R2.Visualization.fsproj +++ b/src/RearEnd/Visualization/B2R2.RearEnd.Visualization.fsproj @@ -1,9 +1,8 @@ - + - netstandard2.1 + net5.0 false - false @@ -22,13 +21,12 @@ - - - + - + + diff --git a/src/Visualization/CoordAssignment.fs b/src/RearEnd/Visualization/CoordAssignment.fs similarity index 99% rename from src/Visualization/CoordAssignment.fs rename to src/RearEnd/Visualization/CoordAssignment.fs index 6ea05290..9b2a3e3e 100644 --- a/src/Visualization/CoordAssignment.fs +++ b/src/RearEnd/Visualization/CoordAssignment.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -module internal B2R2.Visualization.CoordAssignment +module internal B2R2.RearEnd.Visualization.CoordAssignment open System open System.Collections.Generic -open B2R2.BinGraph +open B2R2.MiddleEnd.BinGraph type VDirection = | Topmost diff --git a/src/Visualization/CrossMinimization.fs b/src/RearEnd/Visualization/CrossMinimization.fs similarity index 98% rename from src/Visualization/CrossMinimization.fs rename to src/RearEnd/Visualization/CrossMinimization.fs index 0ce7f1cc..7faf892c 100644 --- a/src/Visualization/CrossMinimization.fs +++ b/src/RearEnd/Visualization/CrossMinimization.fs @@ -22,9 +22,9 @@ SOFTWARE. *) -module internal B2R2.Visualization.CrossMinimization +module internal B2R2.RearEnd.Visualization.CrossMinimization -open B2R2.BinGraph +open B2R2.MiddleEnd.BinGraph type VLayout = Vertex [][] diff --git a/src/Visualization/CycleRemoval.fs b/src/RearEnd/Visualization/CycleRemoval.fs similarity index 72% rename from src/Visualization/CycleRemoval.fs rename to src/RearEnd/Visualization/CycleRemoval.fs index b40e2579..07176c0e 100644 --- a/src/Visualization/CycleRemoval.fs +++ b/src/RearEnd/Visualization/CycleRemoval.fs @@ -22,9 +22,9 @@ SOFTWARE. *) -module internal B2R2.Visualization.CycleRemoval +module internal B2R2.RearEnd.Visualization.CycleRemoval -open B2R2.BinGraph +open B2R2.MiddleEnd.BinGraph let private collectSelfCycle backEdgeList src dst edge = if VisGraph.getID src = VisGraph.getID dst then (* Definition of self cycle *) @@ -33,19 +33,16 @@ let private collectSelfCycle backEdgeList src dst edge = else backEdgeList let private collectBackEdge (vGraph: VisGraph) order backEdgeList src dst edge = - if Map.find src order > Map.find dst order then // BackEdge + if Map.find src order > Map.find dst order then (* BackEdge *) + (edge: VisEdge).IsBackEdge <- true match vGraph.TryFindEdgeData dst src with - | Some _ -> // exist opposite edges - (edge: VisEdge).IsBackEdge <- true - (src, dst, edge, false) :: backEdgeList - | None -> // single backedge - edge.IsBackEdge <- true - (src, dst, edge, true) :: backEdgeList + | Some _ -> (src, dst, edge, false) :: backEdgeList + | None -> (src, dst, edge, true) :: backEdgeList else backEdgeList -let removeBackEdge (vGraph: VisGraph) (src, dst, edge, addReverse) = +let removeBackEdge (vGraph: VisGraph) src dst edge needToAddReverse = vGraph.RemoveEdge src dst |> ignore - if addReverse then vGraph.AddEdge dst src edge |> ignore + if needToAddReverse then vGraph.AddEdge dst src edge |> ignore let private dfsCollectBackEdges vGraph roots backEdgeList = let _, orderMap = @@ -54,8 +51,8 @@ let private dfsCollectBackEdges vGraph roots backEdgeList = vGraph.FoldEdge (collectBackEdge vGraph orderMap) backEdgeList let removeCycles (vGraph: VisGraph) roots = - let backEdgeList = - vGraph.FoldEdge collectSelfCycle [] - |> dfsCollectBackEdges vGraph roots - backEdgeList |> List.iter (removeBackEdge vGraph) - backEdgeList |> List.map (fun (src, dst, edge, _) -> (src, dst, edge)) + vGraph.FoldEdge collectSelfCycle [] + |> dfsCollectBackEdges vGraph roots + |> List.map (fun (src, dst, edge, needToAddReverse) -> + removeBackEdge vGraph src dst edge needToAddReverse + (src, dst, edge)) diff --git a/src/RearEnd/Visualization/EdgeDrawing.fs b/src/RearEnd/Visualization/EdgeDrawing.fs new file mode 100644 index 00000000..005b9466 --- /dev/null +++ b/src/RearEnd/Visualization/EdgeDrawing.fs @@ -0,0 +1,604 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +/// A modified version of Gasner et al. +module internal B2R2.RearEnd.Visualization.EdgeDrawing + +open B2R2 +open B2R2.MiddleEnd.BinGraph + +/// Very simple Box record consisting of four corner points. +type private Box = { + TopLeft: VisPosition + TopRight: VisPosition + BottomLeft: VisPosition + BottomRight: VisPosition + IsVirtual: bool +} + +/// An intersecting line between two boxes. +type private Line = { + Left: VisPosition + Right: VisPosition +} + +/// Categorized edges. +type private PartitionedEdges = { + ForwardEdges: VisEdge list + BackEdgesFromLeft: VisEdge list + BackEdgesFromRight: VisEdge list + SelfLoops: VisEdge list +} + +let private emptyPartitionedEdges = + { ForwardEdges = [] + BackEdgesFromLeft = [] + BackEdgesFromRight = [] + SelfLoops = [] } + +/// The X offset between starting points of two adjacent edges. +let [] private edgeOffsetX = 4.0 + +/// The Y offset between starting points of two adjacent edges. +let [] private edgeOffsetY = 4.0 + +/// The length of the last segment of an edge. This value should be at least +/// less than the half of blockIntervalY. +let [] private lastSegLen = 20.0 + +/// An offset from a node to the surrounding box. This is to give some margin +/// for the box. +let [] private nodeBoxOffset = 20.0 + +/// The margin to prevent an overlap between a node and its back edges. +let [] private backEdgeMargin = 10.0 + +/// A margin for deciding line fitness. +let [] private fitErrorMargin = 1.0 + +/// If the number of incoming/outgoing edges of a layer exceeds this threshold, +/// then we expand the layer's height. +let [] private layerHeightExpansionThreshold = 15 + +let inline private isDummy (v: Vertex) = v.VData.IsDummy + +let private restoreBackEdge (g: VisGraph) (src, dst, edge: VisEdge) = + match g.TryFindEdgeData dst src with + | Some eData when eData.IsBackEdge -> g.RemoveEdge dst src |> ignore + | _ -> () + g.AddEdge src dst edge |> ignore + +let private restoreBackEdges g backEdgeList = + List.iter (restoreBackEdge g) backEdgeList + +/// Compute the original destination vertex, given dummy source node src. +let rec private getOriginalDst (v: Vertex) = + if isDummy v then getOriginalDst (List.head v.Succs) + else v + +/// Given src is original, add original edge to acc. +let private accOriginalEdge acc src dst (edge: VisEdge) = + if isDummy src then acc + elif isDummy dst then (src, getOriginalDst dst, edge ) :: acc + else (src, dst, edge) :: acc + +/// Sort vertices by the x-coordinates. +let private sortLayers vLayout = + vLayout |> Array.map (fun layer -> + Array.sortBy (fun v -> (VisGraph.getXPos v)) layer) + +let private countDegree edges (getter: 'a -> Vertex) v = + edges + |> List.fold (fun cnt e -> if getter e = v then cnt + 1 else cnt) 0 + +let private getMaxDegree edges getter layer = + layer + |> Array.map (countDegree edges getter) + |> Array.max + +let private downShiftLayers layers degree = + Array.iter (Array.iter (fun (v: Vertex) -> + let vData = v.VData + let newY = vData.Coordinate.Y + edgeOffsetY * float degree + vData.Coordinate.Y <- newY)) layers + +let rec private adjustLayers isIncoming layerNum vLayout = function + | [] -> () + | degree :: tl -> + if degree >= layerHeightExpansionThreshold then + let shiftStart = if isIncoming then layerNum else layerNum + 1 + if shiftStart < Array.length vLayout then + downShiftLayers vLayout.[ shiftStart .. ] degree + else () + else () + adjustLayers isIncoming (layerNum + 1) vLayout tl + +/// Expand a layer's height if it contains excessive number of incoming/outgoing +/// edges. +let private adjustLayerYPositions edges vLayout = + let maxIncomingDegrees = + vLayout |> Array.map (getMaxDegree edges Utils.tripleSnd) |> Array.toList + let maxOutgoingDegrees = + vLayout |> Array.map (getMaxDegree edges Utils.tripleFst) |> Array.toList + adjustLayers true 0 vLayout maxIncomingDegrees + adjustLayers false 0 vLayout maxOutgoingDegrees + +let private getEntryPoint (v: Vertex) = + let x, y = VisGraph.getXPos v, VisGraph.getYPos v + (x + VisGraph.getWidth v / 2.0), (y + VisGraph.getHeight v) + +let private getExitPoint (v: Vertex) = + let x, y = VisGraph.getXPos v, VisGraph.getYPos v + (x + VisGraph.getWidth v / 2.0), y + +let private makeVisPos (x, y): VisPosition = { X = x; Y = y } + +let private makeBox left right top bottom isVirtual = + { TopLeft = makeVisPos (left, top); + TopRight = makeVisPos (right, top); + BottomLeft = makeVisPos (left, bottom); + BottomRight = makeVisPos (right, bottom); + IsVirtual = isVirtual } + +let private makeDummyBox () = makeBox 0.0 0.0 0.0 0.0 true + +/// Convert a Vertex into a Box. +let private vertexToBox (v: Vertex): Box = + let left = VisGraph.getXPos v - if (isDummy v) then 0.0 else nodeBoxOffset + let right = + (VisGraph.getXPos v + VisGraph.getWidth v + * if (isDummy v) then 0.5 else 1.0) + + if (isDummy v) then 0.0 else nodeBoxOffset + let top = VisGraph.getYPos v - nodeBoxOffset + let bottom = (VisGraph.getYPos v + VisGraph.getHeight v) + nodeBoxOffset + makeBox left right top bottom (isDummy v) + +/// Converts vertex arrays to Box arrays. +let private verticesToBoxes1D vertices = + Array.map vertexToBox vertices + +let private verticesToBoxes2D vLayout = + Array.map verticesToBoxes1D vLayout + +let private makeLine left right y = + { Left = makeVisPos (left, y); Right = makeVisPos (right, y) } + +let private makeDummyLine () = + { Left = makeVisPos (-10000.0, 0.0); Right = makeVisPos (-10000.0, 0.0) } + +/// Get intersection line segment between two neighbouring boxes. +let private getIntersection upper lower = + let upperBottom, lowerTop = upper.BottomLeft.Y, lower.TopLeft.Y + if int upperBottom <> int lowerTop then makeDummyLine () + else + let left = max (upper.BottomLeft.X) (lower.TopLeft.X) + let right = min (upper.BottomRight.X) (lower.BottomRight.X) + makeLine left right upperBottom + +let private getIntersectingLines boxes = + let rec aux acc (hd: Box) (tl: Box list) = + match tl with + | [] -> + List.rev ((makeLine hd.TopLeft.X hd.TopRight.X hd.BottomLeft.Y) :: acc) + | th :: tt -> aux ((getIntersection hd th) :: acc) th tt + match boxes with + | hd :: tl -> + (makeLine hd.TopLeft.X hd.TopRight.X hd.TopLeft.Y) :: (aux [] hd tl) + | _ -> Utils.impossible () + +let private getBasicComponents vLayout boxes (v: Vertex) = + let layer = VisGraph.getLayer v + let nth = Array.findIndex ((=) v) (vLayout: Vertex [][]).[layer] + let boxarr = (boxes: Box [][]).[layer] + let box = boxes.[layer].[nth] + struct (layer, boxarr, box) + +let private computeLayerDiff q r = + abs (VisGraph.getLayer r - VisGraph.getLayer q) + +let private findDummies q r (edge: VisEdge) dummyMap = + match (Map.tryFind (q, r) dummyMap) with + | Some (_, dummies) -> + if edge.IsBackEdge then List.rev dummies, false + else dummies, false + | None -> + if not edge.IsBackEdge || (computeLayerDiff q r) = 1 then [], false + else (* Dummy node deleted. Refer to existing forward edge. *) + match Map.tryFind (r, q) dummyMap with + | Some (_, dummies) -> dummies, true + | None -> [], false + +let private computeBoxHeight (box: Box) = + box.BottomLeft.Y - box.TopLeft.Y + +let private computeLayerHeight layer = + Array.map computeBoxHeight layer |> Array.max + +let private computeHeightPerLayer boxes = + Array.map computeLayerHeight boxes + +/// Computes starting and ending y-coordinates for each layer. +let private computeYPositionsPerLayer boxes = + let heights = computeHeightPerLayer boxes + let starts = Array.map (fun (layer: Box []) -> layer.[0].TopLeft.Y) boxes + let ends = Array.map2 (+) starts heights + Array.map2 (fun x y -> (x, y)) starts ends + +/// Given vertex boxes, return two x-coordinates defining the width line of the +/// graph. +let private computeWidthLine boxes = + let lefts = Array.map (Array.map (fun b -> b.TopLeft.X)) boxes + let rights = Array.map (Array.map (fun b -> b.TopRight.X)) boxes + let leftmost = Array.min (Array.concat lefts) + let rightmost = Array.max (Array.concat rights) + leftmost, rightmost + +/// Return a list of layers between q (qLayer) and r (rLayer). +let getLayersBetween (dummies: Vertex list) qLayer rLayer = + if dummies.IsEmpty then [ (min qLayer rLayer) ] + else [ (min qLayer rLayer) .. (max qLayer rLayer) - 1 ] + +/// Assume leftBox is on the left of rightBox, check if those two boxes overlap. +let private boxesOverlapping leftBox rightBox = + let left1, right1 = leftBox.TopLeft.X, leftBox.TopRight.X + let left2, _ = rightBox.TopLeft.X, rightBox.TopRight.X + left2 >= left1 && left2 <= right1 + +let rec private getBoxLeftBound reference index (boxarr: Box []) widthLine = + match index with + | i when i < 0 -> fst widthLine + | i -> + if not (boxesOverlapping boxarr.[i] boxarr.[reference]) + || (reference <> i && not (boxarr.[i].IsVirtual)) + then boxarr.[i].TopRight.X + else getBoxLeftBound reference (i - 1) boxarr widthLine + +let rec private getBoxRightBound reference index (boxarr: Box []) widthLine = + match index with + | i when i > (Array.length boxarr) - 1 -> snd widthLine + | i -> + if not (boxesOverlapping boxarr.[reference] boxarr.[i]) + || (reference <> i && not (boxarr.[i].IsVirtual)) + then boxarr.[i].TopLeft.X + else getBoxRightBound reference (i + 1) boxarr widthLine + +let private initialBox box (boxarr: Box []) widthLine (_, bottom) = + let idx = Array.findIndex ((=) box) boxarr + let left = getBoxLeftBound idx idx boxarr widthLine + let right = getBoxRightBound idx idx boxarr widthLine + let top = box.BottomLeft.Y + makeBox left right top bottom true + +/// Computes an inter-layer Box right under given layerNum. +let private interLayerBox yPositions (left, right) layerNum = + if layerNum >= Array.length yPositions - 1 then makeDummyBox () + else + let top = yPositions.[layerNum] |> snd + let bottom = yPositions.[layerNum + 1] |> fst + makeBox left right top bottom true + +/// Computes a box corresponding to a particular dummy node. +let private virtualNodeBox boxes widthLine (yPositions: _ []) shrinkBox dummy = + let dBox = dummy |> vertexToBox + let dRow = Array.findIndex (Array.contains dBox) boxes + let boxarr = boxes.[dRow] + let dCol = Array.findIndex ((=) dBox) boxarr + let left = getBoxLeftBound dCol dCol boxarr widthLine + let right = getBoxRightBound dCol dCol boxarr widthLine + let top = yPositions.[dRow] |> fst + let bottom = yPositions.[dRow] |> snd + let delta = (right - left) / 3.0 + if shrinkBox then makeBox (left + delta) (right - delta) top bottom true + else makeBox left right top bottom true + +let private nodeIsLeft (q: Vertex) (r: Vertex) = + let qx, rx = VisGraph.getXPos q, VisGraph.getXPos r + qx + 1.5 * (VisGraph.getWidth q) < rx + +let private centerX (box: Box) = + box.TopLeft.X + (box.TopRight.X - box.TopLeft.X) / 2.0 + +let private boxIsLeft b1 b2 = centerX b1 < centerX b2 + +/// Compute tuple of (distance between q-r line and the line segment, left +/// endpoint is closer or not). +let private lineFits (q: VisPosition) (r: VisPosition) line = + let left, right = line.Left, line.Right + let qx, qy, rx, ry = q.X, q.Y, r.X, r.Y + let dy = (ry - qy) + let m = (rx - qx) / dy + let x = qx + m * (left.Y - qy) + let xFits = (x >= left.X - fitErrorMargin && x <= right.X + fitErrorMargin) + if xFits || (abs dy) < 0.1 then (-1, false) + else + if x < left.X then abs (int (x - left.X)), true + else abs (int (x - right.X)), false + +let private getLineFitArray lArray (q: VisPosition) (r: VisPosition) = + Array.map (lineFits q r) lArray + +let rec private computePList (interLines: Line array) q r = + let fitTupleArray = getLineFitArray interLines q r + let furthestLineIndex = + fitTupleArray + |> Array.mapi (fun i v -> i, v) + |> Array.maxBy (fun (_, (dist, _)) -> dist) + |> fst + let farthestDist, isAtLeft = fitTupleArray.[furthestLineIndex] + let splitLine = interLines.[furthestLineIndex] + if farthestDist > 0 then + let p = if isAtLeft then splitLine.Left else splitLine.Right + let slice1 = interLines.[ .. furthestLineIndex ] + let slice2 = interLines.[ furthestLineIndex .. ] + let segment1 = (computePList slice1 q p) + let segment2 = (computePList slice2 p r) + segment1 @ (p :: segment2) + else [] + +let private computeRegularEdgePoints isBackEdge dummies boxes q r qBox rBox = + let intersectingLines = getIntersectingLines boxes + let tailQ, headR = getEntryPoint q, getExitPoint r (* Key points *) + let q1 = makeVisPos (fst tailQ, snd tailQ) + let q2 = { q1 with Y = q1.Y + nodeBoxOffset } + let r1 = makeVisPos (fst headR, snd headR) + let r2 = { r1 with Y = r1.Y - nodeBoxOffset } + let qWidth = VisGraph.getWidth q + if isBackEdge then + let dummyBoxes = dummies |> Array.ofList |> Array.map vertexToBox + let n = Array.length dummyBoxes + let departLeft, arriveLeft = + if n < 1 then nodeIsLeft r q, nodeIsLeft q r + else boxIsLeft dummyBoxes.[ n - 1 ] qBox, boxIsLeft dummyBoxes.[0] rBox + let q3 = + { q2 with X = q2.X + 0.55 * qWidth * if departLeft then -1.0 else 1.0 } + let r3 = + { r2 with X = r2.X + 0.55 * qWidth * if arriveLeft then -1.0 else 1.0 } + let q4 = { q3 with Y = qBox.TopLeft.Y } + let r4 = { r3 with Y = rBox.BottomLeft.Y } + [ q1; q2; q3; q4 + yield! (computePList (Array.ofList intersectingLines) r4 q4 |> List.rev) + r4; r3; r2; r1 ] + else + [ q1; q2 + yield! (computePList (intersectingLines |> Array.ofList) q2 r2) + r2; r1 ] + +/// Draw a regular edge from q to r. +let private drawRegular g vLayout boxes dummyMap (q, r, edge: VisEdge) = + let isBackEdge = edge.IsBackEdge + let struct (qLayer, qBoxArr, qBox) = getBasicComponents vLayout boxes q + let struct (rLayer, rBoxArr, rBox) = getBasicComponents vLayout boxes r + let dummies, isRecovered = findDummies q r edge dummyMap + let yPositions = computeYPositionsPerLayer boxes + let wLine = computeWidthLine boxes + let interLayers = getLayersBetween dummies qLayer rLayer + let initBox = + if isBackEdge then initialBox rBox rBoxArr wLine yPositions.[rLayer] + else initialBox qBox qBoxArr wLine yPositions.[qLayer] + let interLayerBoxes = List.map (interLayerBox yPositions wLine) interLayers + let virtualNodeBoxes = + List.map (virtualNodeBox boxes wLine yPositions isRecovered) dummies + let boxes = (* Boxes between nodes q and r, from upper layer to lower *) + initBox :: + ((List.fold2 (fun acc v i -> i :: v :: acc) [interLayerBoxes.Head] + virtualNodeBoxes interLayerBoxes.Tail) |> List.rev) + let points = computeRegularEdgePoints isBackEdge dummies boxes q r qBox rBox + match (g: VisGraph).TryFindEdgeData q r with + | None -> (* Imaginary edges for display purposes only *) + let newEdge = VisEdge (edge.Type) + newEdge.IsBackEdge <- isBackEdge + newEdge.Points <- points + g.AddEdge q r newEdge |> ignore + | Some e -> e.Points <- points + +let private drawSelfLoop g (v: Vertex) = + let nodeWidth = VisGraph.getWidth v + let eData = (g: VisGraph).FindEdgeData v v + let startP, endP = getEntryPoint v, getExitPoint v + let p1 = (fst startP), (snd startP + lastSegLen) + let p2 = ((fst p1) + nodeWidth / 2.0 + backEdgeMargin), (snd p1) + let p3 = (fst p2), (snd endP) - lastSegLen + let p4 = (fst endP), snd p3 + let points = [ startP; p1; p2; p3; p4; endP ] |> List.map makeVisPos + eData.Points <- points + +let private drawBoxes g vLayout boxes dummyMap (src, dst, edge) = + if isDummy src || isDummy dst then () + elif src = dst then drawSelfLoop g src + else drawRegular g vLayout boxes dummyMap (src, dst, edge) + +let rec private removeDummyLoop (g: VisGraph) src dst points = function + | dummy :: rest -> + let eData = g.FindEdgeData src dummy + g.RemoveEdge src dummy |> ignore + removeDummyLoop g dummy dst (points @ eData.Points) rest + | [] -> + let eData = g.FindEdgeData src dst + g.RemoveEdge src dst |> ignore + points @ eData.Points + +let private makeSmooth isBack points = + let rec loop acc prev = function + | [] -> acc + | h1 :: h2 :: [] -> List.rev (h2 :: h1 :: acc) + | (hd: VisPosition) :: tl -> + match prev with + | None -> loop (hd :: acc) (Some hd.Y) tl + | Some p -> + if (isBack && p >= hd.Y) || (not isBack && p <= hd.Y) then + loop (hd :: acc) (Some hd.Y) tl + else loop acc prev tl + match points with + | hd1 :: hd2 :: rest -> hd1 :: hd2 :: loop [] None rest + | _ -> points + +let private removeDummy g (src, dst) ((edge: VisEdge), dummies) = + let pts = removeDummyLoop g src dst [] dummies |> makeSmooth edge.IsBackEdge + let newEdge = VisEdge (edge.Type) + newEdge.IsBackEdge <- edge.IsBackEdge + newEdge.Points <- pts + g.AddEdge src dst newEdge |> ignore + dummies |> List.iter (fun (v: Vertex<_>) -> g.RemoveVertex v |> ignore) + +let private categorizeEdge isHeadPort acc (q, r, edge: VisEdge) = + let points = edge.Points |> Array.ofList + let n = Array.length points + if n < 4 then acc + else + if q = r then { acc with SelfLoops = edge :: acc.SelfLoops } + elif edge.IsBackEdge then + let p1Index, p2Index = if isHeadPort then n - 2, n - 3 else 1, 2 + if points.[p2Index].X < points.[p1Index].X then + { acc with BackEdgesFromLeft = edge :: acc.BackEdgesFromLeft } + else { acc with BackEdgesFromRight = edge :: acc.BackEdgesFromRight } + else { acc with ForwardEdges = edge :: acc.ForwardEdges } + +/// Compute the slope of the given vector q -> r under an assumption: the vector +/// always directed downwards (q.Y < r.Y). +let private computeSlope (q: VisPosition) (r: VisPosition) = + let qx, qy, rx, ry = q.X, q.Y, r.X, r.Y + let dy = (ry - qy) + if abs dy < 0.1 then (* Approximately horizontal line. *) + if qx < rx then infinity else -infinity + else (* Non-horizontal slope. *) (rx - qx) / dy + +let private getEdgeSlope isBackEdge isHeadPort (edge: VisEdge) = + let points = edge.Points |> Array.ofList + let n = Array.length points + let qIndex, rIndex = + match isBackEdge, isHeadPort with + | true, true -> n - 4, n - 5 + | true, false -> 4, 3 + | false, true -> n - 3, n - 2 + | false, false -> 1, 2 + computeSlope points.[qIndex] points.[rIndex] + +let private sortPartitions isHead descending p = + let sort = if descending then List.sortByDescending else List.sortBy + { ForwardEdges = sort (getEdgeSlope false isHead) p.ForwardEdges + BackEdgesFromLeft = sort (getEdgeSlope true isHead) p.BackEdgesFromLeft + BackEdgesFromRight = sort (getEdgeSlope true isHead) p.BackEdgesFromRight + SelfLoops = sort (getEdgeSlope true isHead) p.SelfLoops } + +let rec private shiftHorizontally toLeft (edges: VisEdge list) offset = + match edges with + | [] -> () + | edge :: rest -> + let points = edge.Points |> Array.ofList + let n = Array.length points + points.[ n - 3 ].X <- points.[ n - 3 ].X + offset + points.[ n - 4 ].X <- points.[ n - 4 ].X + offset + let nextOffset = offset + if toLeft then -edgeOffsetX else edgeOffsetX + shiftHorizontally toLeft rest nextOffset + +let private splitAux isHeadPort edge = + if not isHeadPort then getEdgeSlope false false edge > 0.0 + else getEdgeSlope false true edge < 0.0 + +let rec private splitEdgeList isHeadPort edges = + let edgeArray = Array.ofList edges + match Array.tryFindIndex (splitAux isHeadPort) edgeArray with + | None -> edges, [] + | Some v -> + let left, right = Array.splitAt v edgeArray + List.ofArray left, List.ofArray right + +let private partitionsToMergedList partition = + partition.BackEdgesFromLeft + @ partition.ForwardEdges + @ partition.BackEdgesFromRight + @ partition.SelfLoops + +let private offsetX center i = float (i - center) * edgeOffsetX + +let private shiftSegments isHeadPort (edge: VisEdge) offset = + let pts = edge.Points |> Array.ofList + let n = Array.length pts + let i1, i2 = + match edge.IsBackEdge, isHeadPort with + | true, true -> n - 2, n - 1 + | true, false -> 0, 1 + | false, true -> n - 2, n - 1 + | false, false -> 0, 1 + pts.[i1].X <- pts.[i1].X + offset + pts.[i2].X <- pts.[i2].X + offset + +let rec private shiftVertically isHeadPort offset = function + | [] -> () + | (edge: VisEdge) :: rest -> + let pts = edge.Points |> Array.ofList + if isHeadPort then + let n = Array.length pts + pts.[n - 2].Y <- pts.[n - 2].Y + offset + if edge.IsBackEdge then pts.[n - 3].Y <- pts.[n - 3].Y + offset else () + else + pts.[1].Y <- pts.[1].Y + offset + if edge.IsBackEdge then pts.[2].Y <- pts.[2].Y + offset else () + let offset = offset + (if isHeadPort then -edgeOffsetY else edgeOffsetY) + shiftVertically isHeadPort offset rest + +/// Give some offsets to each neighboring edge of v. +let private giveOffsets (g: VisGraph) (v: Vertex) = + let incoming = v.Preds |> List.map (fun p -> p, v, g.FindEdgeData p v) + let outgoing = v.Succs |> List.map (fun s -> v, s, g.FindEdgeData v s) + let ins = + List.fold (categorizeEdge true) emptyPartitionedEdges incoming + |> sortPartitions true true + let outs = + List.fold (categorizeEdge false) emptyPartitionedEdges outgoing + |> sortPartitions false false + shiftHorizontally true ins.BackEdgesFromLeft 0.0 + shiftHorizontally true outs.BackEdgesFromLeft 0.0 + shiftHorizontally false (List.rev ins.BackEdgesFromRight) 0.0 + shiftHorizontally false (List.rev outs.BackEdgesFromRight) 0.0 + let inFwdFromLeft, inFwdFromRight = splitEdgeList true ins.ForwardEdges + let outFwdToLeft, outFwdToRight = splitEdgeList false outs.ForwardEdges + let incomingFromLeft, incomingFromRight = + ins.BackEdgesFromLeft @ inFwdFromLeft, + inFwdFromRight @ ins.BackEdgesFromRight @ ins.SelfLoops + let outgoingToLeft, outgoingToRight = + outs.BackEdgesFromLeft @ outFwdToLeft, + outFwdToRight @ outs.BackEdgesFromRight @ outs.SelfLoops + let incomingMerged = partitionsToMergedList ins + let outGoingMerged = partitionsToMergedList outs + let iCenter = (List.length incomingMerged) / 2 + let oCenter = (List.length outGoingMerged) / 2 + let headOffsets = List.mapi (fun i _ -> offsetX iCenter i) incomingMerged + let tailOffsets = List.mapi (fun i _ -> offsetX oCenter i) outGoingMerged + List.iter2 (shiftSegments true) incomingMerged headOffsets + List.iter2 (shiftSegments false) outGoingMerged tailOffsets + shiftVertically true 0.0 incomingFromLeft + shiftVertically true 0.0 (incomingFromRight |> List.rev) + shiftVertically false 0.0 outgoingToLeft + shiftVertically false 0.0 (outgoingToRight |> List.rev) + +let drawEdges (g: VisGraph) vLayout backEdgeList dummyMap = + restoreBackEdges g backEdgeList + let originalEdgeList = g.FoldEdge accOriginalEdge [] + let vLayoutSorted = sortLayers vLayout + adjustLayerYPositions originalEdgeList vLayoutSorted + let boxes = verticesToBoxes2D vLayoutSorted + List.iter (drawBoxes g vLayoutSorted boxes dummyMap) originalEdgeList + Map.iter (removeDummy g) dummyMap + g.IterVertex (giveOffsets g) diff --git a/src/Visualization/JSONExport.fs b/src/RearEnd/Visualization/JSONExport.fs similarity index 95% rename from src/Visualization/JSONExport.fs rename to src/RearEnd/Visualization/JSONExport.fs index ca4d8c40..fba134fa 100644 --- a/src/Visualization/JSONExport.fs +++ b/src/RearEnd/Visualization/JSONExport.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -namespace B2R2.Visualization +namespace B2R2.RearEnd.Visualization open B2R2 -open B2R2.FrontEnd -open B2R2.BinGraph -open B2R2.BinEssence +open B2R2.FrontEnd.BinLifter +open B2R2.MiddleEnd.BinGraph +open B2R2.MiddleEnd.ControlFlowGraph open Microsoft.FSharpLu.Json type JSONCoordinate = { diff --git a/src/RearEnd/Visualization/LayerAssignment.fs b/src/RearEnd/Visualization/LayerAssignment.fs new file mode 100644 index 00000000..8133d8ff --- /dev/null +++ b/src/RearEnd/Visualization/LayerAssignment.fs @@ -0,0 +1,98 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.RearEnd.Visualization.LayerAssignment + +open B2R2.MiddleEnd.BinGraph + +let assignLayerFromPred (vGraph: VisGraph) vData = + let v = vGraph.FindVertexByData vData + let preds = VisGraph.getPreds vGraph v + match preds with + | [] -> VisGraph.setLayer v 0 + | preds -> + let predLayers = List.map VisGraph.getLayer preds + VisGraph.setLayer v <| List.max predLayers + 1 + +let kahnAssignLayers (vGraph: VisGraph) = + Traversal.foldTopologically vGraph [] (fun acc v -> v.VData :: acc) [] + |> List.rev + |> List.iter (assignLayerFromPred vGraph) + +let rec addDummy (g: VisGraph) (backEdges, dummies) k src dst (e: VisEdge) cnt = + if cnt = 0 then + let edge = VisEdge (e.Type) + edge.IsBackEdge <- e.IsBackEdge + g.AddEdge src dst edge |> ignore + let backEdges = + if edge.IsBackEdge then (dst, src, edge) :: backEdges else backEdges + backEdges, dummies + else + let vNode = VisBBlock (src.VData, true) + let dummy, _ = g.AddVertex (vNode) + VisGraph.setLayer dummy <| VisGraph.getLayer src + 1 + let edge = VisEdge (e.Type) + edge.IsBackEdge <- e.IsBackEdge + g.AddEdge src dummy edge |> ignore + let backEdges = + if edge.IsBackEdge then (dummy, src, edge) :: backEdges else backEdges + let eData, vertices = Map.find k dummies + let dummies = Map.add k (eData, dummy :: vertices) dummies + addDummy g (backEdges, dummies) k dummy dst e (cnt - 1) + +let siftBackEdgesAndPickLongEdges (backEdges, longEdges) src dst edge = + let delta = VisGraph.getLayer dst - VisGraph.getLayer src + if delta > 1 then + (* Backedge in forward direction = Extra edge added in the cycle removal. *) + let backEdges = + if (edge: VisEdge).IsBackEdge then + List.filter (fun (_, _, e) -> e <> edge) backEdges + else backEdges + let longEdges = (src, dst, edge, delta) :: longEdges + backEdges, longEdges + else backEdges, longEdges + +let addDummyNodes vGraph (backEdges, dummies) (src, dst, edge, delta) = + (vGraph: VisGraph).RemoveEdge src dst |> ignore + let k = if (edge: VisEdge).IsBackEdge then dst, src else src, dst + let dummies = Map.add k (edge, []) dummies + let backEdges, dummies = + addDummy vGraph (backEdges, dummies) k src dst edge (delta - 1) + let dummies = + if not edge.IsBackEdge then + let eData, vertices = Map.find k dummies + Map.add k (eData, List.rev vertices) dummies + else dummies + backEdges, dummies + +let assignDummyNodes (vGraph: VisGraph) backEdges = + let backEdges, longEdges = + vGraph.FoldEdge siftBackEdgesAndPickLongEdges (backEdges, []) + longEdges + |> List.fold (addDummyNodes vGraph) (backEdges, Map.empty) + +/// Assign layers to each node. The root node should be layer zero (0). +let assignLayers vGraph backEdges = + kahnAssignLayers vGraph + assignDummyNodes vGraph backEdges diff --git a/src/Visualization/VisBBlock.fs b/src/RearEnd/Visualization/VisBBlock.fs similarity index 97% rename from src/Visualization/VisBBlock.fs rename to src/RearEnd/Visualization/VisBBlock.fs index 05e627bd..ac8ecf65 100644 --- a/src/Visualization/VisBBlock.fs +++ b/src/RearEnd/Visualization/VisBBlock.fs @@ -22,9 +22,9 @@ SOFTWARE. *) -namespace B2R2.Visualization +namespace B2R2.RearEnd.Visualization -open B2R2.BinEssence +open B2R2.MiddleEnd.ControlFlowGraph /// The main vertex type used for visualization. type VisBBlock (blk: BasicBlock, isDummy) = diff --git a/src/Visualization/VisDebug.fs b/src/RearEnd/Visualization/VisDebug.fs similarity index 96% rename from src/Visualization/VisDebug.fs rename to src/RearEnd/Visualization/VisDebug.fs index 8719a382..20c5a832 100644 --- a/src/Visualization/VisDebug.fs +++ b/src/RearEnd/Visualization/VisDebug.fs @@ -22,12 +22,12 @@ SOFTWARE. *) -namespace B2R2.Visualization +namespace B2R2.RearEnd.Visualization #if DEBUG module VisDebug = open System - open B2R2.BinGraph + open B2R2.MiddleEnd.BinGraph let private fs = IO.File.Create ("visualization.log") diff --git a/src/Visualization/VisEdge.fs b/src/RearEnd/Visualization/VisEdge.fs similarity index 95% rename from src/Visualization/VisEdge.fs rename to src/RearEnd/Visualization/VisEdge.fs index 4345d950..214071be 100644 --- a/src/Visualization/VisEdge.fs +++ b/src/RearEnd/Visualization/VisEdge.fs @@ -22,9 +22,9 @@ SOFTWARE. *) -namespace B2R2.Visualization +namespace B2R2.RearEnd.Visualization -open B2R2.BinEssence +open B2R2.MiddleEnd.ControlFlowGraph /// The main edge data type for visualization. type VisEdge (ty) = diff --git a/src/Visualization/VisGraph.fs b/src/RearEnd/Visualization/VisGraph.fs similarity index 96% rename from src/Visualization/VisGraph.fs rename to src/RearEnd/Visualization/VisGraph.fs index 26f37493..fd979c37 100644 --- a/src/Visualization/VisGraph.fs +++ b/src/RearEnd/Visualization/VisGraph.fs @@ -22,10 +22,10 @@ SOFTWARE. *) -namespace B2R2.Visualization +namespace B2R2.RearEnd.Visualization -open B2R2.BinGraph -open B2R2.BinEssence +open B2R2.MiddleEnd.BinGraph +open B2R2.MiddleEnd.ControlFlowGraph open System.Collections.Generic /// The main graph type for visualization. diff --git a/src/Visualization/VisPosition.fs b/src/RearEnd/Visualization/VisPosition.fs similarity index 97% rename from src/Visualization/VisPosition.fs rename to src/RearEnd/Visualization/VisPosition.fs index d87ac3b0..d413ebb0 100644 --- a/src/Visualization/VisPosition.fs +++ b/src/RearEnd/Visualization/VisPosition.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -namespace B2R2.Visualization +namespace B2R2.RearEnd.Visualization /// X-Y position of nodes and edges for visualization. type VisPosition = { diff --git a/src/Visualization/Visualizer.fs b/src/RearEnd/Visualization/Visualizer.fs similarity index 97% rename from src/Visualization/Visualizer.fs rename to src/RearEnd/Visualization/Visualizer.fs index 6d031565..01d70eba 100644 --- a/src/Visualization/Visualizer.fs +++ b/src/RearEnd/Visualization/Visualizer.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module B2R2.Visualization.Visualizer +module B2R2.RearEnd.Visualization.Visualizer let getJSONFromGraph iGraph roots = try diff --git a/src/Utilities/Assembler/B2R2.Utilities.Assembler.fsproj b/src/Utilities/Assembler/B2R2.Utilities.Assembler.fsproj deleted file mode 100644 index 438274d1..00000000 --- a/src/Utilities/Assembler/B2R2.Utilities.Assembler.fsproj +++ /dev/null @@ -1,26 +0,0 @@ - - - - Exe - netcoreapp3.0 - false - false - - - - - - - - - - - - - - - - - - - diff --git a/src/Utilities/Assembler/Main.fs b/src/Utilities/Assembler/Main.fs deleted file mode 100644 index 2aa63377..00000000 --- a/src/Utilities/Assembler/Main.fs +++ /dev/null @@ -1,133 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.Utilities.Assembler - -open B2R2 -open B2R2.Assembler -open B2R2.FrontEnd -open System - -type AssemblerOpts (isa) = - inherit CmdOpts() - - /// Input file path. - member val InputFile = "" with get, set - - /// Input string from command line. - member val InputStr: string = "" with get, set - - /// ISA - member val ISA = isa with get, set - - /// Base address - member val BaseAddress: Addr = 0UL with get, set - - static member private ToThis (opts: CmdOpts) = - match opts with - | :? AssemblerOpts as opts -> opts - | _ -> failwith "Invalid Opts." - - /// "-a" or "--isa" option for specifying ISA. - static member OptISA () = - let cb (opts: #CmdOpts) (arg: string []) = - (AssemblerOpts.ToThis opts).ISA <- ISA.OfString arg.[0]; opts - CmdOpts.New ( descr = "Specify (e.g., x86) from command line", - extra = 1, callback = cb, short = "-a", long= "--isa" ) - - /// "-i" option for specifying an input file. - static member OptInputFile () = - let cb (opts: #CmdOpts) (arg: string []) = - (AssemblerOpts.ToThis opts).InputFile <- arg.[0]; opts - CmdOpts.New ( descr = "Specify an input ", - extra = 1, callback = cb, short = "-i" ) - - /// "-s" option for specifying an input string. - static member OptInputString () = - let cb (opts: #CmdOpts) (arg: string []) = - (AssemblerOpts.ToThis opts).InputStr <- arg.[0]; opts - CmdOpts.New ( descr = "Specify an input from command line", - extra = 1, callback = cb, short = "-s" ) - - /// "-r" or "--base-addr" option for specifying a base address. - static member OptBaseAddr () = - let cb (opts: #CmdOpts) (arg: string []) = - (AssemblerOpts.ToThis opts).BaseAddress <- Convert.ToUInt64 (arg.[0], 16) - opts - CmdOpts.New ( descr = "Specify the base
in hex (default=0)", - extra = 1, callback = cb, short = "-r", long = "--base-addr" ) - -let spec = - [ CmdOpts.New (descr = "[Input Configuration]\n", dummy = true) - - AssemblerOpts.OptInputFile () - AssemblerOpts.OptInputString () - AssemblerOpts.OptISA () - - CmdOpts.New (descr = "\n[Optional Configuration]\n", dummy = true) - - AssemblerOpts.OptBaseAddr () - - CmdOpts.New (descr = "\n[Extra]\n", dummy = true) - - CmdOpts.OptVerbose () - CmdOpts.OptHelp () ] - -let isInvalidCmdLine (opts: AssemblerOpts) = - String.IsNullOrEmpty opts.InputStr && String.IsNullOrEmpty opts.InputFile - -let inline printIfNotEmpty s = match s with "" -> () | _ -> Console.WriteLine s - -let cmdErrExit () = - eprintfn "Either a string or a file should be given.\n\n\ - See assembler --help for more info." - exit 1 - -let initAsmString (opts: AssemblerOpts) = - if opts.InputStr.Length = 0 then IO.File.ReadAllText opts.InputFile - else opts.InputStr - -let private printLine handler (addr, ctxt) bs = - let bCode = (BitConverter.ToString (bs)).Replace ("-", "") - let handler = BinHandler.UpdateCode handler addr bs - let ins = BinHandler.ParseInstr handler ctxt addr - printfn "%08x: %-20s %s" addr bCode (ins.Disasm ()) - addr + uint64 (Array.length bs), ins.NextParsingContext - -let asmMain _ (opts: AssemblerOpts) = - if isInvalidCmdLine opts then cmdErrExit () else () - let handler = BinHandler.Init (opts.ISA) - let ctxt = handler.DefaultParsingContext - let assembler = AsmInterface (opts.ISA, opts.BaseAddress) - initAsmString opts - |> assembler.AssembleBin - |> List.fold (printLine handler) (opts.BaseAddress, ctxt) - |> ignore - -[] -let main args = - let opts = AssemblerOpts (ISA.Init (Arch.IntelX86) Endian.Little) - CmdOpts.ParseAndRun asmMain "" spec opts args - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/Utilities/BinDump/B2R2.Utilities.BinDump.fsproj b/src/Utilities/BinDump/B2R2.Utilities.BinDump.fsproj deleted file mode 100644 index d4eb76de..00000000 --- a/src/Utilities/BinDump/B2R2.Utilities.BinDump.fsproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - Exe - netcoreapp3.0 - false - false - - - - - - - - - - - - - - diff --git a/src/Utilities/BinDump/Main.fs b/src/Utilities/BinDump/Main.fs deleted file mode 100644 index 91362f99..00000000 --- a/src/Utilities/BinDump/Main.fs +++ /dev/null @@ -1,338 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.Utilities.BinDump - -open B2R2 -open B2R2.BinIR -open B2R2.BinFile -open B2R2.FrontEnd -open System - -type DumpMethod = - | Disassemble - | LowUIRLift (* Default *) - -type OptOption = - | NoOpt - | Opt - | OptPar - -type BinDumpOpts (autoDetect, isa) = - inherit CmdOpts() - - /// Input file path. - member val InputFile = "" with get, set - - /// Input string from command line. - member val InputStr: byte [] = [||] with get, set - - /// ISA - member val ISA = isa with get, set - - /// ArchOperationMode - member val ArchOperationMode = ArchOperationMode.NoMode with get, set - - /// Base address - member val BaseAddress: Addr = 0UL with get, set - - /// Whether to show addresses or not - member val ShowAddress = false with get, set - - /// Show symbols or not? - member val ShowSymbols = false with get, set - - /// Discover binary file format or not? - member val AutoDetect = autoDetect with get, set - - /// Disassemble or IR-translate? - member val DumpMethod = LowUIRLift with get, set - - /// Perform basic block optimization or not? - member val DoOptimization = NoOpt with get, set - - static member private ToThis (opts: CmdOpts) = - match opts with - | :? BinDumpOpts as opts -> opts - | _ -> failwith "Invalid Opts." - - /// "-a" or "--isa" option for specifying ISA. - static member OptISA () = - let cb (opts: #CmdOpts) (arg: string []) = - (BinDumpOpts.ToThis opts).ISA <- ISA.OfString arg.[0]; opts - CmdOpts.New ( descr = "Specify (e.g., x86) from command line", - extra = 1, callback = cb, short = "-a", long= "--isa" ) - - /// "-i" option for specifying an input file. - static member OptInputFile () = - let cb (opts: #CmdOpts) (arg: string []) = - (BinDumpOpts.ToThis opts).InputFile <- arg.[0]; opts - CmdOpts.New ( descr = "Specify an input ", - extra = 1, callback = cb, short = "-i" ) - - /// "-s" option for specifying an input string. - static member OptInputString () = - let cb (opts: #CmdOpts) (arg: string []) = - (BinDumpOpts.ToThis opts).InputStr <- ByteArray.ofHexString arg.[0]; opts - CmdOpts.New ( descr = "Specify an input from command line", - extra = 1, callback = cb, short = "-s" ) - - /// "-m" or "--mode" option for specifying ArchOperationMode. - static member OptArchMode () = - let cb (opts: #CmdOpts) (arg: string []) = - (BinDumpOpts.ToThis opts).ArchOperationMode <- - ArchOperationMode.ofString arg.[0] - opts - CmdOpts.New ( - descr = "Specify (e.g., thumb/arm) from cmdline", - extra = 1, callback = cb, short = "-m", long= "--mode" ) - - /// "-r" or "--base-addr" option for specifying a base address. - static member OptBaseAddr () = - let cb (opts: #CmdOpts) (arg: string []) = - (BinDumpOpts.ToThis opts).BaseAddress <- Convert.ToUInt64 (arg.[0], 16) - (BinDumpOpts.ToThis opts).ShowAddress <- true - opts - CmdOpts.New ( descr = "Specify the base
in hex (default=0)", - extra = 1, callback = cb, short = "-r", long = "--base-addr" ) - - /// "--show-addr" option decides whether to show addresses in disassembly. - static member OptShowAddr () = - let cb (opts: #CmdOpts) _ = - (BinDumpOpts.ToThis opts).ShowAddress <- true; opts - CmdOpts.New ( descr = "Show addresses in disassembly", - callback = cb, long = "--show-addr" ) - - static member OptShowSymbols () = - let cb (opts: #CmdOpts) _ = - (BinDumpOpts.ToThis opts).ShowSymbols <- true; opts - CmdOpts.New ( descr = "Show symbols while disassembling binary", - callback = cb, long = "--show-symbols") - - static member OptDisasm () = - let cb (opts: #CmdOpts) _ = - (BinDumpOpts.ToThis opts).DumpMethod <- Disassemble; opts - CmdOpts.New ( descr = "Disassemble binary (linear sweep)", - callback = cb, long = "--disasm") - - static member OptTransIR () = - let cb (opts: #CmdOpts) _ = - (BinDumpOpts.ToThis opts).DumpMethod <- LowUIRLift; opts - CmdOpts.New ( descr = "Translate a binary into an IL (default mode)", - callback = cb, long = "--translate") - - static member OptTransOptimization () = - let cb (opts: #CmdOpts) _ = - (BinDumpOpts.ToThis opts).DoOptimization <- Opt; opts - CmdOpts.New ( descr = "Perform bblock optimization for IL", - callback = cb, long = "--optimize") - - static member OptTransParOptimization () = - let cb (opts: #CmdOpts) _ = - (BinDumpOpts.ToThis opts).DoOptimization <- OptPar; opts - CmdOpts.New ( descr = "Perform parallel bblock optimization for IL", - callback = cb, long = "--par-optimize") - - static member OptRawBinary () = - let cb (opts: BinDumpOpts) _ = - opts.AutoDetect <- false - opts - CmdOpts.New ( descr = "Turn off file format detection", - callback = cb, long = "--raw-binary" ) - -let spec = - [ - CmdOpts.New (descr = "[Input Configuration]\n", dummy = true) - - BinDumpOpts.OptInputFile () - BinDumpOpts.OptInputString () - BinDumpOpts.OptISA () - BinDumpOpts.OptArchMode () - BinDumpOpts.OptRawBinary () - - CmdOpts.New (descr = "\n[Output Configuration]\n", dummy = true) - - BinDumpOpts.OptDisasm () - BinDumpOpts.OptTransIR () - BinDumpOpts.OptShowAddr () - BinDumpOpts.OptShowSymbols () - - CmdOpts.New (descr = "\n[Optional Configuration]\n", dummy = true) - - BinDumpOpts.OptBaseAddr () - BinDumpOpts.OptTransOptimization () - BinDumpOpts.OptTransParOptimization() - - CmdOpts.New (descr = "\n[Extra]\n", dummy = true) - - CmdOpts.OptVerbose () - CmdOpts.OptHelp () - ] - -let initWithFile (opts: BinDumpOpts) = - BinHandler.Init ( - opts.ISA, - opts.ArchOperationMode, - opts.AutoDetect, - opts.BaseAddress, - opts.InputFile - ) - -let initWithBytes (opts: BinDumpOpts) = - BinHandler.Init ( - opts.ISA, - opts.ArchOperationMode, - false, - opts.BaseAddress, - opts.InputStr - ) - -let isInvalidCmdLine (opts: BinDumpOpts) = - Array.isEmpty opts.InputStr && String.IsNullOrEmpty opts.InputFile - -let checkHeaderMismatch hdl = - if hdl.FileInfo.FileFormat = FileFormat.RawBinary then () - else Utils.assertEqual hdl.ISA.WordSize hdl.FileInfo.WordSize - FileFormatMismatchException - -let initHandle (opts: BinDumpOpts) = - if opts.InputStr.Length = 0 then - initWithFile opts |> Utils.tap checkHeaderMismatch - else initWithBytes opts - -let getNextAddr hdl invalidInsAddr = - let invalidInsLen = - match hdl.ISA.Arch with - | Arch.IntelX86 | Arch.IntelX64 -> 1UL - | _ -> 4UL - invalidInsAddr + invalidInsLen - -let printIllegal () = - Console.WriteLine "(illegal)" - -let inline printIfNotEmpty s = match s with "" -> () | _ -> Console.WriteLine s - -let inline parseUntil hdl ctxt sAddr eAddr = - let rec loop hdl ctxt pc acc = - if pc < eAddr then - let res = BinHandler.TryParseInstr hdl ctxt pc - match res with - | Some ins -> - let ctxt = ins.NextParsingContext - loop hdl ctxt (pc + uint64 ins.Length) (res :: acc) - | None -> loop hdl ctxt (getNextAddr hdl pc) (res :: acc) - else List.rev acc - loop hdl ctxt sAddr [] - -let pickNext hdl eAddr untilFn bbFn sAddr = function - | Error (res, nextAddr) when nextAddr = eAddr -> - bbFn res; None - | Ok (_, nextAddr, _) | Error (_, nextAddr) when nextAddr > eAddr -> - untilFn sAddr |> ignore; None - | Ok (res, nextAddr, ctxt) -> bbFn res; Some (nextAddr, ctxt) - | Error (res, nextAddr) -> - bbFn res - printIllegal () - Some (getNextAddr hdl nextAddr, hdl.DefaultParsingContext) - -let printDisasmUntil hdl showAddr showSymbs sAddr eAddr = - let printFn = function - | Some ins -> - BinHandler.DisasmInstr hdl showAddr showSymbs ins |> Console.WriteLine - | None -> printIllegal () - parseUntil hdl hdl.DefaultParsingContext sAddr eAddr |> List.iter printFn - -let printDisasm result = printIfNotEmpty result - -let printBlkDisasm showAddr showSymbs hdl sA eA = - let untilFn sA = printDisasmUntil hdl showAddr showSymbs sA eA - let digest = pickNext hdl eA untilFn printDisasm - let rec loop sA hdl ctxt = - if sA >= eA then () - else - BinHandler.DisasmBBlock hdl ctxt showAddr showSymbs sA - |> digest sA - |> function - | Some (n, ctxt) -> loop n hdl ctxt - | None -> () - loop sA hdl hdl.DefaultParsingContext - -let printLowUIRUntil hdl sAddr eAddr = - let printFn = function - | Some ins -> - BinHandler.LiftInstr hdl ins - |> LowUIR.Pp.stmtsToString - |> Console.WriteLine - | None -> printIllegal () - parseUntil hdl hdl.DefaultParsingContext sAddr eAddr |> List.iter printFn - -let printLowUIR = LowUIR.Pp.stmtsToString >> printIfNotEmpty - -let printBlkLowUIR opt hdl sAddr eAddr = - let untilFn sAddr = printLowUIRUntil hdl sAddr eAddr - let digest = pickNext hdl eAddr untilFn (opt >> printLowUIR) - let rec loop sAddr hdl ctxt = - if sAddr >= eAddr then () - else let r = BinHandler.LiftBBlock hdl ctxt sAddr |> digest sAddr - match r with Some (n, ctxt) -> loop n hdl ctxt | None -> () - loop sAddr hdl hdl.DefaultParsingContext - -let getSectionRanges handle = - let folder acc (section: Section) = - if section.Size > 0UL then section.ToAddrRange () :: acc else acc - handle.FileInfo.GetExecutableSections () - |> Seq.fold folder [] - |> List.sortBy (fun r -> r.Min) - -let getActor action showAddr showSymbs hdl opt = - match action, opt with - | Disassemble, _ -> printBlkDisasm showAddr showSymbs hdl - | LowUIRLift, NoOpt -> printBlkLowUIR (fun x -> x) hdl - | LowUIRLift, Opt -> printBlkLowUIR (BinHandler.Optimize) hdl - | LowUIRLift, OptPar -> Utils.futureFeature () - -let cmdErrExit () = - eprintfn "Either a string or a file should be given.\n\n\ - See bindump --help for more info." - exit 1 - -let dump _ (opts: BinDumpOpts) = - if isInvalidCmdLine opts then cmdErrExit () else () - let handle = initHandle opts - let secRanges = getSectionRanges handle - let action = opts.DumpMethod - let showAddr = opts.ShowAddress - let showSymbs = opts.ShowSymbols - let actor = opts.DoOptimization |> getActor action showAddr showSymbs handle - if secRanges.IsEmpty then () - else - secRanges - |> List.iter (fun sR -> actor (AddrRange.GetMin sR) (AddrRange.GetMax sR)) - -[] -let main args = - let opts = BinDumpOpts (true, ISA.Init (Arch.IntelX86) Endian.Little) - CmdOpts.ParseAndRun dump "" spec opts args - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/Utilities/Core/Utilities.fs b/src/Utilities/Core/Utilities.fs deleted file mode 100644 index 29bbd180..00000000 --- a/src/Utilities/Core/Utilities.fs +++ /dev/null @@ -1,93 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.Utilities - -open B2R2 -open B2R2.FsOptParse -open System - -/// A common set of command-line options used in analyzing binaries. -type CmdOpts () = - /// Verbosity - member val Verbose = false with get, set - - /// Just a wrapper function that instantiate an OptParse.Option object. - static member New<'a> ( descr, ?callback, ?required, ?extra, ?help, - ?short, ?long, ?dummy, ?descrColor ) = - Option<'a> ( descr, - ?callback=callback, - ?required=required, - ?extra=extra, ?help=help, - ?short=short, ?long=long, - ?dummy=dummy, ?descrColor=descrColor ) - - /// "-v" or "--verbose" option turns on the verbose mode. - static member OptVerbose () = - let cb (opts: #CmdOpts) _ = - opts.Verbose <- true; opts - CmdOpts.New ( descr = "Verbose mode", - callback = cb, short = "-v", long = "--verbose" ) - - /// "-h" or "--help" option. - static member OptHelp () = - CmdOpts.New ( descr = "Show this usage", - help = true, short = "-h", long = "--help" ) - - static member private parseCmdOpts spec defaultOpts argv showLogo usageTail = - let termFn () = exit 1 - let prog = Environment.GetCommandLineArgs().[0] - let usageGetter () = - showLogo () - let tail = if String.IsNullOrEmpty usageTail then "" else " " + usageTail - String.Format ("[Usage]{0}{0}dotnet run -- %o{1}", - Environment.NewLine, tail) - try - optParse spec usageGetter prog argv defaultOpts - with - | SpecErr msg -> - eprintfn "Invalid spec: %s" msg - exit 1 - | RuntimeErr msg -> - eprintfn "Invalid command line args given: %s" msg - usagePrint spec prog usageGetter termFn - | e -> - eprintfn "Fatal error: %s" e.Message - usagePrint spec prog usageGetter termFn - - static member private writeIntro () = - Utils.writeB2R2 false - Console.WriteLine (", the Next-Generation Reversing Platform") - Console.WriteLine (Attribution.copyright + Environment.NewLine) - - /// Parse command line arguments, and run the mainFn - static member ParseAndRun mainFn usageTail optSpec (opts: #CmdOpts) args = - let rest, opts = - CmdOpts.parseCmdOpts optSpec opts args CmdOpts.writeIntro usageTail - if opts.Verbose then CmdOpts.writeIntro () else () - try mainFn rest opts; 0 - with e -> eprintfn "Error: %s" e.Message - eprintfn "%s" (if opts.Verbose then e.StackTrace else ""); 1 - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/Utilities/FileViewer/B2R2.Utilities.FileViewer.fsproj b/src/Utilities/FileViewer/B2R2.Utilities.FileViewer.fsproj deleted file mode 100644 index 98895e11..00000000 --- a/src/Utilities/FileViewer/B2R2.Utilities.FileViewer.fsproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - Exe - netcoreapp3.0 - false - false - - - - - - - - - - - - - - - - diff --git a/src/Utilities/FileViewer/Main.fs b/src/Utilities/FileViewer/Main.fs deleted file mode 100644 index f7185df1..00000000 --- a/src/Utilities/FileViewer/Main.fs +++ /dev/null @@ -1,146 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.Utilities.FileViewer.Main - -open B2R2 -open B2R2.BinFile -open B2R2.FrontEnd -open B2R2.Utilities - -let dumpBasic (fi: FileInfo) = - printfn "## Basic Information" - printfn "- Format : %s" <| FileFormat.toString fi.FileFormat - printfn "- Architecture : %s" <| ISA.ArchToString fi.ISA.Arch - printfn "- Endianness : %s" <| Endian.toString fi.ISA.Endian - printfn "- Word size : %d bit" <| WordSize.toRegType fi.ISA.WordSize - printfn "- File type : %s" <| FileInfo.FileTypeToString fi.FileType - printfn "- Entry point : %s" <| FileInfo.EntryPointToString fi.EntryPoint - printfn "" - -let dumpSecurity (fi: FileInfo) = - printfn "## Security Information" - printfn "- Stripped binary : %b" fi.IsStripped - printfn "- DEP (NX) enabled : %b" fi.IsNXEnabled - printfn "- Relocatable (PIE): %b" fi.IsRelocatable - printfn "" - -let dumpSections (fi: FileInfo) addrToString = - printfn "## Section Information" - fi.GetSections () - |> Seq.iteri (fun idx s -> - printfn "%2d. %s:%s [%s]" - idx - (addrToString s.Address) - (addrToString (s.Address + s.Size)) - s.Name) - printfn "" - -let dumpSegments (fi: FileInfo) addrToString = - printfn "## Segment Information" - fi.GetSegments () - |> Seq.iteri (fun idx s -> - printfn "%2d. %s:%s [%s]" - idx - (addrToString s.Address) - (addrToString (s.Address + s.Size)) - (FileInfo.PermissionToString s.Permission)) - printfn "" - -let targetString s = - match s.Target with - | TargetKind.StaticSymbol -> "(s)" - | TargetKind.DynamicSymbol -> "(d)" - | _ -> failwith "Invalid symbol target kind." - -let dumpSymbols (fi: FileInfo) addrToString dumpAll = - let lib s = if System.String.IsNullOrWhiteSpace s then "" else " @ " + s - let name (s: Symbol) = if s.Name.Length > 0 then " " + s.Name else "" - let filterNoType (s: Symbol) = - s.Target = TargetKind.DynamicSymbol - || (s.Kind <> SymbolKind.NoType && s.Name.Length > 0) - printfn "## Symbol Information (s: static / d: dynamic)" - fi.GetSymbols () - |> (fun symbs -> if dumpAll then symbs else Seq.filter filterNoType symbs) - |> Seq.sortBy (fun s -> s.Name) - |> Seq.sortBy (fun s -> s.Address) - |> Seq.sortBy (fun s -> s.Target) - |> Seq.iter (fun s -> - printfn "- %s %s%s%s" - (targetString s) (addrToString s.Address) (name s) (lib s.LibraryName)) - printfn "" - -let dumpRelocs (fi: FileInfo) addrToString = - printfn "## Relocation Information" - fi.GetRelocationSymbols () - |> Seq.sortBy (fun s -> s.Address) - |> Seq.iter (fun r -> - printfn "- (%d) %s: %s%s" - (int r.Kind) - (addrToString r.Address) - r.Name - (if r.LibraryName = "" then "" else " @ " + r.LibraryName)) - printfn "" - -let dumpIfNotEmpty s = - if System.String.IsNullOrEmpty s then "" else "@" + s - -let dumpLinkageTable (fi: FileInfo) addrToString = - printfn "## Linkage Table (PLT -> GOT) Information" - fi.GetLinkageTableEntries () - |> Seq.iter (fun a -> - printfn "- %s -> %s %s%s" - (addrToString a.TrampolineAddress) - (addrToString a.TableAddress) - a.FuncName - (dumpIfNotEmpty a.LibraryName)) - printfn "" - -let dumpFunctions (fi: FileInfo) addrToString = - printfn "## Functions" - fi.GetFunctionSymbols () - |> Seq.iter (fun s -> printfn "- %s: %s" (addrToString s.Address) s.Name) - -let dumpFile (opts: CmdOptions.FileViewerOpts) (filepath: string) = - let hdl = BinHandler.Init (opts.ISA, opts.BaseAddress, filepath) - let fi = hdl.FileInfo - let addrToString = Addr.toString hdl.ISA.WordSize - printfn "# %s" fi.FilePath - printfn "" - dumpBasic fi - dumpSecurity fi - dumpSections fi addrToString - dumpSegments fi addrToString - dumpSymbols fi addrToString opts.Verbose - dumpRelocs fi addrToString - dumpLinkageTable fi addrToString - dumpFunctions fi addrToString - -let dump files opts = - files |> List.iter (dumpFile opts) - -[] -let main args = - let opts = CmdOptions.FileViewerOpts () - CmdOpts.ParseAndRun dump "" CmdOptions.spec opts args diff --git a/src/Utilities/Repl/B2R2.Utilities.Repl.fsproj b/src/Utilities/Repl/B2R2.Utilities.Repl.fsproj deleted file mode 100644 index 4a1b7c51..00000000 --- a/src/Utilities/Repl/B2R2.Utilities.Repl.fsproj +++ /dev/null @@ -1,35 +0,0 @@ - - - - Exe - netcoreapp3.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Visualization/EdgeDrawing.fs b/src/Visualization/EdgeDrawing.fs deleted file mode 100644 index c6d7aba3..00000000 --- a/src/Visualization/EdgeDrawing.fs +++ /dev/null @@ -1,227 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.Visualization.EdgeDrawing - -open B2R2 -open B2R2.BinGraph - -/// The X offset between starting points of two adjacent edges. -let [] private edgeOffsetX = 4.0 - -/// The Y offset between starting points of two adjacent edges. -let [] private edgeOffsetY = 4.0 - -/// The length of the last segment of an edge. This value should be at least -/// less than the half of blockIntervalY. -let [] private lastSegLen = 20.0 - -/// The margin to prevent an overlap between a node and its back edges. -let [] private backEdgeMargin = 10.0 - -let private restoreBackEdge (vGraph: VisGraph) (src, dst, (edge: VisEdge)) = - match vGraph.TryFindEdgeData dst src with - | Some eData -> - if eData.IsBackEdge then - vGraph.RemoveEdge dst src |> ignore - vGraph.AddEdge src dst edge |> ignore - else - vGraph.AddEdge src dst edge |> ignore - | None -> - vGraph.AddEdge src dst edge |> ignore - -let private restoreBackEdges vGraph backEdgeList = - List.iter (restoreBackEdge vGraph) backEdgeList - -let private computeHeight vertices = - let heights = Array.map VisGraph.getHeight vertices - Array.max heights - -let private computeHeightPerLayer vLayout = - Array.map computeHeight vLayout - -let private computeEdgeEndOffset v neighbors map isPred = - let len = Array.length neighbors - neighbors - |> Array.foldi (fun map idx neighbor -> - let xOffset = float idx * edgeOffsetX - float (len - 1) * edgeOffsetX / 2.0 - let yOffset = - if VisGraph.getXPos neighbor < VisGraph.getXPos v then - float idx * edgeOffsetY + lastSegLen - elif VisGraph.getXPos neighbor > VisGraph.getXPos v then - float (len - idx - 1) * edgeOffsetY + lastSegLen - else - lastSegLen - let key = if isPred then (neighbor, v) else (v, neighbor) - Map.add key (xOffset, yOffset) map - ) map - |> fst - -let private computeEdgeEndOffsets vGraph (predEndOffsets, succEndOffsets) v = - let preds = - DiGraph.getPreds vGraph v |> List.sortBy VisGraph.getIndex |> List.toArray - let succs = - DiGraph.getSuccs vGraph v |> List.sortBy VisGraph.getIndex |> List.toArray - computeEdgeEndOffset v preds predEndOffsets true, - computeEdgeEndOffset v succs succEndOffsets false - -let inline private goingUp pY cY = pY > cY - -let inline private goingDown pY cY = pY < cY - -let inline private goingRight pX cX = pX < cX - -let inline private isDummy (v: Vertex) = v.VData.IsDummy - -let private initializeLine p pX pY c cY (pEndOffX, pEndOffY) line = - if goingUp pY cY && isDummy p then - (pX + pEndOffX, pY + pEndOffY) :: line - else - (pX + pEndOffX, pY + pEndOffY) :: (pX + pEndOffX, pY) :: line - -let private extendForward (hPerLayer: _ []) p pX pY _cX cY pEndOff line = - if goingDown pY cY && isDummy p then - let pEndOffX, pEndOffY = pEndOff - let x, y = pX + pEndOffX, pY + pEndOffY - (x, y + hPerLayer.[VisGraph.getLayer p]) :: (x, y) :: line - else line - -let inline private computeHorizontalX v vX vEndOffX toRight = - let width = VisGraph.getWidth v - if toRight then - vX + vEndOffX + width / 2.0 + backEdgeMargin - else - vX + vEndOffX - width / 2.0 - backEdgeMargin - -let private extendHorizontallyForParent p pX pEndOff cX line = - let pEndOffX, _ = pEndOff - let _, prevY = List.head line - if (pX = cX && pEndOffX > 0.0) || goingRight pX cX then - (computeHorizontalX p pX pEndOffX true, prevY) :: line - else - (computeHorizontalX p pX pEndOffX false, prevY) :: line - -let private extendHorizontallyForChild pX c cX cEndOff line = - let cEndOffX, cEndOffY = cEndOff - let _, prevY = List.head line - if goingRight pX cX then - (computeHorizontalX c cX cEndOffX false, prevY + cEndOffY) :: line - else - (computeHorizontalX c cX cEndOffX true, prevY + cEndOffY) :: line - -let private extendBackward hPerLayer p pX pY pEndOff c cX cY cEndOff line = - if goingUp pY cY then - if not (isDummy p) then - let line = extendHorizontallyForParent p pX pEndOff cX line - let prevX, _ = List.head line - let height = (hPerLayer: float []).[VisGraph.getLayer p] - (prevX, pY - height - backEdgeMargin) :: line - elif not (isDummy c) then - let line = extendHorizontallyForChild pX c cX cEndOff line - let prevX, _ = List.head line - let height = hPerLayer.[VisGraph.getLayer c] - (prevX, cY + height + backEdgeMargin) :: line - else line - else line - -let private finalizeLine p pX pY c cX cY (cEndOffX, cEndOffY) line = - if isDummy c then line - else - let lastX, seLastY = cX + cEndOffX, cY - cEndOffY - [ - yield (lastX, cY) - yield (lastX, seLastY) - if goingUp pY cY then - let extX = computeHorizontalX c cX cEndOffX (not (goingRight pX cX)) - if p = c then yield (lastX, cY); yield (lastX, seLastY); yield! line - elif not (isDummy p) then - let prevY = List.head line |> snd - yield (extX, seLastY); yield (extX, prevY); yield! line - else yield (extX, seLastY); yield! line - else yield! line - ] - -let private buildLine hPerLayer p pEndOff c cEndOff = - let pX = VisGraph.getXPos p + VisGraph.getWidth p / 2.0 - let pY = VisGraph.getYPos p + VisGraph.getHeight p - let cX = VisGraph.getXPos c + VisGraph.getWidth c / 2.0 - let cY = VisGraph.getYPos c - initializeLine p pX pY c cY pEndOff [] - |> extendForward hPerLayer p pX pY cX cY pEndOff - |> extendBackward hPerLayer p pX pY pEndOff c cX cY cEndOff - |> finalizeLine p pX pY c cX cY cEndOff - -let private drawEdge vGraph hPerLayer predEndOffsets succEndOffsets p c _ = - let pEndOff = Map.find (p, c) succEndOffsets - let cEndOff = Map.find (p, c) predEndOffsets - let eData = (vGraph: VisGraph).FindEdgeData p c - let line = buildLine hPerLayer p pEndOff c cEndOff |> List.rev - eData.Points <- line |> List.map (fun (x,y) -> { X = x; Y = y }) - -let rec private removeDummyLoop (vGraph: VisGraph) src c points = function - | p :: lst -> - let eData = vGraph.FindEdgeData p c - vGraph.RemoveEdge p c |> ignore - removeDummyLoop vGraph src p (eData.Points @ points) lst - | [] -> - let eData = vGraph.FindEdgeData src c - vGraph.RemoveEdge src c |> ignore - eData.Points @ points - -let private makeSmooth isBack points = - let rec loop acc prev = function - | [] -> acc - | h1 :: h2 :: [] -> List.rev (h2 :: h1 :: acc) - | (hd: VisPosition) :: tl -> - match prev with - | None -> loop (hd :: acc) (Some hd.Y) tl - | Some p -> - if (isBack && p >= hd.Y) || (not isBack && p <= hd.Y) then - loop (hd :: acc) (Some hd.Y) tl - else loop acc prev tl - match points with - | hd1 :: hd2 :: rest -> - hd1 :: hd2 :: loop [] None rest - | _ -> points - -let private removeDummy vGraph (src, dst) ((edge: VisEdge), dummies) = - let points = - removeDummyLoop vGraph src dst [] dummies |> makeSmooth edge.IsBackEdge - let newEdge = VisEdge (edge.Type) - newEdge.IsBackEdge <- edge.IsBackEdge - newEdge.Points <- points - vGraph.AddEdge src dst newEdge |> ignore - dummies - |> List.iter (fun (v: Vertex<_>) -> vGraph.RemoveVertex v |> ignore) - -let private removeDummies (vGraph: VisGraph) dummyMap = - Map.iter (removeDummy vGraph) dummyMap - -let drawEdges (vGraph: VisGraph) vLayout backEdgeList dummyMap = - restoreBackEdges vGraph backEdgeList - let hPerLayer = computeHeightPerLayer vLayout - let predEndOffsets, succEndOffsets = - vGraph.FoldVertex (computeEdgeEndOffsets vGraph) (Map.empty, Map.empty) - vGraph.IterEdge (drawEdge vGraph hPerLayer predEndOffsets succEndOffsets) - removeDummies vGraph dummyMap diff --git a/src/Visualization/LayerAssignment.fs b/src/Visualization/LayerAssignment.fs deleted file mode 100644 index 092ec00b..00000000 --- a/src/Visualization/LayerAssignment.fs +++ /dev/null @@ -1,166 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.Visualization.LayerAssignment - -open B2R2.BinGraph - -let assignLayerFromSucc vGraph v = - let succs = VisGraph.getSuccs vGraph v - match succs with - | [] -> VisGraph.setLayer v 0 - | succs -> - let succLayers = List.map VisGraph.getLayer succs - VisGraph.setLayer v <| List.max succLayers + 1 - -let adjustLayerByMax maxLayer v = - VisGraph.setLayer v <| maxLayer - VisGraph.getLayer v - -let adjustLayer topoOrdered = - let maxLayer = Array.map VisGraph.getLayer topoOrdered |> Array.max - Array.iter (adjustLayerByMax maxLayer) topoOrdered - -let longestPathAssignLayers vGraph root = - let _, orderMap = - Traversal.foldTopologically vGraph [root] (fun (cnt, map) v -> - cnt + 1, Map.add v cnt map) (0, Map.empty) - let topoOrdered = Array.zeroCreate <| vGraph.GetSize () - Map.iter (fun v i -> Array.set topoOrdered i v) orderMap - let topoOrdered = Array.rev topoOrdered - Array.iter (assignLayerFromSucc vGraph) topoOrdered - adjustLayer topoOrdered - -let rec promote vGraph (layerArr: int []) v = - let preds = VisGraph.getPreds vGraph v - let succs = VisGraph.getSuccs vGraph v - let dummyDiff, layerArr = List.fold (promotePred vGraph v) (0, layerArr) preds - layerArr.[v.GetID ()] <- layerArr.[v.GetID ()] - 1 - dummyDiff - List.length preds + List.length succs, layerArr - -and promotePred vGraph v (dummyDiff, layerArr) p = - // Check only immediate predecessors - if layerArr.[p.GetID ()] = layerArr.[v.GetID ()] - 1 then - let dummyDiff_, layerArr = promote vGraph layerArr p - dummyDiff + dummyDiff_, layerArr - else dummyDiff, layerArr - -let rec promoteVerticesLoop (vGraph: VisGraph) root layerArr backUp = - let promotion, layerArr, _ = - let folder (acc, layerArr, backUp) v = - if List.length <| VisGraph.getPreds vGraph v > 0 then - let promotion, layerArr = promote vGraph layerArr v - // If promotion is negative, we preserve the result - if promotion < 0 then acc + 1, layerArr, Array.copy layerArr - // otherwise, restore previous layout - else acc, backUp, Array.copy backUp - else acc, layerArr, backUp - Traversal.foldPreorder vGraph root folder (0, layerArr, backUp) - // If there exists at least one vertex promoted, this process should be done - // one more time - if promotion <> 0 then - promoteVerticesLoop vGraph root layerArr <| Array.copy layerArr - else layerArr - -let promoteVertices (vGraph: VisGraph) root = - let folder (layerArr: int []) (v: Vertex) = - layerArr.[v.GetID ()] <- VisGraph.getLayer v; layerArr - let layerArr = Array.zeroCreate (vGraph.GetSize ()) - let layerArr = vGraph.FoldVertex folder layerArr - let layerArr = promoteVerticesLoop vGraph root layerArr <| Array.copy layerArr - let minLayer = Array.min layerArr - // Set layer from the result of vertex promotion - Array.iteri (fun id layer -> - VisGraph.setLayer (vGraph.FindVertexByID id) (layer - minLayer)) layerArr - -let assignLayerFromPred (vGraph: VisGraph) vData = - let v = vGraph.FindVertexByData vData - let preds = VisGraph.getPreds vGraph v - match preds with - | [] -> VisGraph.setLayer v 0 - | preds -> - let predLayers = List.map VisGraph.getLayer preds - VisGraph.setLayer v <| List.max predLayers + 1 - -let kahnAssignLayers (vGraph: VisGraph) = - Traversal.foldTopologically vGraph [] (fun acc v -> v.VData :: acc) [] - |> List.rev - |> List.iter (assignLayerFromPred vGraph) - -let rec addDummy (g: VisGraph) (backEdges, dummies) k (src: Vertex<_>) (dst: Vertex<_>) (e: VisEdge) cnt = - if cnt = 0 then - let edge = VisEdge (e.Type) - edge.IsBackEdge <- e.IsBackEdge - g.AddEdge src dst edge |> ignore - let backEdges = - if edge.IsBackEdge then (dst, src, edge) :: backEdges else backEdges - backEdges, dummies - else - let vNode = VisBBlock (src.VData, true) - let dummy, _ = g.AddVertex (vNode) - VisGraph.setLayer dummy <| VisGraph.getLayer src + 1 - let edge = VisEdge (e.Type) - edge.IsBackEdge <- e.IsBackEdge - g.AddEdge src dummy edge |> ignore - let backEdges = - if edge.IsBackEdge then (dummy, src, edge) :: backEdges else backEdges - let eData, vertices = Map.find k dummies - let dummies = Map.add k (eData, dummy :: vertices) dummies - addDummy g (backEdges, dummies) k dummy dst e (cnt - 1) - -let chooseBackEdgesWithDummy (backEdges, withDummy) src dst edge = - let delta = VisGraph.getLayer dst - VisGraph.getLayer src - if delta > 1 then - let backEdges = - if (edge: VisEdge).IsBackEdge then - List.filter (fun (_, _, e) -> e <> edge) backEdges - else backEdges - let withDummy = (src, dst, edge, delta) :: withDummy - backEdges, withDummy - else backEdges, withDummy - -let addDummyNodes vGraph (backEdges, dummies) (src, dst, edge, delta) = - (vGraph: VisGraph).RemoveEdge src dst |> ignore - let k = if (edge: VisEdge).IsBackEdge then dst, src else src, dst - let dummies = Map.add k (edge, []) dummies - let backEdges, dummies = - addDummy vGraph (backEdges, dummies) k src dst edge (delta - 1) - let dummies = - if edge.IsBackEdge then - let eData, vertices = Map.find k dummies - Map.add k (eData, List.rev vertices) dummies - else dummies - backEdges, dummies - -let assignDummyNodes (vGraph: VisGraph) backEdgeList = - let backEdgeList, withDummy = - vGraph.FoldEdge (chooseBackEdgesWithDummy) (backEdgeList, []) - withDummy - |> List.fold (addDummyNodes vGraph) (backEdgeList, Map.empty) - -let assignLayers vGraph backEdgeList = - /// XXX: We'll make an option argument to select layer assignment algorithm - /// longestPathAssignLayers vGraph - /// promoteVertices vGraph root - kahnAssignLayers vGraph - assignDummyNodes vGraph backEdgeList