bool Jit::DescribeCodePtr(const u8 *ptr, std::string &name) { u32 jitAddr = blocks.GetAddressFromBlockPtr(ptr); // Returns 0 when it's valid, but unknown. if (jitAddr == 0) name = "UnknownOrDeletedBlock"; else if (jitAddr != (u32)-1) { char temp[1024]; const std::string label = symbolMap.GetDescription(jitAddr); if (!label.empty()) snprintf(temp, sizeof(temp), "%08x_%s", jitAddr, label.c_str()); else snprintf(temp, sizeof(temp), "%08x", jitAddr); name = temp; } else if (asm_.IsInSpace(ptr)) name = "RunLoopUntil"; else if (thunks.IsInSpace(ptr)) name = "Thunk"; else if (safeMemFuncs.IsInSpace(ptr)) name = "JitSafeMem"; else if (IsInSpace(ptr)) name = "Unknown"; // Not anywhere in jit, then. else return false; // If we got here, one of the above cases matched. return true; }
bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx) { u8* codePtr = reinterpret_cast<u8*>(ctx->CTX_PC); if (!IsInSpace(codePtr)) return false; // this will become a regular crash real soon after this auto it = m_back_patch_info.find(codePtr); if (it == m_back_patch_info.end()) { PanicAlert("BackPatch: no register use entry for address %p", codePtr); return false; } TrampolineInfo& info = it->second; u8* exceptionHandler = nullptr; if (jo.memcheck) { auto it2 = m_exception_handler_at_loc.find(codePtr); if (it2 != m_exception_handler_at_loc.end()) exceptionHandler = it2->second; } // In the trampoline code, we jump back into the block at the beginning // of the next instruction. The next instruction comes immediately // after the backpatched operation, or BACKPATCH_SIZE bytes after the start // of the backpatched operation, whichever comes last. (The JIT inserts NOPs // into the original code if necessary to ensure there is enough space // to insert the backpatch jump.) js.generatingTrampoline = true; js.trampolineExceptionHandler = exceptionHandler; // Generate the trampoline. const u8* trampoline = trampolines.GenerateTrampoline(info); js.generatingTrampoline = false; js.trampolineExceptionHandler = nullptr; u8* start = info.start; // Patch the original memory operation. XEmitter emitter(start); emitter.JMP(trampoline, true); // NOPs become dead code const u8* end = info.start + info.len; for (const u8* i = emitter.GetCodePtr(); i < end; ++i) emitter.INT3(); // Rewind time to just before the start of the write block. If we swapped memory // before faulting (eg: the store+swap was not an atomic op like MOVBE), let's // swap it back so that the swap can happen again (this double swap isn't ideal but // only happens the first time we fault). if (info.nonAtomicSwapStoreSrc != Gen::INVALID_REG) { u64* ptr = ContextRN(ctx, info.nonAtomicSwapStoreSrc); switch (info.accessSize << 3) { case 8: // No need to swap a byte break; case 16: *ptr = Common::swap16(static_cast<u16>(*ptr)); break; case 32: *ptr = Common::swap32(static_cast<u32>(*ptr)); break; case 64: *ptr = Common::swap64(static_cast<u64>(*ptr)); break; default: _dbg_assert_(DYNA_REC, 0); break; } } // This is special code to undo the LEA in SafeLoadToReg if it clobbered the address // register in the case where reg_value shared the same location as opAddress. if (info.offsetAddedToAddress) { u64* ptr = ContextRN(ctx, info.op_arg.GetSimpleReg()); *ptr -= static_cast<u32>(info.offset); } ctx->CTX_PC = reinterpret_cast<u64>(trampoline); return true; }
void Client::Killed(Damage &fatal_blow) { DynamicSystemEntity::Killed(fatal_blow); if(GetShip()->typeID() == itemTypeCapsule) { //we have been pod killed... off we go. //TODO: destroy all implants //TODO: send them back to their clone. m_system->RemoveClient(this); } else { //our ship has been destroyed. Off to our capsule. //We are currently not keeping our real capsule around in the DB, so we need to make a new one. //m_system->bubbles.Remove(this, true); std::string capsule_name = GetName(); capsule_name += "'s Capsule"; ItemData idata( itemTypeCapsule, GetCharacterID(), GetLocationID(), flagAutoFit, capsule_name.c_str() ); ShipRef capsule = m_services.item_factory.SpawnShip(idata); if( !capsule ) { codelog(CLIENT__ERROR, "Failed to create capsule for character '%s'", GetName()); //what to do? return; } ShipRef dead_ship = GetShip(); //grab a ship ref to ensure that nobody else nukes it first. //ok, nothing can fail now, we need have our capsule, make the transition. //put the capsule where the ship was capsule->Relocate(dead_ship->position()); //move it out of the way dead_ship->Move(this->GetLocationID(), (EVEItemFlags)flagNone, true ); //this updates m_self and manages destiny updates as needed. BoardShip((ShipRef)capsule); m_shipId = capsule->itemID(); if (IsInSpace()) mSession.SetInt("shipid", capsule->itemID() ); //This sends the RemoveBall for the old ship. //kill off the old ship. //TODO: figure out anybody else which may be referencing this ship... dead_ship->Delete(); //remove from the DB. } }