| 1232 | } |
| 1233 | |
| 1234 | void Decoder::AddBranchTarget(uint64_t Target) { |
| 1235 | if (VisitedBlocks.contains(Target)) { |
| 1236 | return; |
| 1237 | } |
| 1238 | |
| 1239 | auto BlockSuccIt = std::lower_bound(BlockInfo.Blocks.begin(), BlockInfo.Blocks.end(), Target, |
| 1240 | [](const auto& a, uint64_t Address) { return a.Entry < Address; }); |
| 1241 | |
| 1242 | LOGMAN_THROW_A_FMT(BlockSuccIt == BlockInfo.Blocks.end() || BlockSuccIt->Entry != Target, "unexpected"); |
| 1243 | |
| 1244 | if (BlockSuccIt != BlockInfo.Blocks.begin()) { |
| 1245 | auto BlockIt = std::prev(BlockSuccIt); |
| 1246 | if (BlockIt->Entry + BlockIt->Size > Target) { |
| 1247 | uint64_t SplitIdx = 0; |
| 1248 | uint64_t SplitAddr = BlockIt->Entry; |
| 1249 | // Find the instruction boundary of the split |
| 1250 | for (; SplitIdx < BlockIt->NumInstructions && SplitAddr < Target; SplitIdx++) { |
| 1251 | SplitAddr += BlockIt->DecodedInstructions[SplitIdx].InstSize; |
| 1252 | } |
| 1253 | uint64_t SplitOffset = SplitAddr - BlockIt->Entry; |
| 1254 | |
| 1255 | LOGMAN_THROW_A_FMT(SplitIdx != 0, "unexpected"); |
| 1256 | |
| 1257 | if (SplitAddr == Target) { |
| 1258 | // Split at the boundary |
| 1259 | DecodedBlocks SplitBlock { |
| 1260 | .Entry = SplitAddr, |
| 1261 | .Size = BlockIt->Size - SplitOffset, |
| 1262 | .NumInstructions = BlockIt->NumInstructions - SplitIdx, |
| 1263 | .DecodedInstructions = BlockIt->DecodedInstructions + SplitIdx, |
| 1264 | .BlockStatus = BlockIt->BlockStatus, |
| 1265 | }; |
| 1266 | |
| 1267 | BlockIt->Size = SplitOffset; |
| 1268 | BlockIt->NumInstructions = SplitIdx; |
| 1269 | |
| 1270 | BlockInfo.Blocks.insert(BlockSuccIt, SplitBlock); |
| 1271 | } // else misaligned, leave as a branch out of the block |
| 1272 | |
| 1273 | // If we split a block then the target has already been visited as part of that, if it was |
| 1274 | // misaligned the jump will just leave the multiblock, mark it as visited to avoid running |
| 1275 | // this code path again and just bail out early. |
| 1276 | VisitedBlocks.insert(Target); |
| 1277 | return; |
| 1278 | } |
| 1279 | } |
| 1280 | |
| 1281 | CurrentBlockTargets.insert(Target); |
| 1282 | if (Target >= DecodeInst->PC + DecodeInst->InstSize && Target < NextBlockStartAddress) { |
| 1283 | NextBlockStartAddress = Target; |
| 1284 | } |
| 1285 | } |
| 1286 | |
| 1287 | const uint8_t* Decoder::AdjustAddrForSpecialRegion(const uint8_t* _InstStream, uint64_t EntryPoint, uint64_t RIP) { |
| 1288 | constexpr uint64_t VSyscall_Base = 0xFFFF'FFFF'FF60'0000ULL; |